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;