From 8184d71aa68169b19f42c832f22ad838eb193a6d Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 21 Oct 2023 08:13:22 +0200 Subject: [PATCH] Removing the remaining unnecessary files that should not have been committed. --- src/codegen/codegen_ops_x86-64 - Cópia.h | 5963 ---------------------- src/cpu/codegen_timing_p6 - Cópia.c | 2162 -------- src/cpu/error_log.txt | 29 - src/cpu/gcc_check.sh | 1 - src/device/serial - Cópia.c | 1071 ---- src/include/86box/serial - Cópia.h | 150 - src/include/86box/timer - Cópia.h | 194 - src/include/86box/vid_mda - Cópia.h | 67 - src/timer - Cópia.c | 242 - src/video/vid_cga - Cópia.c | 701 --- src/video/vid_mda - Cópia.c | 519 -- src/video/vid_oak_oti - Cópia.c | 738 --- 12 files changed, 11837 deletions(-) delete mode 100644 src/codegen/codegen_ops_x86-64 - Cópia.h delete mode 100644 src/cpu/codegen_timing_p6 - Cópia.c delete mode 100644 src/cpu/error_log.txt delete mode 100644 src/cpu/gcc_check.sh delete mode 100644 src/device/serial - Cópia.c delete mode 100644 src/include/86box/serial - Cópia.h delete mode 100644 src/include/86box/timer - Cópia.h delete mode 100644 src/include/86box/vid_mda - Cópia.h delete mode 100644 src/timer - Cópia.c delete mode 100644 src/video/vid_cga - Cópia.c delete mode 100644 src/video/vid_mda - Cópia.c delete mode 100644 src/video/vid_oak_oti - Cópia.c diff --git a/src/codegen/codegen_ops_x86-64 - Cópia.h b/src/codegen/codegen_ops_x86-64 - Cópia.h deleted file mode 100644 index 63c0a5c35..000000000 --- a/src/codegen/codegen_ops_x86-64 - Cópia.h +++ /dev/null @@ -1,5963 +0,0 @@ -/*Register allocation : - R8-R15 - emulated registers -*/ -#include - -#define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 - -#define IS_32_ADDR(x) !(((uintptr_t) x) & 0xffffffff00000000) - -static __inline int -find_host_xmm_reg(void) -{ - int c; - for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) { - if (host_reg_xmm_mapping[c] == -1) - break; - } - - if (c == HOST_REG_XMM_END) - fatal("Out of host XMM regs!\n"); - return c; -} -static __inline void -call(codeblock_t *block, uintptr_t func) -{ - intptr_t diff = (intptr_t) (func - (uintptr_t) &block->data[block_pos + 5]); - - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - if (diff >= -0x80000000LL && diff < 0x7fffffffLL) { - addbyte(0xE8); /*CALL*/ - addlong((uint32_t) diff); - } else { - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); - } -} - -static __inline void -call_long(uintptr_t func) -{ - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); -} - -static __inline void -load_param_1_32(codeblock_t *block, uint32_t param) -{ -#if _WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif - addlong(param); -} -static __inline void -load_param_1_reg_32(int reg) -{ -#if _WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc0 | REG_ECX | (reg << 3)); -#else - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc0 | REG_EDI | (reg << 3)); -#endif -} -#if 0 -static __inline void load_param_1_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); -# if _WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -# else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -# endif - addquad(param); -} -#endif - -static __inline void -load_param_2_32(codeblock_t *block, uint32_t param) -{ -#if _WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ -#else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ -#endif - addlong(param); -} -static __inline void -load_param_2_reg_32(int reg) -{ -#if _WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDX, EAX*/ - addbyte(0xc0 | REG_EDX | (reg << 3)); -#else - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV ESI, EAX*/ - addbyte(0xc0 | REG_ESI | (reg << 3)); -#endif -} -static __inline void -load_param_2_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); -#if _WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ -#else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ -#endif - addquad(param); -} -static __inline void -load_param_2_reg_64(int reg) -{ - if (reg & 8) { -#if _WIN64 - addbyte(0x4c); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#else - addbyte(0x4c); /*MOVL ESI,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); -#endif - } else { -#if _WIN64 - addbyte(0x48); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#else - addbyte(0x48); /*MOVL ESI,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); -#endif - } -} - -static __inline void -load_param_3_reg_32(int reg) -{ - if (reg & 8) { -#if _WIN64 - addbyte(0x45); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x44); /*MOV EDX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | (reg << 3)); -#endif - } else { -#if _WIN64 - addbyte(0x41); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x90); - addbyte(0x89); /*MOV EDX, reg*/ - addbyte(0xc0 | REG_EDX | (reg << 3)); -#endif - } -} -static __inline void -load_param_3_reg_64(int reg) -{ - if (reg & 8) { -#if _WIN64 - addbyte(0x4d); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x4c); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#endif - } else { -#if _WIN64 - addbyte(0x49); /*MOVL R8,reg*/ - addbyte(0x89); - addbyte(0xc0 | ((reg & 7) << 3)); -#else - addbyte(0x48); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); -#endif - } -} - -static __inline void -CALL_FUNC(uintptr_t func) -{ - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); -} - -static __inline void -RELEASE_REG(int host_reg) -{ -} - -static __inline int -LOAD_REG_B(int reg) -{ - int host_reg = reg & 3; - - if (!codegen_reg_loaded[reg & 3]) { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[host_reg & 3].b)); - } - - codegen_reg_loaded[reg & 3] = 1; - - if (reg & 4) - return host_reg | 0x18; - - return host_reg | 8; -} -static __inline int -LOAD_REG_W(int reg) -{ - int host_reg = reg; - - if (!codegen_reg_loaded[reg & 7]) { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].w)); - } - - codegen_reg_loaded[reg & 7] = 1; - - return host_reg | 8; -} -static __inline int -LOAD_REG_L(int reg) -{ - int host_reg = reg; - - if (!codegen_reg_loaded[reg & 7]) { - addbyte(0x44); /*MOVZX W[reg],host_reg*/ - addbyte(0x8b); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); - } - - codegen_reg_loaded[reg & 7] = 1; - - return host_reg | 8; -} - -static __inline int -LOAD_REG_IMM(uint32_t imm) -{ - int host_reg = REG_EBX; - - addbyte(0xb8 | REG_EBX); /*MOVL EBX, imm*/ - addlong(imm); - - return host_reg; -} - -static __inline void -STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) -{ - int dest_reg = LOAD_REG_L(guest_reg & 3) & 7; - - if (guest_reg & 4) { - if (host_reg & 8) { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - } else if (host_reg & 3) { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - } - if (host_reg & 0x10) { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } else { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(0x08); - } - addbyte(0x66); /*AND dest_reg, 0x00ff*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | dest_reg); - addword(0x00ff); - addbyte(0x66); /*OR dest_reg, AX*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | dest_reg); - addbyte(0x66); /*MOVW regs[guest_reg].w, dest_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (dest_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].w)); - } else { - if (host_reg & 8) { - if (host_reg & 0x10) { - addbyte(0x66); /*MOV AX, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 3) << 3)); - addbyte(0x88); /*MOV AL, AH*/ - addbyte(0xe0); - addbyte(0x41); /*MOV dest_reg, AL*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7)); - addbyte(0x88); /*MOVB regs[reg].b, AH*/ - addbyte(0x65); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } else { - addbyte(0x45); /*MOVB dest_reg, host_reg*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); - addbyte(0x44); /*MOVB regs[guest_reg].b, host_reg*/ - addbyte(0x88); - addbyte(0x45 | ((host_reg & 3) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - } else { - if (host_reg & 0x10) { - addbyte(0xc1); /*SHR host_reg, 8*/ - addbyte(0xe8 | (host_reg & 7)); - addbyte(8); - } - addbyte(0x41); /*MOVB dest_reg, host_reg*/ - addbyte(0x88); - addbyte(0xc0 | (dest_reg & 7) | ((host_reg & 7) << 3)); - addbyte(0x88); /*MOVB regs[guest_reg].b, host_reg*/ - addbyte(0x45 | ((host_reg & 3) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 3].b)); - } - } -} -static __inline void -STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) -{ - int dest_reg = LOAD_REG_L(guest_reg & 7) & 7; - - if (host_reg & 8) { - addbyte(0x66); /*MOVW guest_reg, host_reg*/ - addbyte(0x45); - addbyte(0x89); - addbyte(0xc0 | dest_reg | ((host_reg & 7) << 3)); - addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].w)); - } else { - addbyte(0x66); /*MOVW guest_reg, host_reg*/ - addbyte(0x41); - addbyte(0x89); - addbyte(0xc0 | dest_reg | (host_reg << 3)); - addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].w)); - } -} -static __inline void -STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) -{ - if (host_reg & 8) { - addbyte(0x45); /*MOVL guest_reg, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | guest_reg | (host_reg << 3)); - addbyte(0x44); /*MOVL regs[guest_reg].l, host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].l)); - } else { - addbyte(0x41); /*MOVL guest_reg, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | guest_reg | (host_reg << 3)); - addbyte(0x89); /*MOVL regs[guest_reg].l, host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[guest_reg & 7].l)); - } -} - -static __inline void -STORE_REG_B_RELEASE(int host_reg) -{ - if (host_reg & 0x10) { - addbyte(0x66); /*MOVW [reg],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].w)); - } else { - addbyte(0x44); /*MOVB [reg],host_reg*/ - addbyte(0x88); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].b)); - } -} -static __inline void -STORE_REG_W_RELEASE(int host_reg) -{ - addbyte(0x66); /*MOVW [reg],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].w)); -} -static __inline void -STORE_REG_L_RELEASE(int host_reg) -{ - addbyte(0x44); /*MOVL [reg],host_reg*/ - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].l)); -} - -static __inline void -STORE_IMM_REG_B(int reg, uint8_t val) -{ - if (reg & 4) { - int host_reg = LOAD_REG_W(reg & 3) & 7; - addbyte(0x66); /*AND host_reg, 0x00ff*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | host_reg); - addword(0x00ff); - addbyte(0x66); /*OR host_reg, val << 8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xc8 | host_reg); - addword(val << 8); - addbyte(0x66); /*MOVW host_reg, regs[host_reg].w*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte(cpu_state_offset(regs[reg & 3].w)); - } else { - addbyte(0x41); /*MOVB reg, imm*/ - addbyte(0xb0 | reg); - addbyte(val); - addbyte(0x44); /*MOVB reg, regs[reg].b*/ - addbyte(0x88); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].b)); - } -} -static __inline void -STORE_IMM_REG_W(int reg, uint16_t val) -{ - addbyte(0x66); /*MOVW reg, imm*/ - addbyte(0x41); - addbyte(0xb8 | reg); - addword(val); - addbyte(0x66); /*MOVW reg, regs[reg].w*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].w)); -} -static __inline void -STORE_IMM_REG_L(int reg, uint32_t val) -{ - addbyte(0x41); /*MOVL reg, imm*/ - addbyte(0xb8 | reg); - addlong(val); - addbyte(0x44); /*MOVL reg, regs[reg].l*/ - addbyte(0x89); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); -} - -static __inline void -STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) -{ - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x45); - addbyte(addr - (uintptr_t) &cpu_state - 128); - addlong(val); - } else if (addr < 0x100000000) { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x04); - addbyte(0x25); - addlong(addr); - addlong(val); - } else { - addbyte(0x48); /*MOV ESI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad(addr); - addbyte(0xc7); /*MOVL [ESI], val*/ - addbyte(0x00 | REG_ESI); - addlong(val); - } -} - -static x86seg * -FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; - - if (!mod && rm == 6) { - addbyte(0xb8); /*MOVL EAX, imm*/ - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } else { - int base_reg = 0; - int index_reg = 0; - - switch (rm) { - case 0: - case 1: - case 7: - base_reg = LOAD_REG_W(REG_BX); - break; - case 2: - case 3: - case 6: - base_reg = LOAD_REG_W(REG_BP); - break; - case 4: - base_reg = LOAD_REG_W(REG_SI); - break; - case 5: - base_reg = LOAD_REG_W(REG_DI); - break; - } - if (!(rm & 4)) { - if (rm & 1) - index_reg = LOAD_REG_W(REG_DI); - else - index_reg = LOAD_REG_W(REG_SI); - } - base_reg &= 7; - index_reg &= 7; - - switch (mod) { - case 0: - if (rm & 4) { - addbyte(0x41); /*MOVZX EAX, base_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xc0 | base_reg); - } else { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte(0); - } else { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3)); - } - } - break; - case 1: - if (rm & 4) { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - } else { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3)); - addbyte((fetchdat >> 8) & 0xff); - } - (*op_pc)++; - break; - case 2: - if (rm & 4) { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong((fetchdat >> 8) & 0xffff); - } else { - addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3)); - addlong((fetchdat >> 8) & 0xffff); - } - (*op_pc) += 2; - break; - } - if (mod || !(rm & 4)) { - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - } - - if (mod1seg[rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; -} -static x86seg * -FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; - uint32_t new_eaaddr; - - if (rm == 4) { - uint8_t sib = fetchdat >> 8; - int base_reg = -1; - int index_reg = -1; - - (*op_pc)++; - - if (mod || (sib & 7) != 5) - base_reg = LOAD_REG_L(sib & 7) & 7; - - if (((sib >> 3) & 7) != 4) - index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; - - if (index_reg == -1) { - switch (mod) { - case 0: - if ((sib & 7) == 5) { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOV EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } else { - addbyte(0x44); /*MOV EAX, base_reg*/ - addbyte(0x89); - addbyte(0xc0 | (base_reg << 3)); - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) { - addbyte(0x44); - addbyte(0x24); - } else { - addbyte(0x40 | base_reg); - } - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg*/ - addbyte(0x41); - addbyte(0x8d); - if (base_reg == 4) { - addbyte(0x84); - addbyte(0x24); - } else { - addbyte(0x80 | base_reg); - } - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } - } else { - switch (mod) { - case 0: - if ((sib & 7) == 5) { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - if (sib >> 6) { - addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ - addbyte(0x42); - addbyte(0x8d); - addbyte(0x04); - addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); - addlong(new_eaaddr); - } else { - addbyte(0x67); /*LEA EAX, imm32+index_reg*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | index_reg); - addlong(new_eaaddr); - } - (*op_pc) += 4; - } else { - addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - if (base_reg == 5) { - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte(0); - } else { - addbyte(0x04); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - } - } - break; - case 1: - addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x44); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addbyte((fetchdat >> 16) & 0xff); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ - addbyte(0x43); - addbyte(0x8d); - addbyte(0x84); - addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); - addlong(new_eaaddr); - (*op_pc) += 4; - break; - } - } - if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } else { - int base_reg; - - if (!mod && rm == 5) { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - base_reg = LOAD_REG_L(rm) & 7; - if (mod) { - if (rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (mod == 1) { - addbyte(0x67); /*LEA EAX, base_reg+imm8*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x40 | base_reg); - addbyte((fetchdat >> 8) & 0xff); - (*op_pc)++; - } else { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x67); /*LEA EAX, base_reg+imm32*/ - addbyte(0x41); - addbyte(0x8d); - addbyte(0x80 | base_reg); - addlong(new_eaaddr); - (*op_pc) += 4; - } - } else { - addbyte(0x44); /*MOV EAX, base_reg*/ - addbyte(0x89); - addbyte(0xc0 | (base_reg << 3)); - } - } - return op_ea_seg; -} - -static __inline x86seg * -FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) -{ - if (op_32 & 0x200) - return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); - return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); -} - -static __inline void -CHECK_SEG_READ(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - if (IS_32_ADDR(&seg->base)) { - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - addbyte(-1); - } else { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x83); /*CMP RSI, -1*/ - addbyte(0xe8 | REG_ESI); - addbyte(0xff); - } - addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ - addbyte(0x84); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static __inline void -CHECK_SEG_WRITE(x86seg *seg) -{ - /*Segments always valid in real/V86 mode*/ - if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG)) - return; - /*CS and SS must always be valid*/ - if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss) - return; - if (seg->checked) - return; - if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) - return; - - if (IS_32_ADDR(&seg->base)) { - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - addbyte(-1); - } else { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x83); /*CMP RSI, -1*/ - addbyte(0xe8 | REG_ESI); - addbyte(0xff); - } - addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ - addbyte(0x84); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - - seg->checked = 1; -} -static __inline void -CHECK_SEG_LIMITS(x86seg *seg, int end_offset) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - return; - - if (IS_32_ADDR(&seg->base)) { - addbyte(0xb8 | REG_ESI); /*MOV ESI, &addr*/ - addlong((uint32_t) (uintptr_t) seg); - } else { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) seg); - } - addbyte(0x3b); /*CMP EAX, seg->limit_low*/ - addbyte(0x46); - addbyte((uintptr_t) &seg->limit_low - (uintptr_t) seg); - addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ - addbyte(0x82); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - if (end_offset) { - addbyte(0x83); /*ADD EAX, end_offset*/ - addbyte(0xc0); - addbyte(end_offset); - addbyte(0x3b); /*CMP EAX, seg->limit_high*/ - addbyte(0x46); - addbyte((uintptr_t) &seg->limit_high - (uintptr_t) seg); - addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ - addbyte(0x87); - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - addbyte(0x83); /*SUB EAX, end_offset*/ - addbyte(0xe8); - addbyte(end_offset); - } -} - -static __inline void -MEM_LOAD_ADDR_EA_B(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3 + 2); - addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12 + 4 + 6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmembl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static __inline void -MEM_LOAD_ADDR_EA_W(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + 4 + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4 + 2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12 + 4 + 6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmemwl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static __inline void -MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) -{ - addbyte(0x83); /*ADD EAX, offset*/ - addbyte(0xc0); - addbyte(offset); - MEM_LOAD_ADDR_EA_W(seg); -} -static __inline void -MEM_LOAD_ADDR_EA_L(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + 3 + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3 + 2); - addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12 + 4 + 6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmemll); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static __inline void -MEM_LOAD_ADDR_EA_Q(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + 4 + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4 + 2); - addbyte(0x48); /*MOV RAX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12 + 4 + 6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmemql); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} - -static __inline void -MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_B(seg); -} -static __inline void -MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_W(seg); -} -static __inline void -MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_LOAD_ADDR_EA_L(seg); -} - -static __inline void -MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) -{ - if (host_reg & 0x10) { - /*Handle high byte of register*/ - if (host_reg & 8) { - addbyte(0x45); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } else { - addbyte(0x41); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - addbyte(0x66); /*SHR R8, 8*/ - addbyte(0x41); - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - host_reg = 8; - } - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4 : 3) + 2); - if (host_reg & 8) { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x88); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2 + 2 + 3 + 12 + 4 + 6); - } else { - addbyte(2 + 2 + 2 + 12 + 4 + 6); - } - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(host_reg); - call_long((uintptr_t) writemembl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static __inline void -MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + ((host_reg & 8) ? 5 : 4) + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 5 : 4) + 2); - if (host_reg & 8) { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2 + 2 + 3 + 12 + 4 + 6); - } else { - addbyte(2 + 2 + 2 + 12 + 4 + 6); - } - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(host_reg); - call_long((uintptr_t) writememwl); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static __inline void -MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + ((host_reg & 8) ? 4 : 3) + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4 : 3) + 2); - if (host_reg & 8) { - addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2 + 2 + 3 + 12 + 4 + 6); - } else { - addbyte(2 + 2 + 2 + 12 + 4 + 6); - } - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_32(host_reg); - call_long((uintptr_t) writememll); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} -static __inline void -MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + 4 + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4 + 2); - if (host_reg & 8) { - addbyte(0x4c); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x48); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 3 + 12 + 4 + 6); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - load_param_2_reg_64(host_reg); - call_long((uintptr_t) writememql); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - /*done:*/ -} - -static __inline void -MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_B(seg, host_reg); -} -static __inline void -MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_W(seg, host_reg); -} -static __inline void -MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) -{ - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_L(seg, host_reg); -} - -static __inline void -STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) -{ - int temp_reg = REG_ECX; - - if (host_reg_mapping[REG_ECX] != -1) - temp_reg = REG_EBX; - - if (host_reg & 0x10) { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb7); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - addbyte(0xc1); /*SHR temp_reg, 8*/ - addbyte(0xe8 | temp_reg); - addbyte(8); - } else { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb6); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - } - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x45 | (temp_reg << 3)); - addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); - } else if (IS_32_ADDR(addr)) { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x04 | (temp_reg << 3)); - addbyte(0x25); - addlong(addr); - } else { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) addr); - addbyte(0x89); /*MOV [RSI], temp_reg*/ - addbyte(0x06 | (temp_reg << 3)); - } -} -static __inline void -STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) -{ - int temp_reg = REG_ECX; - - if (host_reg_mapping[REG_ECX] != -1) - temp_reg = REG_EBX; - - if (host_reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX temp_reg, host_reg*/ - addbyte(0xb7); - addbyte(0xc0 | (temp_reg << 3) | (host_reg & 7)); - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x45 | (temp_reg << 3)); - addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); - } else if (IS_32_ADDR(addr)) { - addbyte(0x89); /*MOV addr, temp_reg*/ - addbyte(0x04 | (temp_reg << 3)); - addbyte(0x25); - addlong(addr); - } else { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) addr); - addbyte(0x89); /*MOV [RSI], temp_reg*/ - addbyte(0x06 | (temp_reg << 3)); - } -} -static __inline void -STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - addbyte(0x66); /*MOVW [addr],host_reg*/ - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); - } else if (IS_32_ADDR(addr)) { - addbyte(0x66); - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVW addr,host_reg*/ - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(0x25); - addlong(addr); - } else { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) addr); - - addbyte(0x66); - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVW [RSI],host_reg*/ - addbyte(0x06 | ((host_reg & 7) << 3)); - } -} -static __inline void -STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) -{ - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [addr],host_reg*/ - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte((uint32_t) addr - (uint32_t) (uintptr_t) &cpu_state - 128); - } else if (IS_32_ADDR(addr)) { - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL addr,host_reg*/ - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(0x25); - addlong(addr); - } else { - addbyte(0x48); /*MOV RSI, addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) addr); - - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [RSI],host_reg*/ - addbyte(0x06 | ((host_reg & 7) << 3)); - } -} - -static __inline void -AND_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } - addbyte(0x66); /*OR AX, 0x00ff*/ - addbyte(0x0d); - addword(0xff); - addbyte(0x66); /*ANDW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7)); - } else if (src_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ANDB dst_reg, AL*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7)); - } else { - addbyte(0x45); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (dst_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*OR src_reg, 0xff*/ - addbyte(0x81); - addbyte(0xc8 | src_reg); - addword(0xff); - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x41); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x20); /*ANDB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x44); /*ANDB dst_reg, src_reg*/ - addbyte(0x20); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x20); /*ANDB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x20); /*ANDB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static __inline void -AND_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x66); /*ANDW dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -AND_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x45); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x41); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x44); /*ANDL dst_reg, src_reg*/ - addbyte(0x21); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x21); /*ANDL dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -AND_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) { - addbyte(0x66); /*ANDW host_reg, imm<<8*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xe0 | (host_reg & 7)); - addword((imm << 8) | 0xff); - } else { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xe0 | (host_reg & 7)); - addlong(imm); - } -} - -static __inline int -TEST_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = (dst_reg & 0x10) | REG_EDX; - } - - AND_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; -} -static __inline int -TEST_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - AND_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static __inline int -TEST_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - AND_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} -static __inline int -TEST_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 8) { - addbyte(0x44); /*MOV EDX, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((host_reg & 7) << 3)); - host_reg = REG_EDX | (host_reg & 0x10); - } - if (host_reg & 0x10) { - addbyte(0x66); /*ANDW host_reg, imm<<8*/ - addbyte(0x81); - addbyte(0xe0 | (host_reg & 7)); - addword((imm << 8) | 0xff); - } else { - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xe0 | (host_reg & 7)); - addlong(imm); - } - - return host_reg; -} - -static __inline void -OR_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } else { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*ORW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7)); - } else if (src_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ORB dst_reg, AL*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7)); - } else { - addbyte(0x45); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (dst_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x41); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x08); /*ORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x44); /*ORB dst_reg, src_reg*/ - addbyte(0x08); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x08); /*ORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x08); /*ORB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static __inline void -OR_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x66); /*ORW dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -OR_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x45); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x41); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x44); /*ORL dst_reg, src_reg*/ - addbyte(0x09); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x09); /*ORW dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -OR_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) { - addbyte(0x66); /*ORW host_reg, imm<<8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xc8 | (host_reg & 7)); - addword(imm << 8); - } else if (host_reg & 8) { - addbyte(0x41); /*ORL host_reg, imm*/ - addbyte(0x81); - addbyte(0xc8 | (host_reg & 7)); - addlong(imm); - } else { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xc8 | (host_reg & 7)); - addlong(imm); - } -} - -static __inline void -XOR_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } else { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*XORW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7)); - } else if (src_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*XORB dst_reg, AL*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7)); - } else { - addbyte(0x45); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (dst_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x41); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x30); /*XORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x44); /*XORB dst_reg, src_reg*/ - addbyte(0x30); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x30); /*XORB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x30); /*XORB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static __inline void -XOR_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x66); /*XORW dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -XOR_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x45); /*XORL dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x41); /*XORL dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x44); /*XORW dst_reg, src_reg*/ - addbyte(0x31); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x31); /*XORW dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -XOR_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 0x10) { - addbyte(0x66); /*ORW host_reg, imm<<8*/ - addbyte(0x41); - addbyte(0x81); - addbyte(0xf0 | (host_reg & 7)); - addword(imm << 8); - } else if (host_reg & 8) { - addbyte(0x41); /*ORL host_reg, imm*/ - addbyte(0x81); - addbyte(0xf0 | (host_reg & 7)); - addlong(imm); - } else { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xf0 | (host_reg & 7)); - addlong(imm); - } -} - -static __inline void -ADD_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } else { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*ADDW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7)); - } else if (src_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*ADDB dst_reg, AL*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7)); - } else { - addbyte(0x45); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (dst_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x41); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (src_reg & 8) { - if (src_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x00); /*ADDB dst_reg, AL*/ - addbyte(0xc0 | (dst_reg & 7)); - } else { - addbyte(0x44); /*ADDB dst_reg, src_reg*/ - addbyte(0x00); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else - fatal("!(dst_reg & src_reg & 8)\n"); -} -static __inline void -ADD_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else - fatal("!(dst_reg & src_reg & 8)\n"); -} -static __inline void -ADD_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x45); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x41); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x44); /*ADDL dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else - fatal("!(dst_reg & src_reg & 8)\n"); -} - -static __inline void -SUB_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - if (!(src_reg & 0x10)) { - addbyte(0x66); /*SHL AX, 8*/ - addbyte(0xc1); - addbyte(0xe0); - addbyte(8); - } else { - addbyte(0x66); /*AND AX, 0xff00*/ - addbyte(0x25); - addword(0xff00); - } - addbyte(0x66); /*SUBW dst_reg, AX*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7)); - } else if (src_reg & 0x10) { - addbyte(0x66); /*MOVW AX, src_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | ((src_reg & 7) << 3)); - addbyte(0x66); /*SHR AX, 8*/ - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - addbyte(0x41); /*SUBB dst_reg, AL*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7)); - } else { - addbyte(0x45); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (dst_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0x66); /*SHL src_reg, 8*/ - addbyte(0xc1); - addbyte(0xe0 | src_reg); - addbyte(0x08); - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x41); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else if (src_reg & 8) { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x41); /*MOVZX EBX, src_reg*/ - addbyte(0x0f); - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x28); /*SUBB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x44); /*SUBB dst_reg, src_reg*/ - addbyte(0x28); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } else { - if (dst_reg & 0x10) { - addbyte(0xc1); /*SHR dst_reg, 8*/ - addbyte(0xe8 | (dst_reg & 7)); - addbyte(8); - } - if (src_reg & 0x10) { - addbyte(0x0f); /*MOVZX EBX, src_reg*/ - addbyte(0xb7); - addbyte(0xd8 | (src_reg & 7)); - addbyte(0xc1); /*SHR EBX, 8*/ - addbyte(0xeb); - addbyte(8); - addbyte(0x28); /*SUBB dst_reg, EBX*/ - addbyte(0xd8 | (dst_reg & 7)); - } else { - addbyte(0x28); /*SUBB dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } - } -} -static __inline void -SUB_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x45); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x41); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x44); - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} -static __inline void -SUB_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & src_reg & 8) { - addbyte(0x45); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (dst_reg & 8) { - addbyte(0x41); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else if (src_reg & 8) { - addbyte(0x44); /*SUBL dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } else { - addbyte(0x29); /*SUBL dst_reg, src_reg*/ - addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); - } -} - -static __inline int -CMP_HOST_REG_B(int dst_reg, int src_reg) -{ - if (dst_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = (dst_reg & 0x10) | REG_EDX; - } - - SUB_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; -} -static __inline int -CMP_HOST_REG_W(int dst_reg, int src_reg) -{ - if (dst_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - SUB_HOST_REG_W(dst_reg, src_reg); - - return dst_reg; -} -static __inline int -CMP_HOST_REG_L(int dst_reg, int src_reg) -{ - if (dst_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); - - dst_reg = REG_EDX; - } - - SUB_HOST_REG_L(dst_reg, src_reg); - - return dst_reg; -} - -static __inline void -ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 0x10) { - addbyte(0x66); /*ADDW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xC0 | (host_reg & 7)); - addword(imm << 8); - } else { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*ADDB host_reg, imm*/ - addbyte(0xC0 | (host_reg & 7)); - addbyte(imm); - } -} -static __inline void -ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - addbyte(0x66); /*ADDW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xC0 | (host_reg & 7)); - addword(imm); -} -static __inline void -ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ADDL host_reg, imm*/ - addbyte(0xC0 | (host_reg & 7)); - addlong(imm); -} - -static __inline void -SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 0x10) { - addbyte(0x66); /*SUBW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xE8 | (host_reg & 7)); - addword(imm << 8); - } else { - if (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*SUBB host_reg, imm*/ - addbyte(0xE8 | (host_reg & 7)); - addbyte(imm); - } -} -static __inline void -SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - addbyte(0x66); /*SUBW host_reg, imm*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); - addbyte(0xE8 | (host_reg & 7)); - addword(imm); -} -static __inline void -SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*SUBL host_reg, imm*/ - addbyte(0xE8 | (host_reg & 7)); - addlong(imm); -} - -static __inline void -INC_HOST_REG_W(int host_reg) -{ - addbyte(0x66); /*INCW host_reg*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); - addbyte(0xc0 | (host_reg & 7)); -} -static __inline void -INC_HOST_REG(int host_reg) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); /*INCL host_reg*/ - addbyte(0xc0 | (host_reg & 7)); -} -static __inline void -DEC_HOST_REG_W(int host_reg) -{ - addbyte(0x66); /*DECW host_reg*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); - addbyte(0xc8 | (host_reg & 7)); -} -static __inline void -DEC_HOST_REG(int host_reg) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0xff); /*DECL host_reg*/ - addbyte(0xc8 | (host_reg & 7)); -} - -static __inline int -CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) -{ - if (host_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = (host_reg & 0x10) | REG_EDX; - } - - SUB_HOST_REG_IMM_B(host_reg, imm); - - return host_reg; -} -static __inline int -CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (host_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = REG_EDX; - } - - SUB_HOST_REG_IMM_W(host_reg, imm); - - return host_reg; -} -static __inline int -CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) -{ - if (host_reg & 8) { - addbyte(0x44); /*MOV EDX, dst_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - - host_reg = REG_EDX; - } - - SUB_HOST_REG_IMM(host_reg, imm); - - return host_reg; -} - -static __inline void -LOAD_STACK_TO_EA(int off) -{ - if (stack32) { - addbyte(0x8b); /*MOVL EAX,[ESP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); - if (off) { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } else { - addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); - if (off) { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} -static __inline void -LOAD_EBP_TO_EA(int off) -{ - if (stack32) { - addbyte(0x8b); /*MOVL EAX,[EBP]*/ - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t) cpu_state_offset(regs[REG_EBP].l)); - if (off) { - addbyte(0x83); /*ADD EAX, off*/ - addbyte(0xc0 | (0 << 3) | REG_EAX); - addbyte(off); - } - } else { - addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ - addbyte(0xb7); - addbyte(0x45 | (REG_EAX << 3)); - addbyte((uint8_t) cpu_state_offset(regs[REG_BP].l)); - if (off) { - addbyte(0x66); /*ADD AX, off*/ - addbyte(0x05); - addword(off); - } - } -} - -static __inline void -SP_MODIFY(int off) -{ - if (stack32) { - if (off < 0x80) { - addbyte(0x83); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); - addbyte(off); - } else { - addbyte(0x81); /*ADD [ESP], off*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].l)); - addlong(off); - } - } else { - if (off < 0x80) { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x83); - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); - addbyte(off); - } else { - addbyte(0x66); /*ADD [SP], off*/ - addbyte(0x81); - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(regs[REG_ESP].w)); - addword(off); - } - } -} - -static __inline void -TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7 + 5 + (taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static __inline void -TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x75); /*JNZ +*/ - addbyte(7 + 5 + (taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static __inline void -TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) -{ - addbyte(0x66); /*CMPW host_reg, 0*/ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + (taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} -static __inline void -TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) -{ - if (host_reg & 8) - addbyte(0x41); - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | (host_reg & 7)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + (taken_cycles ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(new_pc); - if (taken_cycles) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(taken_cycles); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static __inline void -BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) -{ - uint8_t *jump1; - - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } else { - CALL_FUNC((uintptr_t) ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - CALL_FUNC((uintptr_t) CF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - if (not ) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + (timing_bt ? 4 : 0)); - - if (!not ) - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(op_pc + pc_offset + offset); - if (timing_bt) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - if (not ) - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; -} - -static __inline void -BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) -{ - CALL_FUNC((uintptr_t) NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t) VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not ) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + (timing_bt ? 4 : 0)); - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(op_pc + pc_offset + offset); - if (timing_bt) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} - -static __inline void -BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) -{ - uint8_t *jump1; - if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { - addbyte(0x83); /*CMP flags_res, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(flags_res)); - addbyte(0); - addbyte(0x74); /*JZ +*/ - } else { - CALL_FUNC((uintptr_t) ZF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x75); /*JNZ +*/ - } - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - CALL_FUNC((uintptr_t) NF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE BL*/ - addbyte(0x95); - addbyte(0xc3); - CALL_FUNC((uintptr_t) VF_SET); - addbyte(0x85); /*TEST EAX,EAX*/ - addbyte(0xc0); - addbyte(0x0f); /*SETNE AL*/ - addbyte(0x95); - addbyte(0xc0); - addbyte(0x38); /*CMP AL, BL*/ - addbyte(0xd8); - if (not ) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + (timing_bt ? 4 : 0)); - if (!not ) - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; - addbyte(0xC7); /*MOVL [pc], new_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(pc)); - addlong(op_pc + pc_offset + offset); - if (timing_bt) { - addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x6d); - addbyte((uint8_t) cpu_state_offset(_cycles)); - addbyte(timing_bt); - } - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - if (not ) - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; -} - -static __inline int -LOAD_VAR_W(uintptr_t addr) -{ - int host_reg = REG_EBX; - - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - addbyte(0x0f); /*MOVZX host_reg, offset[cpu_state]*/ - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte(addr - (uintptr_t) &cpu_state - 128); - } else if (IS_32_ADDR(addr)) { - addbyte(0x0f); /*MOVZX host_reg,[reg]*/ - addbyte(0xb7); - addbyte(0x04 | (host_reg << 3)); - addbyte(0x25); - addlong((uint32_t) addr); - } else { - addbyte(0x48); /*MOV host_reg, &addr*/ - addbyte(0xb8 | host_reg); - addquad(addr); - addbyte(0x0f); /*MOVZX host_reg, [host_reg]*/ - addbyte(0xb7); - addbyte(host_reg | (host_reg << 3)); - } - - return host_reg; -} -static __inline int -LOAD_VAR_WL(uintptr_t addr) -{ - return LOAD_VAR_W(addr); -} -static __inline int -LOAD_VAR_L(uintptr_t addr) -{ - int host_reg = REG_EBX; - - if (addr >= (uintptr_t) &cpu_state && addr < ((uintptr_t) &cpu_state) + 0x100) { - addbyte(0x8b); /*MOVL host_reg, offset[cpu_state]*/ - addbyte(0x45 | (host_reg << 3)); - addbyte(addr - (uintptr_t) &cpu_state - 128); - } else if (IS_32_ADDR(addr)) { - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(0x25); - addlong((uint32_t) addr); - } else { - addbyte(0x48); /*MOV host_reg, &addr*/ - addbyte(0xb8 | host_reg); - addquad(addr); - addbyte(0x8b); /*MOVL host_reg, [host_reg]*/ - addbyte(host_reg | (host_reg << 3)); - } - - return host_reg; -} - -static __inline int -COPY_REG(int src_reg) -{ - if (src_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | REG_ECX | ((src_reg & 7) << 3)); - - return REG_ECX | (src_reg & 0x10); -} - -static __inline int -LOAD_HOST_REG(int host_reg) -{ - if (host_reg & 8) - addbyte(0x44); - addbyte(0x89); - addbyte(0xc0 | REG_EBX | ((host_reg & 7) << 3)); - - return REG_EBX | (host_reg & 0x10); -} - -static __inline int -ZERO_EXTEND_W_B(int reg) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVZX EAX, AH*/ - addbyte(0xb6); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static __inline int -ZERO_EXTEND_L_B(int reg) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVZX EAX, AH*/ - addbyte(0xb6); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static __inline int -ZERO_EXTEND_L_W(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVZX regl, regw*/ - addbyte(0xb7); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} - -static __inline int -SIGN_EXTEND_W_B(int reg) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVSX EAX, AH*/ - addbyte(0xbe); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static __inline int -SIGN_EXTEND_L_B(int reg) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | (reg << 3)); - addbyte(0x0f); /*MOVSX EAX, AH*/ - addbyte(0xbe); - addbyte(0xc4); - - return REG_EAX; - } - - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} -static __inline int -SIGN_EXTEND_L_W(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0x0f); /*MOVSX regl, regw*/ - addbyte(0xbf); - addbyte(0xc0 | (reg & 7)); - - return REG_EAX; -} - -static __inline void -SHL_B_IMM(int reg, int count) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SHL AH, count*/ - addbyte(0xe0 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } else { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); - } -} -static __inline void -SHL_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHL reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); -} -static __inline void -SHL_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); -} -static __inline void -SHR_B_IMM(int reg, int count) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SHR AH, count*/ - addbyte(0xe8 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } else { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); - } -} -static __inline void -SHR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SHR reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); -} -static __inline void -SHR_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SHR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x28); - addbyte(count); -} -static __inline void -SAR_B_IMM(int reg, int count) -{ - if (reg & 0x10) { - addbyte(0x44); /*MOV EAX, reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); - addbyte(0xc0); /*SAR AH, count*/ - addbyte(0xf8 | REG_AH); - addbyte(count); - addbyte(0x41); /*MOV reg, EAX*/ - addbyte(0x89); - addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); - } else { - if (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SAR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); - } -} -static __inline void -SAR_W_IMM(int reg, int count) -{ - addbyte(0x66); /*SAR reg, count*/ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); -} -static __inline void -SAR_L_IMM(int reg, int count) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xc1); /*SAR reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x38); - addbyte(count); -} - -static __inline void -NEG_HOST_REG_B(int reg) -{ - if (reg & 0x10) { - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV BX, reg*/ - addbyte(0xc3 | ((reg & 7) << 3)); - addbyte(0xf6); /*NEG BH*/ - addbyte(0xdf); - if (reg & 8) - addbyte(0x41); - addbyte(0x89); /*MOV reg, BX*/ - addbyte(0xd8 | (reg & 7)); - } else { - if (reg & 8) - addbyte(0x41); - addbyte(0xf6); - addbyte(0xd8 | (reg & 7)); - } -} -static __inline void -NEG_HOST_REG_W(int reg) -{ - addbyte(0x66); - if (reg & 8) - addbyte(0x41); - addbyte(0xf7); - addbyte(0xd8 | (reg & 7)); -} -static __inline void -NEG_HOST_REG_L(int reg) -{ - if (reg & 8) - addbyte(0x41); - addbyte(0xf7); - addbyte(0xd8 | (reg & 7)); -} - -static __inline void -FP_ENTER(void) -{ - if (codegen_fpu_entered) - return; - if (IS_32_ADDR(&cr0)) { - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x04); - addbyte(0x25); - addlong((uintptr_t) &cr0); - addbyte(0x0c); - } else { - addbyte(0x48); /*MOV RAX, &cr0*/ - addbyte(0xb8 | REG_EAX); - addquad((uint64_t) &cr0); - addbyte(0xf6); /*TEST [RAX], 0xc*/ - addbyte(0 | (REG_EAX << 3)); - addbyte(0x0c); - } - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + 12 + 5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(oldpc)); - addlong(op_old_pc); - load_param_1_32(&codeblock[block_current], 7); - CALL_FUNC((uintptr_t) x86_int); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - codegen_fpu_entered = 1; -} - -static __inline void -FP_FXCH(int reg) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - - addbyte(0x48); /*MOV RDX, ST[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0x48); /*MOV RCX, ST[RAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST[RAX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST[RBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - - addbyte(0x48); /*MOV RDX, MM[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0x48); /*MOV RCX, MM[RAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0x48); /*MOV MM[RAX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0x48); /*MOV MM[RBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(MM)); -} - -static __inline void -FP_FLD(int reg) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (reg) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } else { - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - } - - addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(0x07); - addbyte(0x48); /*MOV RDX, ST_i64[EAX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(0x48); /*MOV ST[EBX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x48); /*MOV ST_i64[EBX*8], RDX*/ - addbyte(0x89); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); - - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); -} - -static __inline void -FP_FST(int reg) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ - addbyte(0x8b); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [tag+EAX]*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - - if (reg) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - - addbyte(0x48); /*MOV ST[EAX*8], RCX*/ - addbyte(0x89); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EAX], BL*/ - addbyte(0x5c); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); -} - -static __inline void -FP_POP(void) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(3); - addbyte(0x83); /*ADD AL, 1*/ - addbyte(0xc0); - addbyte(1); - addbyte(0x83); /*AND AL, 7*/ - addbyte(0xe0); - addbyte(7); - addbyte(0x89); /*MOV [TOP], EAX*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); -} -static __inline void -FP_POP2(void) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(3); - addbyte(0x83); /*ADD AL, 2*/ - addbyte(0xc0); - addbyte(2); - addbyte(0x83); /*AND AL, 7*/ - addbyte(0xe0); - addbyte(7); - addbyte(0x89); /*MOV [TOP], EAX*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); -} - -static __inline void -FP_LOAD_S(void) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x66); /*MOVD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf3); /*CVTSS2SD XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); -} -static __inline void -FP_LOAD_D(void) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x48); /*TEST RAX, RAX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x48); /*MOVQ [ST+EBX*8], RAX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); -} - -static __inline void -FP_LOAD_IW(void) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); -} -static __inline void -FP_LOAD_IL(void) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); -} -static __inline void -FP_LOAD_IQ(void) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0xf2); /*CVTSI2SDQ XMM0, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc0); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x48); /*TEST RAX, RAX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0x48); /*MOV [ST_i64+EBX*8], RAX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); -} - -static __inline void -FP_LOAD_IMM_Q(uint64_t v) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST) + 4); - addlong(v >> 32); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0xc6); /*MOV [tag+EBX], (v ? 0 : 1)*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(v ? 0 : 1); -} - -static __inline void -FP_FCHS(void) -{ - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0xf2); /*SUBSD XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc0); - addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0x11); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); -} - -static __inline int -FP_LOAD_REG(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - if (reg) { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0xf2); /*CVTSD2SS XMM0, XMM0*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc0); - addbyte(0x66); /*MOVD EBX, XMM0*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0xc0 | REG_EBX); - - return REG_EBX; -} -static __inline void -FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t) cpu_state_offset(TOP)); - if (reg) { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0x48); /*MOV RBX, ST[EBX*8]*/ - addbyte(0x8b); - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - - *host_reg1 = REG_EBX; -} -static __inline int64_t -x87_fround16_64(double b) -{ - int16_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) { - case 0: /*Nearest*/ - a = (int16_t) floor(b); - c = (int16_t) floor(b + 1.0); - if ((b - a) < (c - b)) - return (int64_t) a; - else if ((b - a) > (c - b)) - return (int64_t) c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t) ((int16_t) floor(b)); - case 2: /*Up*/ - return (int64_t) ((int16_t) ceil(b)); - case 3: /*Chop*/ - return (int64_t) ((int16_t) b); - } - - return 0; -} -static __inline int64_t -x87_fround32_64(double b) -{ - int32_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) { - case 0: /*Nearest*/ - a = (int32_t) floor(b); - c = (int32_t) floor(b + 1.0); - if ((b - a) < (c - b)) - return (int64_t) a; - else if ((b - a) > (c - b)) - return (int64_t) c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t) ((int32_t) floor(b)); - case 2: /*Up*/ - return (int64_t) ((int32_t) ceil(b)); - case 3: /*Chop*/ - return (int64_t) ((int32_t) b); - } - - return 0; -} -static __inline int64_t -x87_fround(double b) -{ - int64_t a, c; - - switch ((cpu_state.npxc >> 10) & 3) { - case 0: /*Nearest*/ - a = (int64_t) floor(b); - c = (int64_t) floor(b + 1.0); - if ((b - a) < (c - b)) - return a; - else if ((b - a) > (c - b)) - return c; - else - return (a & 1) ? c : a; - case 1: /*Down*/ - return (int64_t) floor(b); - case 2: /*Up*/ - return (int64_t) ceil(b); - case 3: /*Chop*/ - return (int64_t) b; - } - - return 0; -} -static __inline int -FP_LOAD_REG_INT_W(int reg) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - if (reg) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t) x87_fround16_64); - - addbyte(0x93); /*XCHG EBX, EAX*/ - - return REG_EBX; -} -static __inline int -FP_LOAD_REG_INT(int reg) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - if (reg) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t) x87_fround32_64); - - addbyte(0x93); /*XCHG EBX, EAX*/ - - return REG_EBX; -} -static __inline void -FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) -{ - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - if (reg) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - if (codegen_fpu_loaded_iq[cpu_state.TOP] && (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)) { - /*If we know the register was loaded with FILDq in this block and - has not been modified, then we can skip most of the conversion - and just load the 64-bit integer representation directly */ - addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ - addbyte(0x8b); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(MM)); - - addbyte(0x48); /*XCHG RBX, RAX*/ - addbyte(0x93); - - *host_reg1 = REG_EBX; - - return; - } - - addbyte(0xf6); /*TEST TAG[EAX], TAG_UINT64*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(TAG_UINT64); - - addbyte(0x74); /*JZ +*/ - addbyte(5 + 2); - - addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ - addbyte(0x8b); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(MM)); - - addbyte(0xeb); /*JMP done*/ - addbyte(6 + 12); - - addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - - CALL_FUNC((uintptr_t) x87_fround); - - addbyte(0x48); /*XCHG RBX, RAX*/ - addbyte(0x93); - - *host_reg1 = REG_EBX; -} - -#define FPU_ADD 0 -#define FPU_DIV 4 -#define FPU_DIVR 5 -#define FPU_MUL 1 -#define FPU_SUB 2 -#define FPU_SUBR 3 - -static __inline void -FP_OP_REG(int op, int dst, int src) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (dst) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - if (src) { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc0 | REG_EBX); - addbyte(src); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe0 | REG_EBX); - addbyte(0x07); - } - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(TAG_NOT_UINT64); - if (op == FPU_DIVR || op == FPU_SUBR) { - addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - } else { - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - } - switch (op) { - case FPU_ADD: - addbyte(0xf2); /*ADDSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x58); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - break; - case FPU_DIV: - addbyte(0xf2); /*DIVSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - break; - case FPU_DIVR: - addbyte(0xf2); /*DIVSD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - break; - case FPU_MUL: - addbyte(0xf2); /*MULSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x59); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - break; - case FPU_SUB: - addbyte(0xf2); /*SUBSD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - break; - case FPU_SUBR: - addbyte(0xf2); /*SUBSD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - break; - } - addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); -} - -static __inline void -FP_OP_MEM(int op) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte((uint8_t) cpu_state_offset(tag)); - addbyte(TAG_NOT_UINT64); - - switch (op) { - case FPU_ADD: - addbyte(0xf2); /*ADDSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x58); - addbyte(0xc1); - break; - case FPU_DIV: - addbyte(0xf2); /*DIVSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0xc1); - break; - case FPU_DIVR: - addbyte(0xf2); /*DIVSD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x5e); - addbyte(0xc8); - break; - case FPU_MUL: - addbyte(0xf2); /*MULSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x59); - addbyte(0xc1); - break; - case FPU_SUB: - addbyte(0xf2); /*SUBSD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc1); - break; - case FPU_SUBR: - addbyte(0xf2); /*SUBSD XMM1, XMM0*/ - addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc8); - break; - } - if (op == FPU_DIVR || op == FPU_SUBR) { - addbyte(0x66); /*MOVQ ST[RAX*8], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - } else { - addbyte(0x66); /*MOVQ ST[RAX*8], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - } -} - -static __inline void -FP_OP_S(int op) -{ - addbyte(0x66); /*MOVD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc9); - FP_OP_MEM(op); -} -static __inline void -FP_OP_D(int op) -{ - addbyte(0x66); /*MOVQ XMM1, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { - addbyte(0x0f); /*STMXCSR [ESP+8]*/ - addbyte(0xae); - addbyte(0x5c); - addbyte(0x24); - addbyte(0x08); - addbyte(0x8b); /*MOV EAX, [ESP+8]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x08); - addbyte(0x25); /*AND EAX, ~(3 << 13)*/ - addlong(~(3 << 10)); - addbyte(0x0d); /*OR EAX, (npxc & (3 << 10)) << 3*/ - addlong((cpu_state.npxc & (3 << 10)) << 3); - addbyte(0x89); /*MOV [RSP+12], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x0c); - addbyte(0x0f); /*LDMXCSR [RSP+12]*/ - addbyte(0xae); - addbyte(0x54); - addbyte(0x24); - addbyte(0x0c); - } - FP_OP_MEM(op); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { - addbyte(0x0f); /*LDMXCSR [RSP+8]*/ - addbyte(0xae); - addbyte(0x54); - addbyte(0x24); - addbyte(0x08); - } -} -static __inline void -FP_OP_IW(int op) -{ - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_OP_MEM(op); -} -static __inline void -FP_OP_IL(int op) -{ - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_OP_MEM(op); -} - -static __inline void -FP_COMPARE_REG(int dst, int src) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t) cpu_state_offset(npxs) + 1); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); - - if (src) { - addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x66); /*COMISD XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - } else { - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x66); /*COMISD XMM0, ST[RBX*8]*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t) cpu_state_offset(ST)); - } - - addbyte(0x9f); /*LAHF*/ - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t) cpu_state_offset(npxs) + 1); -} - -static __inline void -FP_COMPARE_MEM(void) -{ - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t) cpu_state_offset(npxs) + 1); - addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t) cpu_state_offset(ST)); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); - addbyte(0x66); /*COMISD XMM0, XMM1*/ - addbyte(0x0f); - addbyte(0x2f); - addbyte(0xc1); - addbyte(0x9f); /*LAHF*/ - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte((uint8_t) cpu_state_offset(npxs) + 1); -} -static __inline void -FP_COMPARE_S(void) -{ - addbyte(0x66); /*MOVD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ - addbyte(0x0f); - addbyte(0x5a); - addbyte(0xc9); - FP_COMPARE_MEM(); -} -static __inline void -FP_COMPARE_D(void) -{ - addbyte(0x66); /*MOVQ XMM1, RAX*/ - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - FP_COMPARE_MEM(); -} -static __inline void -FP_COMPARE_IW(void) -{ - addbyte(0x0f); /*MOVSX EAX, AX*/ - addbyte(0xbf); - addbyte(0xc0); - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_COMPARE_MEM(); -} -static __inline void -FP_COMPARE_IL(void) -{ - addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ - addbyte(0x0f); - addbyte(0x2a); - addbyte(0xc8); - FP_COMPARE_MEM(); -} - -static __inline void -UPDATE_NPXC(int reg) -{ -} - -static __inline void -SET_BITS(uintptr_t addr, uint32_t val) -{ - if (IS_32_ADDR(addr)) { - if (val & ~0xff) { - addbyte(0x81); /*OR [addr], val*/ - addbyte(0x0c); - addbyte(0x25); - addlong(addr); - addlong(val); - } else { - addbyte(0x80); /*OR [addr], val*/ - addbyte(0x0c); - addbyte(0x25); - addlong(addr); - addbyte(val); - } - } else { - addbyte(0x48); /*MOV RAX, &addr*/ - addbyte(0xb8 | REG_EAX); - addquad(addr); - if (val & ~0xff) { - addbyte(0x81); /*OR [RAX], val*/ - addbyte(0x08); - addlong(val); - } else { - addbyte(0x80); /*OR [RAX], val*/ - addbyte(0x08); - addbyte(val); - } - } -} - -static __inline void -CLEAR_BITS(uintptr_t addr, uint32_t val) -{ - if (IS_32_ADDR(addr)) { - if (val & ~0xff) { - addbyte(0x81); /*AND [addr], val*/ - addbyte(0x24); - addbyte(0x25); - addlong(addr); - addlong(~val); - } else { - addbyte(0x80); /*AND [addr], val*/ - addbyte(0x24); - addbyte(0x25); - addlong(addr); - addbyte(~val); - } - } else { - addbyte(0x48); /*MOV RAX, &addr*/ - addbyte(0xb8 | REG_EAX); - addquad(addr); - if (val & ~0xff) { - addbyte(0x81); /*AND [RAX], val*/ - addbyte(0x20); - addlong(~val); - } else { - addbyte(0x80); /*AND [RAX], val*/ - addbyte(0x20); - addbyte(~val); - } - } -} - -#define LOAD_Q_REG_1 REG_EAX -#define LOAD_Q_REG_2 REG_EDX - -static __inline void -MMX_ENTER(void) -{ - if (codegen_mmx_entered) - return; - - if (IS_32_ADDR(&cr0)) { - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x04); - addbyte(0x25); - addlong((uintptr_t) &cr0); - addbyte(0x0c); - } else { - addbyte(0x48); /*MOV RAX, &cr0*/ - addbyte(0xb8 | REG_EAX); - addquad((uint64_t) &cr0); - addbyte(0xf6); /*TEST [RAX], 0xc*/ - addbyte(0 | (REG_EAX << 3)); - addbyte(0x0c); - } - addbyte(0x74); /*JZ +*/ - addbyte(7 + 5 + 12 + 5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(oldpc)); - addlong(op_old_pc); - load_param_1_32(&codeblock[block_current], 7); - CALL_FUNC((uintptr_t) x86_int); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - addbyte(0x31); /*XOR EAX, EAX*/ - addbyte(0xc0); - addbyte(0xc6); /*MOV ISMMX, 1*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(ismmx)); - addbyte(1); - addbyte(0x89); /*MOV TOP, EAX*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0x89); /*MOV tag, EAX*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV tag+4, EAX*/ - addbyte(0x45); - addbyte((uint8_t) cpu_state_offset(tag[4])); - - codegen_mmx_entered = 1; -} - -extern int mmx_ebx_ecx_loaded; - -static __inline int -LOAD_MMX_D(int guest_reg) -{ - int host_reg = REG_EBX; - - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x44 | (host_reg << 3)); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); - - return host_reg; -} -static __inline void -LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) -{ - int host_reg = REG_EBX; - - if (host_reg & 8) - addbyte(0x4c); - else - addbyte(0x48); - addbyte(0x8b); /*MOV RBX, reg*/ - addbyte(0x44 | ((host_reg & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); - - *host_reg1 = host_reg; -} -static __inline int -LOAD_MMX_Q_MMX(int guest_reg) -{ - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0xf3); /*MOV XMMx, reg*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x44 | ((dst_reg & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); - - return dst_reg; -} - -static __inline int -LOAD_INT_TO_MMX(int src_reg1, int src_reg2) -{ - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = 100; - - addbyte(0x66); /*MOVQ host_reg, src_reg1*/ - if (src_reg1 & 8) - addbyte(0x49); - else - addbyte(0x48); - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (dst_reg << 3) | (src_reg1 & 7)); - - return dst_reg; -} - -static __inline void -STORE_MMX_LQ(int guest_reg, int host_reg1) -{ - addbyte(0xC7); /*MOVL [reg],0*/ - addbyte(0x44); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); - addlong(0); - if (host_reg1 & 8) - addbyte(0x44); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x44 | ((host_reg1 & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); -} -static __inline void -STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) -{ - if (host_reg1 & 8) - addbyte(0x4c); - else - addbyte(0x48); - addbyte(0x89); /*MOV [reg],host_reg*/ - addbyte(0x44 | ((host_reg1 & 7) << 3)); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); -} -static __inline void -STORE_MMX_Q_MMX(int guest_reg, int host_reg) -{ - addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x44 | (host_reg << 3)); - addbyte(0x25); - addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); -} - -#define MMX_x86_OP(name, opcode) \ - static __inline void MMX_##name(int dst_reg, int src_reg) \ - { \ - addbyte(0x66); /*op dst_reg, src_reg*/ \ - addbyte(0x0f); \ - addbyte(opcode); \ - addbyte(0xc0 | (dst_reg << 3) | src_reg); \ - } - -MMX_x86_OP(AND, 0xdb) - MMX_x86_OP(ANDN, 0xdf) - MMX_x86_OP(OR, 0xeb) - MMX_x86_OP(XOR, 0xef) - - MMX_x86_OP(ADDB, 0xfc) - MMX_x86_OP(ADDW, 0xfd) - MMX_x86_OP(ADDD, 0xfe) - MMX_x86_OP(ADDSB, 0xec) - MMX_x86_OP(ADDSW, 0xed) - MMX_x86_OP(ADDUSB, 0xdc) - MMX_x86_OP(ADDUSW, 0xdd) - - MMX_x86_OP(SUBB, 0xf8) - MMX_x86_OP(SUBW, 0xf9) - MMX_x86_OP(SUBD, 0xfa) - MMX_x86_OP(SUBSB, 0xe8) - MMX_x86_OP(SUBSW, 0xe9) - MMX_x86_OP(SUBUSB, 0xd8) - MMX_x86_OP(SUBUSW, 0xd9) - - MMX_x86_OP(PUNPCKLBW, 0x60); -MMX_x86_OP(PUNPCKLWD, 0x61); -MMX_x86_OP(PUNPCKLDQ, 0x62); -MMX_x86_OP(PCMPGTB, 0x64); -MMX_x86_OP(PCMPGTW, 0x65); -MMX_x86_OP(PCMPGTD, 0x66); - -MMX_x86_OP(PCMPEQB, 0x74); -MMX_x86_OP(PCMPEQW, 0x75); -MMX_x86_OP(PCMPEQD, 0x76); - -MMX_x86_OP(PSRLW, 0xd1); -MMX_x86_OP(PSRLD, 0xd2); -MMX_x86_OP(PSRLQ, 0xd3); -MMX_x86_OP(PSRAW, 0xe1); -MMX_x86_OP(PSRAD, 0xe2); -MMX_x86_OP(PSLLW, 0xf1); -MMX_x86_OP(PSLLD, 0xf2); -MMX_x86_OP(PSLLQ, 0xf3); - -MMX_x86_OP(PMULLW, 0xd5); -MMX_x86_OP(PMULHW, 0xe5); -MMX_x86_OP(PMADDWD, 0xf5); - -static __inline void -MMX_PACKSSWB(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x63); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static __inline void -MMX_PACKUSWB(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x67); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static __inline void -MMX_PACKSSDW(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x6b); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x08); -} -static __inline void -MMX_PUNPCKHBW(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x60); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} -static __inline void -MMX_PUNPCKHWD(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x61); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} -static __inline void -MMX_PUNPCKHDQ(int dst_reg, int src_reg) -{ - addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | (dst_reg << 3) | src_reg); - addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/ - addbyte(0x0f); - addbyte(0x70); - addbyte(0xc0 | (dst_reg << 3) | dst_reg); - addbyte(0x0e); -} - -static __inline void -MMX_PSRLW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static __inline void -MMX_PSRAW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static __inline void -MMX_PSLLW_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLW dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x71); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static __inline void -MMX_PSRLD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static __inline void -MMX_PSRAD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static __inline void -MMX_PSLLD_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLD dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x72); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static __inline void -MMX_PSRLQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x10); - addbyte(amount); -} -static __inline void -MMX_PSRAQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSRAQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x20); - addbyte(amount); -} -static __inline void -MMX_PSLLQ_imm(int dst_reg, int amount) -{ - addbyte(0x66); /*PSLLQ dst_reg, amount*/ - addbyte(0x0f); - addbyte(0x73); - addbyte(0xc0 | dst_reg | 0x30); - addbyte(amount); -} - -static __inline void -SAVE_EA(void) -{ - addbyte(0x89); /*MOV [ESP+0x24], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); -} -static __inline void -LOAD_EA(void) -{ - addbyte(0x8b); /*MOV EAX, [ESP+0x24]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); -} - -#define MEM_CHECK_WRITE_B MEM_CHECK_WRITE - -static __inline void -MEM_CHECK_WRITE(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3 = NULL; - - CHECK_SEG_WRITE(seg); - - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &cr0); - addbyte(0); - } else { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t) &cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - if (IS_32_ADDR(writelookup2)) { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t) (uintptr_t) writelookup2); - addbyte(-1); - } else { - addbyte(0x48); /*MOV RCX, writelookup2*/ - addbyte(0xb9); - addquad((uint64_t) writelookup2); - addbyte(0x83); /*CMP [RCX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf9); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump3 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump3 - 1; - /*slowpath:*/ - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - - load_param_1_reg_32(REG_EDI); - load_param_2_32(&codeblock[block_current], 1); - - call(&codeblock[block_current], (uintptr_t) mmutranslatereal32); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t) &codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t) (&codeblock[block_current].data[block_pos]) + 4)); - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; - *jump2 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump2 - 1; - - LOAD_EA(); -} - -static __inline void -MEM_CHECK_WRITE_W(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; - int jump_pos; - - CHECK_SEG_WRITE(seg); - - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &cr0); - addbyte(0); - } else { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t) &cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - } - addbyte(0x8d); /*LEA ESI, 1[EDI]*/ - addbyte(0x77); - addbyte(0x01); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x74); /*JE slowpath*/ - jump4 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - addbyte(0x89); /*MOV EBX, EDI*/ - addbyte(0xfb); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t) (uintptr_t) writelookup2); - addbyte(-1); - } else { - addbyte(0x48); /*MOV RAX, writelookup2*/ - addbyte(0xb8); - addquad((uint64_t) writelookup2); - addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf8); - addbyte(-1); - } - addbyte(0x74); /*JE +*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - addbyte(-1); - } else { - addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ - addbyte(0x3c); - addbyte(0xf0); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - /*slowpath:*/ - *jump2 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump2 - 1; - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump4 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump4 - 1; - jump_pos = block_pos; - load_param_1_reg_32(REG_EBX); - load_param_2_32(&codeblock[block_current], 1); - call(&codeblock[block_current], (uintptr_t) mmutranslatereal32); - addbyte(0x83); /*ADD EBX, 1*/ - addbyte(0xc3); - addbyte(1); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t) &codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t) (&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $fff, EBX*/ - addbyte(0xc3); - addlong(0xfff); - addbyte(0x74); /*JNE slowpath*/ - addbyte(jump_pos - block_pos - 1); - - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; - *jump3 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump3 - 1; - - LOAD_EA(); -} - -static __inline void -MEM_CHECK_WRITE_L(x86seg *seg) -{ - uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; - int jump_pos; - - CHECK_SEG_WRITE(seg); - - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOV ESI, seg->base*/ - addbyte(0x34); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ESI, [RSI]*/ - addbyte(0x36); - } - - /*seg = ESI, addr = EAX*/ - - if (IS_32_ADDR(&cr0)) { - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &cr0); - addbyte(0); - } else { - addbyte(0x48); /*MOV RDI, &cr0*/ - addbyte(0xbf); - addquad((uint64_t) &cr0); - addbyte(0x83); /*CMPL [RDI], 0*/ - addbyte(0x3f); - addbyte(0); - } - addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x8d); - addbyte(0x3c); - addbyte(0x30); - addbyte(0x79); /*JNS +*/ - jump1 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - } - addbyte(0x8d); /*LEA ESI, 3[EDI]*/ - addbyte(0x77); - addbyte(0x03); - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x74); /*JE slowpath*/ - jump4 = &codeblock[block_current].data[block_pos]; - addbyte(0); - } - addbyte(0x89); /*MOV EBX, EDI*/ - addbyte(0xfb); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t) (uintptr_t) writelookup2); - addbyte(-1); - } else { - addbyte(0x48); /*MOV RAX, writelookup2*/ - addbyte(0xb8); - addquad((uint64_t) writelookup2); - addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ - addbyte(0x3c); - addbyte(0xf8); - addbyte(-1); - } - addbyte(0x74); /*JE slowpath*/ - jump2 = &codeblock[block_current].data[block_pos]; - addbyte(0); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - addbyte(-1); - } else { - addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ - addbyte(0x3c); - addbyte(0xf0); - addbyte(-1); - } - addbyte(0x75); /*JNE +*/ - jump3 = &codeblock[block_current].data[block_pos]; - addbyte(0); - - /*slowpath:*/ - *jump2 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump2 - 1; - if (!(seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) && !(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) - *jump4 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump4 - 1; - jump_pos = block_pos; - load_param_1_reg_32(REG_EBX); - load_param_2_32(&codeblock[block_current], 1); - call(&codeblock[block_current], (uintptr_t) mmutranslatereal32); - addbyte(0x83); /*ADD EBX, 3*/ - addbyte(0xc3); - addbyte(3); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong((uintptr_t) &codeblock[block_current].data[BLOCK_EXIT_OFFSET] - ((uintptr_t) (&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST $ffc, EBX*/ - addbyte(0xc3); - addlong(0xffc); - addbyte(0x74); /*JE slowpath*/ - addbyte(jump_pos - block_pos - 1); - - *jump1 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump1 - 1; - *jump3 = (uintptr_t) &codeblock[block_current].data[block_pos] - (uintptr_t) jump3 - 1; - - LOAD_EA(); -} - -static __inline int -MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3 + 2); - addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmembl); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static __inline int -MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + 4 + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4 + 2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ - addbyte(0x8b); - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmemwl); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -static __inline int -MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR ECX, ECX*/ - addbyte(0xc9); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL ECX, seg->base*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV ECX, [RSI]*/ - addbyte(0x0e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(readlookup2)) { - addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) readlookup2); - } else { - addbyte(0x48); /*MOV RDX, readlookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) readlookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + 3 + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3 + 2); - addbyte(0x8b); /*MOV EAX,[RDI+RSI]*/ - addbyte(0x04); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xeb); /*JMP done*/ - addbyte(2 + 2 + 12); - /*slowpath:*/ - addbyte(0x01); /*ADD ECX,EAX*/ - addbyte(0xc1); - load_param_1_reg_32(REG_ECX); - call_long((uintptr_t) readmemll); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); - /*done:*/ - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} - -static __inline void -MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) -{ - if (host_reg & 0x10) { - /*Handle high byte of register*/ - if (host_reg & 8) { - addbyte(0x45); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } else { - addbyte(0x41); /*MOVL R8, host_reg*/ - addbyte(0x89); - addbyte(0xc0 | ((host_reg & 7) << 3)); - } - addbyte(0x66); /*SHR R8, 8*/ - addbyte(0x41); - addbyte(0xc1); - addbyte(0xe8); - addbyte(8); - host_reg = 8; - } - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4 : 3) + 2); - if (host_reg & 8) { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x88); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2 + 2 + 3 + 12); - } else { - addbyte(2 + 2 + 2 + 12); - } - /*slowpath:*/ - load_param_2_reg_32(host_reg); - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - load_param_1_reg_32(REG_EBX); - call_long((uintptr_t) writemembl); - /*done:*/ -} -static __inline void -MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + ((host_reg & 8) ? 5 : 4) + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 5 : 4) + 2); - if (host_reg & 8) { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x44); - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x66); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2 + 2 + 3 + 12); - } else { - addbyte(2 + 2 + 2 + 12); - } - /*slowpath:*/ - load_param_2_reg_32(host_reg); - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - load_param_1_reg_32(REG_EBX); - call_long((uintptr_t) writememwl); - /*done:*/ -} -static __inline void -MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) -{ - if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { - addbyte(0x31); /*XOR EBX, EBX*/ - addbyte(0xdb); - } else if (IS_32_ADDR(&seg->base)) { - addbyte(0x8b); /*MOVL EBX, seg->base*/ - addbyte(0x1c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &seg->base); - } else { - addbyte(0x48); /*MOV RSI, &seg->base*/ - addbyte(0xb8 | REG_ESI); - addquad((uint64_t) &seg->base); - addbyte(0x8b); /*MOV EBX, [RSI]*/ - addbyte(0x1e); - } - /* !--- ALERT: Crash-fixing patch begin. */ - addbyte(0x48); /*XOR RSI, RSI*/ - addbyte(0x31); - addbyte(0xf6); - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - /* !--- ALERT: Crash-fixing patch end. */ - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x18); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - if (IS_32_ADDR(writelookup2)) { - addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ - addbyte(0x48); - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf5); - addlong((uint32_t) (uintptr_t) writelookup2); - } else { - addbyte(0x48); /*MOV RDX, writelookup2*/ - addbyte(0xb8 | REG_EDX); - addquad((uint64_t) writelookup2); - addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ - addbyte(0x8b); - addbyte(0x34); - addbyte(0xf2); - } - addbyte(0x75); /*JNE slowpath*/ - addbyte(3 + 2 + ((host_reg & 8) ? 4 : 3) + 2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(((host_reg & 8) ? 4 : 3) + 2); - if (host_reg & 8) { - addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x89); - addbyte(0x04 | ((host_reg & 7) << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } else { - addbyte(0x89); /*MOV [RDI+RSI],host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - } - addbyte(0xeb); /*JMP done*/ - if (host_reg & 8) { - addbyte(2 + 2 + 3 + 12); - } else { - addbyte(2 + 2 + 2 + 12); - } - /*slowpath:*/ - load_param_2_reg_32(host_reg); - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - load_param_1_reg_32(REG_EBX); - call_long((uintptr_t) writememll); - /*done:*/ -} - -static __inline void -LOAD_SEG(int host_reg, void *seg) -{ - load_param_2_64(&codeblock[block_current], (uint64_t) seg); - load_param_1_reg_32(host_reg); - CALL_FUNC((uintptr_t) loadseg); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t) cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*JNE end*/ - addbyte(0x85); - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); -} diff --git a/src/cpu/codegen_timing_p6 - Cópia.c b/src/cpu/codegen_timing_p6 - Cópia.c deleted file mode 100644 index cce2ebe2c..000000000 --- a/src/cpu/codegen_timing_p6 - Cópia.c +++ /dev/null @@ -1,2162 +0,0 @@ -/*Basic P6 timing model by plant/nerd73. Based on the K6 timing model*/ -/*Some cycle timings come from https://www.agner.org/optimize/instruction_tables.pdf*/ -#include -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> -#include <86box/machine.h> -#include <86box/plat_unused.h> - -#include "x86.h" -#include "x86_ops.h" -#include "x86seg_common.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_ops.h" -#include "codegen_timing_common.h" - -typedef enum uop_type_t -{ - UOP_ALU0 = 0, /*Executes in port 0 ALU*/ - UOP_ALU1, /*Executes in port 1 ALU*/ - UOP_ALU01, /*Executes in either port 0 or 1 ALU*/ - UOP_BRANCH, /*Executes in port 1 branch*/ - UOP_LOAD, /*Executes in port 2 Load unit*/ - UOP_STOREADDR, /*Executes in port 3 Store Address unit*/ - UOP_STOREDATA, /*Executes in port 4 Store Data unit*/ - UOP_FLOAT, /*Executes in port 0 Floating Point unit*/ - UOP_ALU0_SEG /*Executes in port 0 ALU, loads segment, causing pipeline flush on PPro*/ -} uop_type_t; - -#define MAX_UOPS 300 - -typedef struct p6_uop_t -{ - uop_type_t type; - int throughput; - int latency; -} p6_uop_t; - -typedef struct p6_instruction_t -{ - int nr_uops; - p6_uop_t uop[MAX_UOPS]; -} p6_instruction_t; - -static const p6_instruction_t alu_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu0_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu1_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu01_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu4_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu6_op = -{ - .nr_uops = 6, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t aluc_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_alu_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_aluc_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu_store_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t alu0_store_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t aluc_store_op = -{ - .nr_uops = 6, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t branch_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t load_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} -}; - -static const p6_instruction_t store_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; - - -static const p6_instruction_t bswap_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t leave_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t lods_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t loop_op = -{ - .nr_uops = 11, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, -}; -static const p6_instruction_t movs_op = -{ - .nr_uops = 6, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, -}; -static const p6_instruction_t pop_reg_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t pop_mem_op = -{ - .nr_uops = 8, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t push_imm_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t push_mem_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, -}; -static const p6_instruction_t push_seg_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t rcx_op = -{ - .nr_uops = 8, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, -}; -static const p6_instruction_t rcx_store_op = -{ - .nr_uops = 11, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t stos_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t xchg_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t mmx_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t mmx_mul_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 3} -}; -static const p6_instruction_t mmx_shift_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_mmx_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_mmx_mul_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_mmx_shift_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t faddsub_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 3} -}; -static const p6_instruction_t load_faddsub_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 3} -}; -static const p6_instruction_t fbstp_op = -{ - .nr_uops = 5, - .uop[0] = {.type = UOP_FLOAT, .throughput = 165, .latency = 165}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t fcom_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_fcom_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t fcompp_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t fild_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_fi_op = -{ - .nr_uops = 7, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t fmul_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 5} -}; -static const p6_instruction_t load_fmul_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 5} -}; - -static const p6_instruction_t fxch_op = -{ - .nr_uops = 0 -}; - -static const p6_instruction_t fist_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t fdiv_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 37, .latency = 38} -}; -static const p6_instruction_t fdiv_mem_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 37, .latency = 38} -}; -static const p6_instruction_t fsin_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 62, .latency = 62} -}; -static const p6_instruction_t fsqrt_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 69, .latency = 69} -}; - -static const p6_instruction_t float_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t fldcw_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_FLOAT, .throughput = 7, .latency = 7}, -}; -static const p6_instruction_t flde_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t frstor_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 72, .latency = 72} -}; -static const p6_instruction_t fsave_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_FLOAT, .throughput = 141, .latency = 141} -}; -static const p6_instruction_t fste_op = -{ - .nr_uops = 6, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t fstsw_ax_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t fstsw_mem_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; - -static const p6_instruction_t aad_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 4}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t aam_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 4}, - .uop[2] = {.type = UOP_ALU1, .throughput = 1, .latency = 9}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t arpl_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_ALU01, .throughput = 3, .latency = 3}, - .uop[1] = {.type = UOP_ALU01, .throughput = 3, .latency = 3} -}; -static const p6_instruction_t bound_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU0, .throughput = 7, .latency = 7}, - .uop[3] = {.type = UOP_ALU01, .throughput = 6, .latency = 6} -}; -static const p6_instruction_t bsx_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t load_bsx_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t call_far_op = -{ - .nr_uops = 6, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0_SEG, .throughput = 28, .latency = 28} -}; -static const p6_instruction_t load_call_far_op = -{ - .nr_uops = 7, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU0_SEG, .throughput = 28, .latency = 28} -}; -static const p6_instruction_t cli_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU01, .throughput = 9, .latency = 9} -}; -static const p6_instruction_t sti_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU01, .throughput = 17, .latency = 17} -}; -static const p6_instruction_t cmps_op = -{ - .nr_uops = 6, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t cmpxchg_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t cpuid_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU0, .throughput = 48, .latency = 48} -}; -/*static const p6_instruction_t div8_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU0, .throughput = 12, .latency = 17}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -};*/ -/*static const p6_instruction_t div8_mem_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[0] = {.type = UOP_ALU0, .throughput = 12, .latency = 17}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -};*/ -static const p6_instruction_t div16_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU0, .throughput = 21, .latency = 21}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t div16_mem_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[0] = {.type = UOP_ALU0, .throughput = 21, .latency = 21}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t div32_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU0, .throughput = 35, .latency = 35}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t div32_mem_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[0] = {.type = UOP_ALU0, .throughput = 35, .latency = 35}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t emms_op = -{ - .nr_uops = 11, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t enter_op = -{ - .nr_uops = 14, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[11] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[12] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[13] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t io_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_LOAD, .throughput = 18, .latency = 18} -}; -static const p6_instruction_t ins_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_ALU0, .throughput = 18, .latency = 18}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t int_op = -{ - .nr_uops = 7, - .uop[0] = {.type = UOP_ALU0, .throughput = 20, .latency = 20}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, -}; -static const p6_instruction_t iret_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[3] = {.type = UOP_ALU01, .throughput = 20, .latency = 20}, -}; -static const p6_instruction_t invd_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU01, .throughput = 1000, .latency = 1000} -}; -static const p6_instruction_t jmp_far_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0_SEG, .throughput = 21, .latency = 21} -}; -static const p6_instruction_t load_jmp_far_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU0_SEG, .throughput = 21, .latency = 21} -}; -static const p6_instruction_t lss_op = -{ - .nr_uops = 11, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[3] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -/*static const p6_instruction_t mov_mem_seg_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, -};*/ -static const p6_instruction_t mov_seg_mem_op = -{ - .nr_uops = 9, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t mov_seg_reg_op = -{ - .nr_uops = 8, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t mul_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 4} -}; -static const p6_instruction_t mul_mem_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 4} -}; -static const p6_instruction_t outs_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 18, .latency = 18}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t pusha_op = -{ - .nr_uops = 18, - .uop[0] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[11] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[12] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[13] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[14] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[15] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[16] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[17] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t popa_op = -{ - .nr_uops = 10, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t popf_op = -{ - .nr_uops = 17, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[11] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[12] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[13] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[14] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[15] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[16] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, -}; -static const p6_instruction_t pushf_op = -{ - .nr_uops = 16, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[9] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[11] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[12] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[13] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[14] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[15] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t ret_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t reti_op = -{ - .nr_uops = 5, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_ALU1, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t retf_op = -{ - .nr_uops = 4, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[3] = {.type = UOP_ALU0, .throughput = 23, .latency = 23}, -}; -static const p6_instruction_t scas_op = -{ - .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t xchg_mem_op = -{ - .nr_uops = 7, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1} -}; -static const p6_instruction_t xlat_op = -{ - .nr_uops = 2, - .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} -}; -static const p6_instruction_t wbinvd_op = -{ - .nr_uops = 1, - .uop[0] = {.type = UOP_ALU0, .throughput = 10000, .latency = 10000} -}; - -#define INVALID NULL - -static const p6_instruction_t *opcode_timings[256] = -{ -/* ADD ADD ADD ADD*/ -/*00*/ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op, -/* ADD ADD PUSH ES POP ES*/ - &alu_op, &alu_op, &push_seg_op, &mov_seg_mem_op, -/* OR OR OR OR*/ - &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op, -/* OR OR PUSH CS */ - &alu_op, &alu_op, &push_seg_op, INVALID, - -/* ADC ADC ADC ADC*/ -/*10*/ &aluc_store_op, &aluc_store_op, &load_aluc_op, &load_aluc_op, -/* ADC ADC PUSH SS POP SS*/ - &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op, -/* SBB SBB SBB SBB*/ -/*10*/ &aluc_store_op, &aluc_store_op, &load_aluc_op, &load_aluc_op, -/* SBB SBB PUSH DS POP DS*/ - &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op, - -/* AND AND AND AND*/ -/*20*/ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op, -/* AND AND DAA*/ - &alu_op, &alu_op, INVALID, &alu1_op, -/* SUB SUB SUB SUB*/ - &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op, -/* SUB SUB DAS*/ - &alu_op, &alu_op, INVALID, &alu1_op, - -/* XOR XOR XOR XOR*/ -/*30*/ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op, -/* XOR XOR AAA*/ - &alu_op, &alu_op, INVALID, &alu1_op, -/* CMP CMP CMP CMP*/ - &load_alu_op, &load_alu_op, &load_alu_op, &load_alu_op, -/* CMP CMP AAS*/ - &alu_op, &alu_op, INVALID, &alu1_op, - -/* INC EAX INC ECX INC EDX INC EBX*/ -/*40*/ &alu_op, &alu_op, &alu_op, &alu_op, -/* INC ESP INC EBP INC ESI INC EDI*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* DEC EAX DEC ECX DEC EDX DEC EBX*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* DEC ESP DEC EBP DEC ESI DEC EDI*/ - &alu_op, &alu_op, &alu_op, &alu_op, - -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/*50*/ &store_op, &store_op, &store_op, &store_op, -/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ - &store_op, &store_op, &store_op, &store_op, -/* POP EAX POP ECX POP EDX POP EBX*/ - &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, -/* POP ESP POP EBP POP ESI POP EDI*/ - &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, - -/* PUSHA POPA BOUND ARPL*/ -/*60*/ &pusha_op, &popa_op, &bound_op, &arpl_op, - INVALID, INVALID, INVALID, INVALID, -/* PUSH imm IMUL PUSH imm IMUL*/ - &push_imm_op, &mul_op, &push_imm_op, &mul_op, -/* INSB INSW OUTSB OUTSW*/ - &ins_op, &ins_op, &outs_op, &outs_op, - -/* Jxx*/ -/*70*/ &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - -/*80*/ INVALID, INVALID, INVALID, INVALID, -/* TEST TEST XCHG XCHG*/ - &load_alu_op, &load_alu_op, &xchg_mem_op, &xchg_mem_op, -/* MOV MOV MOV MOV*/ - &store_op, &store_op, &load_op, &load_op, -/* MOV from seg LEA MOV to seg POP*/ - &store_op, &alu0_op, &mov_seg_mem_op, &pop_mem_op, - -/* NOP XCHG XCHG XCHG*/ -/*90*/ &alu_op, &xchg_op, &xchg_op, &xchg_op, -/* XCHG XCHG XCHG XCHG*/ - &xchg_op, &xchg_op, &xchg_op, &xchg_op, -/* CBW CWD CALL far WAIT*/ - &alu_op, &alu0_op, &call_far_op, &alu_op, -/* PUSHF POPF SAHF LAHF*/ - &pushf_op, &popf_op, &alu_op, &alu_op, - -/* MOV MOV MOV MOV*/ -/*a0*/ &load_op, &load_op, &store_op, &store_op, -/* MOVSB MOVSW CMPSB CMPSW*/ - &movs_op, &movs_op, &cmps_op, &cmps_op, -/* TEST TEST STOSB STOSW*/ - &load_alu_op, &load_alu_op, &stos_op, &stos_op, -/* LODSB LODSW SCASB SCASW*/ - &lods_op, &lods_op, &scas_op, &scas_op, - -/* MOV*/ -/*b0*/ &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - -/* RET imm RET*/ -/*c0*/ INVALID, INVALID, &reti_op, &ret_op, -/* LES LDS MOV MOV*/ - &lss_op, &lss_op, &store_op, &store_op, -/* ENTER LEAVE RETF RETF*/ - &enter_op, &leave_op, &retf_op, &retf_op, -/* INT3 INT INTO IRET*/ - &int_op, &int_op, &int_op, &iret_op, - - -/*d0*/ INVALID, INVALID, INVALID, INVALID, -/* AAM AAD SETALC XLAT*/ - &aam_op, &aad_op, &alu_op, &xlat_op, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, -/* LOOPNE LOOPE LOOP JCXZ*/ -/*e0*/ &loop_op, &loop_op, &loop_op, &loop_op, -/* IN AL IN AX OUT_AL OUT_AX*/ - &io_op, &io_op, &io_op, &io_op, -/* CALL JMP JMP JMP*/ - &store_op, &branch_op, &jmp_far_op, &branch_op, -/* IN AL IN AX OUT_AL OUT_AX*/ - &io_op, &io_op, &io_op, &io_op, - -/* REPNE REPE*/ -/*f0*/ INVALID, INVALID, INVALID, INVALID, -/* HLT CMC*/ - &alu4_op, &alu_op, INVALID, INVALID, -/* CLC STC CLI STI*/ - &alu_op, &alu_op, &cli_op, &sti_op, -/* CLD STD INCDEC*/ - &alu4_op, &alu4_op, &store_op, INVALID -}; - -static const p6_instruction_t *opcode_timings_mod3[256] = -{ -/* ADD ADD ADD ADD*/ -/*00*/ &alu_op, &alu_op, &alu_op, &alu_op, -/* ADD ADD PUSH ES POP ES*/ - &alu_op, &alu_op, &push_seg_op, &mov_seg_mem_op, -/* OR OR OR OR*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* OR OR PUSH CS */ - &alu_op, &alu_op, &push_seg_op, INVALID, - -/* ADC ADC ADC ADC*/ -/*10*/ &aluc_op, &aluc_op, &aluc_op, &aluc_op, -/* ADC ADC PUSH SS POP SS*/ - &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op, -/* SBB SBB SBB SBB*/ - &aluc_op, &aluc_op, &aluc_op, &aluc_op, -/* SBB SBB PUSH DS POP DS*/ - &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op, - -/* AND AND AND AND*/ -/*20*/ &alu_op, &alu_op, &alu_op, &alu_op, -/* AND AND DAA*/ - &alu_op, &alu_op, INVALID, &alu1_op, -/* SUB SUB SUB SUB*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* SUB SUB DAS*/ - &alu_op, &alu_op, INVALID, &alu1_op, - -/* XOR XOR XOR XOR*/ -/*30*/ &alu_op, &alu_op, &alu_op, &alu_op, -/* XOR XOR AAA*/ - &alu_op, &alu_op, INVALID, &alu1_op, -/* CMP CMP CMP CMP*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* CMP CMP AAS*/ - &alu_op, &alu_op, INVALID, &alu1_op, - -/* INC EAX INC ECX INC EDX INC EBX*/ -/*40*/ &alu_op, &alu_op, &alu_op, &alu_op, -/* INC ESP INC EBP INC ESI INC EDI*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* DEC EAX DEC ECX DEC EDX DEC EBX*/ - &alu_op, &alu_op, &alu_op, &alu_op, -/* DEC ESP DEC EBP DEC ESI DEC EDI*/ - &alu_op, &alu_op, &alu_op, &alu_op, - -/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ -/*50*/ &store_op, &store_op, &store_op, &store_op, -/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ - &store_op, &store_op, &store_op, &store_op, -/* POP EAX POP ECX POP EDX POP EBX*/ - &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, -/* POP ESP POP EBP POP ESI POP EDI*/ - &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, - -/* PUSHA POPA BOUND ARPL*/ -/*60*/ &pusha_op, &popa_op, &bound_op, &arpl_op, - INVALID, INVALID, INVALID, INVALID, -/* PUSH imm IMUL PUSH imm IMUL*/ - &push_imm_op, &mul_op, &push_imm_op, &mul_op, -/* INSB INSW OUTSB OUTSW*/ - &ins_op, &ins_op, &outs_op, &outs_op, - -/* Jxx*/ -/*70*/ &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - -/*80*/ INVALID, INVALID, INVALID, INVALID, -/* TEST TEST XCHG XCHG*/ - &alu_op, &alu_op, &xchg_op, &xchg_op, -/* MOV MOV MOV MOV*/ - &store_op, &store_op, &load_op, &load_op, -/* MOV from seg LEA MOV to seg POP*/ - &alu_op, &alu0_op, &mov_seg_reg_op, &pop_reg_op, - -/* NOP XCHG XCHG XCHG*/ -/*90*/ &alu_op, &xchg_op, &xchg_op, &xchg_op, -/* XCHG XCHG XCHG XCHG*/ - &xchg_op, &xchg_op, &xchg_op, &xchg_op, -/* CBW CWD CALL far WAIT*/ - &alu_op, &alu0_op, &call_far_op, &alu_op, -/* PUSHF POPF SAHF LAHF*/ - &pushf_op, &popf_op, &alu_op, &alu_op, - -/* MOV MOV MOV MOV*/ -/*a0*/ &load_op, &load_op, &store_op, &store_op, -/* MOVSB MOVSW CMPSB CMPSW*/ - &movs_op, &movs_op, &cmps_op, &cmps_op, -/* TEST TEST STOSB STOSW*/ - &alu_op, &alu_op, &stos_op, &stos_op, -/* LODSB LODSW SCASB SCASW*/ - &lods_op, &lods_op, &scas_op, &scas_op, - -/* MOV*/ -/*b0*/ &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - -/* RET imm RET*/ -/*c0*/ INVALID, INVALID, &reti_op, &ret_op, -/* LES LDS MOV MOV*/ - &lss_op, &lss_op, &store_op, &store_op, -/* ENTER LEAVE RETF RETF*/ - &enter_op, &leave_op, &retf_op, &retf_op, -/* INT3 INT INTO IRET*/ - &int_op, &int_op, &int_op, &iret_op, - - -/*d0*/ INVALID, INVALID, INVALID, INVALID, -/* AAM AAD SETALC XLAT*/ - &aam_op, &aad_op, &alu_op, &xlat_op, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, -/* LOOPNE LOOPE LOOP JCXZ*/ -/*e0*/ &loop_op, &loop_op, &loop_op, &loop_op, -/* IN AL IN AX OUT_AL OUT_AX*/ - &io_op, &io_op, &io_op, &io_op, -/* CALL JMP JMP JMP*/ - &store_op, &branch_op, &jmp_far_op, &branch_op, -/* IN AL IN AX OUT_AL OUT_AX*/ - &io_op, &io_op, &io_op, &io_op, - -/* REPNE REPE*/ -/*f0*/ INVALID, INVALID, INVALID, INVALID, -/* HLT CMC*/ - &alu4_op, &alu_op, INVALID, INVALID, -/* CLC STC CLI STI*/ - &alu_op, &alu_op, &cli_op, &sti_op, -/* CLD STD INCDEC*/ - &alu4_op, &alu4_op, &alu_op, INVALID -}; - -static const p6_instruction_t *opcode_timings_0f[256] = -{ -/*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, - INVALID, &alu6_op, &alu6_op, INVALID, - &invd_op, &wbinvd_op, INVALID, INVALID, - INVALID, &load_op, INVALID, INVALID, - -/*10*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*20*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, - &alu6_op, &alu6_op, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*30*/ &alu6_op, &alu6_op, &alu6_op, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*40*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*50*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*60*/ &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, - &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, - &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, - INVALID, INVALID, &load_op, &load_op, - -/*70*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, - &load_mmx_op, &load_mmx_op, &load_mmx_op, &emms_op, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, &store_op, &store_op, - -/*80*/ &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - -/*90*/ &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - -/*a0*/ &push_seg_op, &mov_seg_mem_op, &cpuid_op, &load_alu_op, - &alu_store_op, &alu_store_op, INVALID, INVALID, - &push_seg_op, &mov_seg_mem_op, INVALID, &load_alu_op, - &alu_store_op, &alu_store_op, INVALID, &mul_op, - -/*b0*/ &cmpxchg_op, &cmpxchg_op, &lss_op, &load_alu_op, - &lss_op, &lss_op, &load_alu_op, &load_alu_op, - INVALID, INVALID, &load_alu_op, &load_alu_op, - &load_bsx_op, &load_bsx_op, &load_alu_op, &load_alu_op, - -/*c0*/ &alu_store_op, &alu_store_op, INVALID, INVALID, - INVALID, INVALID, INVALID, &cmpxchg_op, - &bswap_op, &bswap_op, &bswap_op, &bswap_op, - &bswap_op, &bswap_op, &bswap_op, &bswap_op, - -/*d0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, - INVALID, &load_mmx_mul_op, INVALID, INVALID, - &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, - &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, - -/*e0*/ &load_mmx_op, &load_mmx_shift_op, &load_mmx_shift_op, INVALID, - INVALID, &load_mmx_mul_op, INVALID, INVALID, - &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, - &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, - -/*f0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, - INVALID, &load_mmx_mul_op, INVALID, INVALID, - &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, - &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, -}; -static const p6_instruction_t *opcode_timings_0f_mod3[256] = -{ -/*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, - INVALID, &alu6_op, &alu6_op, INVALID, - &invd_op, &wbinvd_op, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*10*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*20*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, - &alu6_op, &alu6_op, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*30*/ &alu6_op, &alu6_op, &alu6_op, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*40*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*50*/ INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/*60*/ &mmx_op, &mmx_op, &mmx_op, &mmx_op, - &mmx_op, &mmx_op, &mmx_op, &mmx_op, - &mmx_op, &mmx_op, &mmx_op, &mmx_op, - INVALID, INVALID, &mmx_op, &mmx_op, - -/*70*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, - &mmx_op, &mmx_op, &mmx_op, &emms_op, - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, &mmx_op, &mmx_op, - -/*80*/ &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - &branch_op, &branch_op, &branch_op, &branch_op, - -/*90*/ &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - &alu_op, &alu_op, &alu_op, &alu_op, - -/*a0*/ &push_seg_op, &mov_seg_mem_op, &cpuid_op, &alu_op, - &alu_op, &alu_op, INVALID, INVALID, - &push_seg_op, &mov_seg_mem_op, INVALID, &alu_op, - &alu_op, &alu_op, INVALID, &mul_op, - -/*b0*/ &cmpxchg_op, &cmpxchg_op, &lss_op, &alu_op, - &lss_op, &lss_op, &alu_op, &alu_op, - INVALID, INVALID, &alu_op, &alu_op, - &bsx_op, &bsx_op, &alu_op, &alu_op, - -/*c0*/ &alu_op, &alu_op, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - &bswap_op, &bswap_op, &bswap_op, &bswap_op, - &bswap_op, &bswap_op, &bswap_op, &bswap_op, - -/*d0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, - INVALID, &mmx_mul_op, INVALID, INVALID, - &mmx_op, &mmx_op, INVALID, &mmx_op, - &mmx_op, &mmx_op, INVALID, &mmx_op, - -/*e0*/ &mmx_op, &mmx_shift_op, &mmx_shift_op, INVALID, - INVALID, &mmx_mul_op, INVALID, INVALID, - &mmx_op, &mmx_op, INVALID, &mmx_op, - &mmx_op, &mmx_op, INVALID, &mmx_op, - -/*f0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, - INVALID, &mmx_mul_op, INVALID, INVALID, - &mmx_op, &mmx_op, &mmx_op, INVALID, - &mmx_op, &mmx_op, &mmx_op, INVALID, -}; - -static const p6_instruction_t *opcode_timings_shift[8] = -{ - &alu0_store_op, &alu0_store_op, &rcx_store_op, &rcx_store_op, - &alu0_store_op, &alu0_store_op, &alu0_store_op, &alu0_store_op -}; -static const p6_instruction_t *opcode_timings_shift_mod3[8] = -{ - &alu0_op, &alu0_op, &rcx_op, &rcx_op, - &alu0_op, &alu0_op, &alu0_op, &alu0_op -}; - -static const p6_instruction_t *opcode_timings_8x[8] = -{ - &alu_store_op, &alu_store_op, &aluc_store_op, &aluc_store_op, - &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, -}; -static const p6_instruction_t *opcode_timings_8x_mod3[8] = -{ - &alu_op, &alu_op, &aluc_op, &aluc_op, - &alu_op, &alu_op, &alu_op, &alu_op, -}; - -static const p6_instruction_t *opcode_timings_f6[8] = -{ -/* TST NOT NEG*/ - &load_alu_op, INVALID, &alu_store_op, &alu_store_op, -/* MUL IMUL DIV IDIV*/ - &mul_mem_op, &mul_mem_op, &div16_mem_op, &div16_mem_op, -}; -static const p6_instruction_t *opcode_timings_f6_mod3[8] = -{ -/* TST NOT NEG*/ - &alu_op, INVALID, &alu_op, &alu_op, -/* MUL IMUL DIV IDIV*/ - &mul_op, &mul_op, &div16_op, &div16_op, -}; -static const p6_instruction_t *opcode_timings_f7[8] = -{ -/* TST NOT NEG*/ - &load_alu_op, INVALID, &alu_store_op, &alu_store_op, -/* MUL IMUL DIV IDIV*/ - &mul_mem_op, &mul_mem_op, &div32_mem_op, &div32_mem_op, -}; -static const p6_instruction_t *opcode_timings_f7_mod3[8] = -{ -/* TST NOT NEG*/ - &alu_op, INVALID, &alu_op, &alu_op, -/* MUL IMUL DIV IDIV*/ - &mul_op, &mul_op, &div32_op, &div32_op, -}; -static const p6_instruction_t *opcode_timings_ff[8] = -{ -/* INC DEC CALL CALL far*/ - &alu_store_op, &alu_store_op, &store_op, &load_call_far_op, -/* JMP JMP far PUSH*/ - &branch_op, &load_jmp_far_op, &push_mem_op, INVALID -}; -static const p6_instruction_t *opcode_timings_ff_mod3[8] = -{ -/* INC DEC CALL CALL far*/ - &alu_op, &alu_op, &store_op, &call_far_op, -/* JMP JMP far PUSH*/ - &branch_op, &load_jmp_far_op, &push_mem_op, INVALID -}; - -static const p6_instruction_t *opcode_timings_d8[8] = -{ -/* FADDs FMULs FCOMs FCOMPs*/ - &load_faddsub_op, &load_fmul_op, &fcom_op, &load_fcom_op, -/* FSUBs FSUBRs FDIVs FDIVRs*/ - &load_faddsub_op, &load_faddsub_op, &fdiv_mem_op, &fdiv_mem_op, -}; -static const p6_instruction_t *opcode_timings_d8_mod3[8] = -{ -/* FADD FMUL FCOM FCOMP*/ - &faddsub_op, &fmul_op, &fcom_op, &fcom_op, -/* FSUB FSUBR FDIV FDIVR*/ - &faddsub_op, &faddsub_op, &fdiv_op, &fdiv_op, -}; - -static const p6_instruction_t *opcode_timings_d9[8] = -{ -/* FLDs FSTs FSTPs*/ - &load_op, INVALID, &store_op, &store_op, -/* FLDENV FLDCW FSTENV FSTCW*/ - &flde_op, &fldcw_op, &fste_op, &fstsw_mem_op -}; -static const p6_instruction_t *opcode_timings_d9_mod3[64] = -{ - /*FLD*/ - &float_op, &float_op, &float_op, &float_op, - &float_op, &float_op, &float_op, &float_op, - /*FXCH*/ - &fxch_op, &fxch_op, &fxch_op, &fxch_op, - &fxch_op, &fxch_op, &fxch_op, &fxch_op, - /*FNOP*/ - &float_op, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - /*FSTP*/ - &float_op, &float_op, &float_op, &float_op, - &float_op, &float_op, &float_op, &float_op, -/* opFCHS opFABS*/ - &float_op, &float_op, INVALID, INVALID, -/* opFTST opFXAM*/ - &float_op, &float_op, INVALID, INVALID, -/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/ - &float_op, &float_op, &float_op, &float_op, -/* opFLDEG2 opFLDLN2 opFLDZ*/ - &float_op, &float_op, &float_op, INVALID, -/* opF2XM1 opFYL2X opFPTAN opFPATAN*/ - &fsin_op, &fsin_op, &fsin_op, &fsin_op, -/* opFDECSTP opFINCSTP,*/ - INVALID, INVALID, &float_op, &float_op, -/* opFPREM opFSQRT opFSINCOS*/ - &fdiv_op, INVALID, &fsqrt_op, &fsin_op, -/* opFRNDINT opFSCALE opFSIN opFCOS*/ - &float_op, &fdiv_op, &fsin_op, &fsin_op -}; - -static const p6_instruction_t *opcode_timings_da[8] = -{ -/* FIADDl FIMULl FICOMl FICOMPl*/ - &load_fi_op, &load_fi_op, &load_fcom_op, &load_fcom_op, -/* FISUBl FISUBRl FIDIVl FIDIVRl*/ - &load_fi_op, &load_fi_op, &load_fi_op, &load_fi_op, -}; -static const p6_instruction_t *opcode_timings_da_mod3[8] = -{ - INVALID, INVALID, INVALID, INVALID, -/* FCOMPP*/ - INVALID, &fcompp_op, INVALID, INVALID -}; - -static const p6_instruction_t *opcode_timings_db[8] = -{ -/* FLDil FSTil FSTPil*/ - &fild_op, INVALID, &fist_op, &fist_op, -/* FLDe FSTPe*/ - INVALID, &flde_op, INVALID, &fste_op -}; -static const p6_instruction_t *opcode_timings_db_mod3[64] = -{ - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - -/* opFNOP opFCLEX opFINIT*/ - INVALID, &float_op, &float_op, &float_op, -/* opFNOP opFNOP*/ - &float_op, &float_op, INVALID, INVALID, - - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, - - INVALID, INVALID, INVALID, INVALID, - INVALID, INVALID, INVALID, INVALID, -}; - -static const p6_instruction_t *opcode_timings_dc[8] = -{ -/* FADDd FMULd FCOMd FCOMPd*/ - &load_faddsub_op, &load_fmul_op, &load_fcom_op, &load_fcom_op, -/* FSUBd FSUBRd FDIVd FDIVRd*/ - &load_faddsub_op, &load_faddsub_op, &fdiv_mem_op, &fdiv_mem_op, -}; -static const p6_instruction_t *opcode_timings_dc_mod3[8] = -{ -/* opFADDr opFMULr*/ - &faddsub_op, &fmul_op, INVALID, INVALID, -/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ - &faddsub_op, &faddsub_op, &fdiv_op, &fdiv_op -}; - -static const p6_instruction_t *opcode_timings_dd[8] = -{ -/* FLDd FSTd FSTPd*/ - &load_op, INVALID, &store_op, &store_op, -/* FRSTOR FSAVE FSTSW*/ - &frstor_op, INVALID, &fsave_op, &fstsw_mem_op -}; -static const p6_instruction_t *opcode_timings_dd_mod3[8] = -{ -/* FFFREE FST FSTP*/ - &float_op, INVALID, &float_op, &float_op, -/* FUCOM FUCOMP*/ - &float_op, &float_op, INVALID, INVALID -}; - -static const p6_instruction_t *opcode_timings_de[8] = -{ -/* FIADDw FIMULw FICOMw FICOMPw*/ - &load_fi_op, &load_fi_op, &load_fcom_op, &load_fcom_op, -/* FISUBw FISUBRw FIDIVw FIDIVRw*/ - &load_fi_op, &load_fi_op, &load_fi_op, &load_fi_op, -}; -static const p6_instruction_t *opcode_timings_de_mod3[8] = -{ -/* FADDP FMULP FCOMPP*/ - &faddsub_op, &fmul_op, INVALID, &fcompp_op, -/* FSUBP FSUBRP FDIVP FDIVRP*/ - &faddsub_op, &faddsub_op, &fdiv_op, &fdiv_op, -}; - -static const p6_instruction_t *opcode_timings_df[8] = -{ -/* FILDiw FISTiw FISTPiw*/ - &fild_op, INVALID, &fist_op, &fist_op, -/* FILDiq FBSTP FISTPiq*/ - INVALID, &fild_op, &fbstp_op, &fist_op, -}; -static const p6_instruction_t *opcode_timings_df_mod3[8] = -{ - INVALID, INVALID, INVALID, INVALID, -/* FSTSW AX*/ - &fstsw_ax_op, INVALID, INVALID, INVALID -}; - - -static uint8_t last_prefix; -static int prefixes; - -static int decode_timestamp; -static int last_complete_timestamp; - -typedef struct p6_unit_t -{ - const uint32_t uop_mask; - const int port; - int first_available_cycle; -} p6_unit_t; - -enum -{ - UNIT_INT0 = 0, - UNIT_INT1, - UNIT_FPU, - UNIT_MMX_ADD, - UNIT_MMX_MUL, - UNIT_JUMP, - UNIT_LOAD, - UNIT_STORE_ADDR, - UNIT_STORE_DATA -}; - -/*Each port can only be used once per clock*/ -typedef struct p6_port_t -{ - uint32_t unit_mask; -} p6_port_t; - -static int port_last_timestamps[5]; - -static const p6_port_t ports[] = -{ - {UNIT_INT0 | UNIT_FPU | UNIT_MMX_MUL}, - {UNIT_INT1 | UNIT_MMX_ADD | UNIT_JUMP}, - {UNIT_LOAD}, - {UNIT_STORE_ADDR}, - {UNIT_STORE_DATA} -}; -const int nr_ports = (sizeof(ports) / sizeof(p6_port_t)); - -static p6_unit_t units[] = -{ - [UNIT_INT0] = {.uop_mask = (1 << UOP_ALU0) | (1 << UOP_ALU0_SEG) | (1 << UOP_ALU01), .port = 0}, /*Integer 0*/ - [UNIT_INT1] = {.uop_mask = (1 << UOP_ALU1) | (1 << UOP_ALU01), .port = 1}, /*Integer 1*/ - [UNIT_FPU] = {.uop_mask = 1 << UOP_FLOAT, .port = 0}, - [UNIT_MMX_ADD] = {.uop_mask = 0, .port = 1}, - [UNIT_MMX_MUL] = {.uop_mask = 0, .port = 0}, - [UNIT_JUMP] = {.uop_mask = 1 << UOP_BRANCH, .port = 1}, - [UNIT_LOAD] = {.uop_mask = 1 << UOP_LOAD, .port = 2}, - [UNIT_STORE_ADDR] = {.uop_mask = 1 << UOP_STOREADDR, .port = 3}, - [UNIT_STORE_DATA] = {.uop_mask = 1 << UOP_STOREDATA, .port = 4} -}; -const int nr_units = (sizeof(units) / sizeof(p6_unit_t)); - -static int rat_timestamp = 0; -static int rat_uops = 0; - -static int uop_run(const p6_uop_t *uop, int decode_time) -{ - int c; - p6_unit_t *best_unit = NULL; - int best_start_cycle = 99999; - - /*Peak of 3 uOPs from decode to RAT per cycle*/ - if (decode_time < rat_timestamp) - decode_time = rat_timestamp; - else if (decode_time > rat_timestamp) - { - rat_timestamp = decode_time; - rat_uops = 0; - } - - rat_uops++; - if (rat_uops == 3) - { - rat_timestamp++; - rat_uops = 0; - } - - - /*Find execution unit for this uOP*/ - for (c = 0; c < nr_units; c++) - { - p6_unit_t *unit = &units[c]; - if (unit->uop_mask & (1 << uop->type)) - { - int start_cycle = MAX(unit->first_available_cycle, - port_last_timestamps[units[c].port]); - - if (start_cycle < best_start_cycle) - { - best_unit = unit; - best_start_cycle = start_cycle; - } - } - } - if (!best_unit) - fatal("uop_run: can not find execution unit %x\n", uop->type); - - if (cpu_s->cpu_type == CPU_PENTIUMPRO && uop->type == UOP_ALU0_SEG) - { - /*Pentium Pro will flush pipeline on a segment load. Find last - execution unit to complete, then set earliest start times on - _all_ execution units to after this point*/ - int last_start_cycle = 0; - - for (c = 0; c < nr_units; c++) - { - p6_unit_t *unit = &units[c]; - int start_cycle = unit->first_available_cycle; - - if (start_cycle > last_start_cycle) - last_start_cycle = start_cycle; - } - for (c = 0; c < nr_units; c++) - units[c].first_available_cycle = last_start_cycle+1; - } - if (best_start_cycle < decode_time) - best_start_cycle = decode_time; - best_unit->first_available_cycle = best_start_cycle + uop->throughput; - port_last_timestamps[best_unit->port] = best_start_cycle + 1; - - return best_start_cycle + uop->throughput; -// return decode_time+1; -} - -/*The P6 decoder can decode up to three instructions per clock - First can be up to 4 uOPs - Second and third must be 1 uOP each - Up to 16 bytes per cycle - 1 cycle per prefix beyond 1 prefix - 0x66 causes delays if instruction has immediate - 0x67 causes delays if modr/m present (and mod != 3) -*/ -static struct -{ - int nr_ins; - int nr_uops; - const p6_uop_t *uops[6]; - /*Earliest time a uop can start. If the timestamp is -1, then the uop is - part of a dependency chain and the start time is the completion time of - the previous uop*/ - int earliest_start[6]; -} decode_buffer; - -#define NR_REGS 8 -/*Timestamp of when last operation on an integer register completed*/ -static int reg_available_timestamp[NR_REGS]; -/*Timestamp of when last operation on an FPU register completed*/ -static int fpu_st_timestamp[8]; -/*Completion time of the last uop to be processed. Used to calculate timing of - dependent uop chains*/ -static int last_uop_timestamp = 0; - -static int ifetch_length = 0; -static int has_66_prefix, has_67_prefix; - -static void decode_flush(void) -{ - int c; - int uop_timestamp = 0; - - /*Ensure that uops can not be submitted before they have been decoded*/ - if (decode_timestamp > last_uop_timestamp) - last_uop_timestamp = decode_timestamp; - - /*Submit uops to execution units, and determine the latest completion time*/ - for (c = 0; c < decode_buffer.nr_uops; c++) - { - int start_timestamp; - -// pclog("uOP %i, %p\n", c, decode_buffer.uops[c]); - - if (decode_buffer.earliest_start[c] == -1) - start_timestamp = last_uop_timestamp; - else - start_timestamp = decode_buffer.earliest_start[c]; - - last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); - if (last_uop_timestamp > uop_timestamp) - uop_timestamp = last_uop_timestamp; - } - - /*Calculate opquad completion time. Since opquads complete in order, it - must be after the last completion.*/ - if (uop_timestamp <= last_complete_timestamp) - last_complete_timestamp = last_complete_timestamp + 1; - else - last_complete_timestamp = uop_timestamp; - - decode_timestamp++; - decode_buffer.nr_uops = 0; - decode_buffer.nr_ins = 0; - ifetch_length = 0; -} - -/*The instruction is only of interest here if it's longer than 8 bytes, as that's the - limit on P6 short decoding*/ -static int codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) -{ - int len = prefixes + 1; /*Opcode*/ - if (deps & MODRM) - { - len++; /*ModR/M*/ - if (deps & HAS_IMM8) - len++; - if (deps & HAS_IMM1632) - len += (op_32 & 0x100) ? 4 : 2; - - if (op_32 & 0x200) - { - if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) - { - /* Has SIB*/ - len++; - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0x700) == 0x500) - len += 4; - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 4; - else if ((fetchdat & 0xc7) == 0x05) - len += 4; - } - } - else - { - if ((fetchdat & 0xc0) == 0x40) - len++; - else if ((fetchdat & 0xc0) == 0x80) - len += 2; - else if ((fetchdat & 0xc7) == 0x06) - len += 2; - } - } - - return len; -} - -static void decode_instruction(const p6_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, uint32_t op_pc, int bit8) -{ - uint32_t regmask_required; - uint32_t regmask_modified; - int c, d; - int earliest_start; - int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); - - if (has_66_prefix && (deps & HAS_IMM1632)) - decode_timestamp += 2; - if (has_67_prefix && (deps & MODRM)) - decode_timestamp += 4; - - earliest_start = decode_timestamp; - - /*Generate input register mask, and determine the earliest time this - instruction can start. This is not accurate, as this is calculated per - x86 instruction when it should be handled per uop*/ - regmask_required = get_dstdep_mask(deps, fetchdat, bit8); - regmask_required |= get_addr_regmask(deps, fetchdat, op_32); - for (c = 0; c < 8; c++) - { - if (regmask_required & (1 << c)) - { - if (reg_available_timestamp[c] > decode_timestamp) - earliest_start = reg_available_timestamp[c]; - } - } - if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) - earliest_start = fpu_st_timestamp[0]; - if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) - earliest_start = fpu_st_timestamp[1]; - if ((deps & FPU_RW_STREG)) - { - int reg = fetchdat & 7; - - if (fpu_st_timestamp[reg] > decode_timestamp) - earliest_start = fpu_st_timestamp[reg]; - } - -// pclog("ins->nr_uops=%i decode_buffer.nr_uops=%i decode_buffer.nr_ins=%i instr_length=%i\n", ins->nr_uops, decode_buffer.nr_uops, decode_buffer.nr_ins, instr_length); - - /*Can only decode 16 bytes per cycle*/ - if ((ifetch_length + instr_length) > 16) - decode_flush(); - else - ifetch_length += instr_length; - - if (ins->nr_uops > 4) - { -// pclog("Long decode\n"); - /*Multi-cycle decode (> 4 uOPs) instruction*/ - if (decode_buffer.nr_ins) - decode_flush(); - - d = 0; - - for (c = 0; c < ins->nr_uops; c++) - { - decode_buffer.uops[d] = &ins->uop[c]; - if (c == 0) - decode_buffer.earliest_start[d] = earliest_start; - else - decode_buffer.earliest_start[d] = -1; - d++; - - if (d == 4) - { - d = 0; - decode_buffer.nr_uops = 4; - decode_flush(); - } - } - if (d) - { - decode_buffer.nr_uops = d; - decode_flush(); - } - } - else if (ins->nr_uops > 1 || instr_length > 8) - { -// pclog("Mid decode\n"); - /*Long (> 1 uOPs) instruction*/ - if (decode_buffer.nr_ins) - decode_flush(); - - decode_buffer.nr_uops = ins->nr_uops; - - for (c = 0; c < ins->nr_uops; c++) - { - decode_buffer.uops[c] = &ins->uop[c]; - if (c == 0) - decode_buffer.earliest_start[c] = earliest_start; - else - decode_buffer.earliest_start[c] = -1; - } - decode_buffer.nr_ins++; - } - else if (ins->nr_uops == 1) - { -// pclog("Short decode\n"); - /*Short (1 uOP) instruction*/ - decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; - decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; - decode_buffer.nr_ins++; - decode_buffer.nr_uops++; - - if (decode_buffer.nr_ins == 3) - decode_flush(); - } - - /*Update write timestamps for any output registers*/ - regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); - for (c = 0; c < 8; c++) - { - if (regmask_modified & (1 << c)) - reg_available_timestamp[c] = last_complete_timestamp; - } - if (deps & FPU_POP) - { - for (c = 0; c < 7; c++) - fpu_st_timestamp[c] = fpu_st_timestamp[c+1]; - fpu_st_timestamp[7] = 0; - } - if (deps & FPU_POP2) - { - for (c = 0; c < 6; c++) - fpu_st_timestamp[c] = fpu_st_timestamp[c+2]; - fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; - } - if (deps & FPU_PUSH) - { - for (c = 0; c < 7; c++) - fpu_st_timestamp[c+1] = fpu_st_timestamp[c]; - fpu_st_timestamp[0] = 0; - } - if (deps & FPU_WRITE_ST0) - fpu_st_timestamp[0] = last_complete_timestamp; - if (deps & FPU_WRITE_ST1) - fpu_st_timestamp[1] = last_complete_timestamp; - if (deps & FPU_WRITE_STREG) - { - int reg = fetchdat & 7; - if (deps & FPU_POP) - reg--; - if (reg >= 0 && - !(reg == 0 && (deps & FPU_WRITE_ST0)) && - !(reg == 1 && (deps & FPU_WRITE_ST1))) - fpu_st_timestamp[reg] = last_complete_timestamp; - } -} - -void codegen_timing_p6_block_start(void) -{ - int c; - - for (c = 0; c < nr_units; c++) - units[c].first_available_cycle = 0; - - decode_timestamp = 0; - last_complete_timestamp = 0; - - rat_timestamp = 0; - rat_uops = 0; - - for (c = 0; c < 5; c++) - port_last_timestamps[c] = 0; - - for (c = 0; c < NR_REGS; c++) - reg_available_timestamp[c] = 0; - for (c = 0; c < 8; c++) - fpu_st_timestamp[c] = 0; - - ifetch_length = 0; -} - -void codegen_timing_p6_start(void) -{ -// units = p6_units; -// nr_units = NR_P6_UNITS; - last_prefix = 0; - prefixes = 0; - has_66_prefix = 0; - has_67_prefix = 0; -} - -/*Prefixes : - - first is free - - operand size prefix has a penalty of 'a few clocks' if instruction has 16 or - 32 bit immediate - - address size prefix has penalty if instruction has explicit memory operand*/ -void codegen_timing_p6_prefix(uint8_t prefix, uint32_t fetchdat) -{ - if (last_prefix) /*First prefix is free*/ - decode_timestamp++; - if (prefix == 0x66) - has_66_prefix = 1; - if (prefix == 0x67) - has_67_prefix = 1; - - last_prefix = prefix; - prefixes++; -} - -void codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) -{ - const p6_instruction_t **ins_table; - uint64_t *deps; - int mod3 = ((fetchdat & 0xc0) == 0xc0); - int old_last_complete_timestamp = last_complete_timestamp; - int bit8 = !(opcode & 1); - -// pclog("timing_opcode %02x\n", opcode); - switch (last_prefix) - { - case 0x0f: - ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; - deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; -// pclog("timings 0f\n"); - break; - - case 0xd8: - ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; - deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; - opcode = (opcode >> 3) & 7; -// pclog("timings d8\n"); - break; - case 0xd9: - ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; - deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; -// pclog("timings d9\n"); - break; - case 0xda: - ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; - deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; - opcode = (opcode >> 3) & 7; -// pclog("timings da\n"); - break; - case 0xdb: - ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; - deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; - opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; -// pclog("timings db\n"); - break; - case 0xdc: - ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; - deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; - opcode = (opcode >> 3) & 7; -// pclog("timings dc\n"); - break; - case 0xdd: - ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; - deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; - opcode = (opcode >> 3) & 7; -// pclog("timings dd\n"); - break; - case 0xde: - ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; - deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; - opcode = (opcode >> 3) & 7; -// pclog("timings de\n"); - break; - case 0xdf: - ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; - deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; - opcode = (opcode >> 3) & 7; -// pclog("timings df\n"); - break; - - default: - switch (opcode) - { - case 0x80: case 0x81: case 0x82: case 0x83: - ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; - opcode = (fetchdat >> 3) & 7; -// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x); - break; - - case 0xc0: case 0xd0: case 0xd2: - case 0xc1: case 0xd1: case 0xd3: - ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; - deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; - opcode = (fetchdat >> 3) & 7; -// pclog("timings c1\n"); - break; - - case 0xf6: - ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; - deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; - opcode = (fetchdat >> 3) & 7; -// pclog("timings f6\n"); - break; - case 0xf7: - ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; - deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; - opcode = (fetchdat >> 3) & 7; -// pclog("timings f7\n"); - break; - case 0xff: - ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; - deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; - opcode = (fetchdat >> 3) & 7; -// pclog("timings ff\n"); - break; - - default: - ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; - deps = mod3 ? opcode_deps_mod3 : opcode_deps; -// pclog("timings normal\n"); - break; - } - } - - if (ins_table[opcode]) - decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, op_pc, bit8); - else - decode_instruction(&alu01_op, 0, fetchdat, op_32, op_pc, bit8); - codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); -} - -void codegen_timing_p6_block_end(void) -{ - if (decode_buffer.nr_ins) - { - int old_last_complete_timestamp = last_complete_timestamp; - decode_flush(); - codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); - } -// pclog("codegen_block_cycles=%i\n", codegen_block_cycles); -} - -int codegen_timing_p6_jump_cycles(void) -{ - if (decode_buffer.nr_uops) - return 1; - return 0; -} - -codegen_timing_t codegen_timing_p6 = -{ - codegen_timing_p6_start, - codegen_timing_p6_prefix, - codegen_timing_p6_opcode, - codegen_timing_p6_block_start, - codegen_timing_p6_block_end, - codegen_timing_p6_jump_cycles -}; diff --git a/src/cpu/error_log.txt b/src/cpu/error_log.txt deleted file mode 100644 index 015f1921d..000000000 --- a/src/cpu/error_log.txt +++ /dev/null @@ -1,29 +0,0 @@ -808x.c: In function 'execx86': -808x.c:1912:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 1912 | case 0x40 ... 0x47: /* INC r16 */ - | ^~~~ -808x.c:1927:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 1927 | case 0x48 ... 0x4f: /* DEC r16 */ - | ^~~~ -808x.c:1942:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 1942 | case 0x50 ... 0x57: /* PUSH r16 */ - | ^~~~ -808x.c:1947:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 1947 | case 0x58 ... 0x5f: /* POP r16 */ - | ^~~~ -808x.c:1952:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 1952 | case 0x60 ... 0x7f: /* JMP rel8 */ - | ^~~~ -808x.c:2201:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 2201 | case 0x90 ... 0x97: /* XCHG AX, r */ - | ^~~~ -808x.c:2482:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 2482 | case 0xb0 ... 0xb7: /* MOV r8, imm8 */ - | ^~~~ -808x.c:2494:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 2494 | case 0xb8 ... 0xbf: /* MOV r16, imm16 */ - | ^~~~ -808x.c:2766:13: error: range expressions in switch statements are non-standard [-Werror=pedantic] - 2766 | case 0xd8 ... 0xdf: /* ESC - FPU instructions. */ - | ^~~~ -cc1.exe: all warnings being treated as errors diff --git a/src/cpu/gcc_check.sh b/src/cpu/gcc_check.sh deleted file mode 100644 index 904b1dca0..000000000 --- a/src/cpu/gcc_check.sh +++ /dev/null @@ -1 +0,0 @@ -gcc $1 -std=gnu17 -Wall -Wclobbered -Wbad-function-cast -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers -Wmissing-parameter-type -Wold-style-declaration -Woverride-init -Wsign-compare -Wtype-limits -Wuninitialized -Wunknown-pragmas -pedantic -Werror -I../include -iquote . 2> error_log.txt diff --git a/src/device/serial - Cópia.c b/src/device/serial - Cópia.c deleted file mode 100644 index 80fafefc6..000000000 --- a/src/device/serial - Cópia.c +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * NS8250/16450/16550 UART emulation. - * - * Now passes all the AMIDIAG tests. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/timer.h> -#include <86box/machine.h> -#include <86box/io.h> -#include <86box/pic.h> -#include <86box/mem.h> -#include <86box/rom.h> -#include <86box/fifo.h> -#include <86box/serial.h> -#include <86box/mouse.h> - -serial_port_t com_ports[SERIAL_MAX]; - -enum { - SERIAL_INT_LSR = 1, - SERIAL_INT_TIMEOUT = 2, - SERIAL_INT_RECEIVE = 4, - SERIAL_INT_TRANSMIT = 8, - SERIAL_INT_MSR = 16, - SERIAL_INT_RX_DMA_TC = 32, - SERIAL_INT_TX_DMA_TC = 64 -}; - -void serial_update_ints(serial_t *dev); - -static int next_inst = 0; -static serial_device_t serial_devices[SERIAL_MAX]; - -// #define ENABLE_SERIAL_CONSOLE 1 - -#ifdef ENABLE_SERIAL_LOG -int serial_do_log = ENABLE_SERIAL_LOG; - -static void -serial_log(const char *fmt, ...) -{ - va_list ap; - - if (serial_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define serial_log(fmt, ...) -#endif - -void -serial_reset_port(serial_t *dev) -{ - dev->lsr = 0x60; /* Mark that both THR/FIFO and TXSR are empty. */ - dev->iir = dev->ier = dev->lcr = dev->fcr = 0; - dev->fifo_enabled = 0; - dev->xmit_fifo_pos = 0; - dev->xmit_fifo_end = 0; - dev->baud_cycles = 0; - dev->out_new = 0xffff; - memset(dev->xmit_fifo, 0, 16); - - serial_update_ints(dev); - dev->irq_state = 0; -} - -void -serial_transmit_period(serial_t *dev) -{ - double ddlab; - - if (dev->dlab != 0x0000) - ddlab = (double) dev->dlab; - else - ddlab = 65536.0; - - /* Bit period based on DLAB. */ - dev->transmit_period = (16000000.0 * ddlab) / dev->clock_src; - if (dev->sd && dev->sd->transmit_period_callback) - dev->sd->transmit_period_callback(dev, dev->sd->priv, dev->transmit_period); -} - -void -serial_do_irq(serial_t *dev, int set) -{ - if (dev->irq != 0xff) { - if (set || (dev->irq_state != !!set)) - picint_common(1 << dev->irq, !!(dev->type >= SERIAL_16450), set, &dev->irq_state); - if (dev->type < SERIAL_16450) - dev->irq_state = !!set; - } -} - -#if 0 -void -serial_update_ints(serial_t *dev) -{ - int stat = 0; - - dev->iir = 0x01; - - if ((dev->ier & 0x04) && (dev->int_status & SERIAL_INT_LSR)) { - /* Line status interrupt */ - stat = 1; - dev->iir = 0x06; - } else if ((dev->ier & 0x01) && (dev->int_status & SERIAL_INT_TIMEOUT)) { - /* Received data available */ - stat = 1; - dev->iir = 0x0c; - } else if ((dev->ier & 0x01) && (dev->int_status & SERIAL_INT_RECEIVE)) { - /* Received data available */ - stat = 1; - dev->iir = 0x04; - } else if ((dev->ier & 0x02) && (dev->int_status & SERIAL_INT_TRANSMIT)) { - /* Transmit data empty */ - stat = 1; - dev->iir = 0x02; - } else if ((dev->ier & 0x08) && (dev->int_status & SERIAL_INT_MSR)) { - /* Modem status interrupt */ - stat = 1; - dev->iir = 0x00; - } else if ((dev->ier & 0x40) && (dev->int_status & SERIAL_INT_RX_DMA_TC)) { - /* DMA Reception End of Transfer interrupt */ - stat = 1; - dev->iir = 0x0e; - } else if ((dev->ier & 0x80) && (dev->int_status & SERIAL_INT_TX_DMA_TC)) { - /* DMA Transmission End of Transfer interrupt */ - stat = 1; - dev->iir = 0x0a; - } - - serial_do_irq(dev, stat && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))); -} -#else -void -serial_update_ints(serial_t *dev) -{ - /* TODO: The IRQ priorities are 6 - we need to find a way to treat timeout and receive - as equal and still somehow distinguish them. */ - uint8_t ier_map[7] = { 0x04, 0x01, 0x01, 0x02, 0x08, 0x40, 0x80 }; - uint8_t iir_map[7] = { 0x06, 0x0c, 0x04, 0x02, 0x00, 0x0e, 0x0a }; - int i; - - dev->iir = (dev->iir & 0xf0) | 0x01; - - for (i = 0; i < 7; i++) { - if ((dev->ier & ier_map[i]) && (dev->int_status & (1 << i))) { - dev->iir = (dev->iir & 0xf0) | iir_map[i]; - break; - } - } - - serial_do_irq(dev, !(dev->iir & 0x01) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))); -} -#endif - -static void -serial_clear_timeout(serial_t *dev) -{ - /* Disable timeout timer and clear timeout condition. */ - timer_disable(&dev->timeout_timer); - dev->int_status &= ~SERIAL_INT_TIMEOUT; - serial_update_ints(dev); -} - -static void -serial_receive_timer(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - // serial_log("serial_receive_timer()\n"); - - timer_on_auto(&dev->receive_timer, /* dev->bits * */ dev->transmit_period); - - if (dev->fifo_enabled) { - /* FIFO mode. */ - if (dev->out_new != 0xffff) { - /* We have received a byte into the RSR. */ - - /* Clear FIFO timeout. */ - serial_clear_timeout(dev); - - fifo_write_evt((uint8_t) (dev->out_new & 0xff), dev->rcvr_fifo); - dev->out_new = 0xffff; - - /* pclog("serial_receive_timer(): lsr = %02X, ier = %02X, iir = %02X, int_status = %02X\n", - dev->lsr, dev->ier, dev->iir, dev->int_status); */ - - timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); - } - } else { - /* Non-FIFO mode. */ - if (dev->out_new != 0xffff) { - /* We have received a byte into the RSR. */ - // pclog("Byte received: %04X\n", dev->out_new); - - /* Indicate overrun. */ - if (dev->lsr & 0x01) - dev->lsr |= 0x02; - - dev->dat = (uint8_t) (dev->out_new & 0xff); - dev->out_new = 0xffff; - - /* Raise Data Ready interrupt. */ - dev->lsr |= 0x01; - dev->int_status |= SERIAL_INT_RECEIVE; - - serial_update_ints(dev); - } - } -} - -static void -write_fifo(serial_t *dev, uint8_t dat) -{ - serial_log("write_fifo(%08X, %02X, %i, %i)\n", dev, dat, - (dev->type >= SERIAL_16550) && dev->fifo_enabled, - ((dev->type >= SERIAL_16550) && dev->fifo_enabled) ? - fifo_get_count(dev->rcvr_fifo) : 0); - - /* Do this here, because in non-FIFO mode, this is read directly. */ - dev->out_new = (uint16_t) dat; -} - -void -serial_write_fifo(serial_t *dev, uint8_t dat) -{ - serial_log("serial_write_fifo(%08X, %02X, %i, %i)\n", dev, dat, - (dev->type >= SERIAL_16550) && dev->fifo_enabled, - ((dev->type >= SERIAL_16550) && dev->fifo_enabled) ? - fifo_get_count(dev->rcvr_fifo) : 0); - - if (!(dev->mctrl & 0x10)) - write_fifo(dev, dat); -} - -void -serial_transmit(serial_t *dev, uint8_t val) -{ - if (dev->mctrl & 0x10) { - // pclog("Write to loopback: %02X\n", val); - write_fifo(dev, val); - } else if (dev->sd->dev_write) { - // pclog("Write to device : %02X\n", val); - dev->sd->dev_write(dev, dev->sd->priv, val); - } // else - // pclog("Write to nowhere : %02X\n", val); -#ifdef ENABLE_SERIAL_CONSOLE - if ((val >= ' ' && val <= '~') || val == '\r' || val == '\n') { - fputc(val, stdout); - if (val == '\n') - fflush(stdout); - } else { - fprintf(stdout, "[%02X]", val); - } -#endif -} - -static void -serial_move_to_txsr(serial_t *dev) -{ - if (dev->fifo_enabled) { - dev->txsr = dev->xmit_fifo[0]; - if (dev->xmit_fifo_pos > 0) { - /* Move the entire fifo forward by one byte. */ - for (uint8_t i = 1; i < 16; i++) - dev->xmit_fifo[i - 1] = dev->xmit_fifo[i]; - /* Decrease FIFO position. */ - dev->xmit_fifo_pos--; - } - } else { - dev->txsr = dev->thr; - dev->thr = 0; - } - - dev->lsr &= ~0x40; - serial_log("serial_move_to_txsr(): FIFO %sabled, FIFO pos = %i\n", dev->fifo_enabled ? "en" : "dis", dev->xmit_fifo_pos & 0x0f); - - if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 0x0)) { - /* Update interrupts to signal THRE and that TXSR is no longer empty. */ - dev->lsr |= 0x20; - dev->int_status |= SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - } - if (dev->transmit_enabled & 2) - dev->baud_cycles++; - else - dev->baud_cycles = 0; /* If not moving while transmitting, reset BAUDOUT cycle count. */ - if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 0x0)) - dev->transmit_enabled &= ~1; /* Stop moving. */ - dev->transmit_enabled |= 2; /* Start transmitting. */ -} - -static void -serial_process_txsr(serial_t *dev) -{ - serial_log("serial_process_txsr(): FIFO %sabled\n", dev->fifo_enabled ? "en" : "dis"); - serial_transmit(dev, dev->txsr); - dev->txsr = 0; - /* Reset BAUDOUT cycle count. */ - dev->baud_cycles = 0; - /* If FIFO is enabled and there are bytes left to transmit, - continue with the FIFO, otherwise stop. */ - if (dev->fifo_enabled && (dev->xmit_fifo_pos != 0x0)) - dev->transmit_enabled |= 1; - else { - /* Both FIFO/THR and TXSR are empty. */ - /* If bit 5 is set, also set bit 6 to mark both THR and shift register as empty. */ - if (dev->lsr & 0x20) - dev->lsr |= 0x40; - dev->transmit_enabled &= ~2; - } - dev->int_status &= ~SERIAL_INT_TRANSMIT; - serial_update_ints(dev); -} - -/* Transmit_enable flags: - Bit 0 = Do move if set; - Bit 1 = Do transmit if set. */ -static void -serial_transmit_timer(void *priv) -{ - serial_t *dev = (serial_t *) priv; - int delay = 8; /* STOP to THRE delay is 8 BAUDOUT cycles. */ - - if (dev->transmit_enabled & 3) { - if ((dev->transmit_enabled & 1) && (dev->transmit_enabled & 2)) - delay = dev->data_bits; /* Delay by less if already transmitting. */ - - dev->baud_cycles++; - - /* We have processed (total bits) BAUDOUT cycles, transmit the byte. */ - if ((dev->baud_cycles == dev->bits) && (dev->transmit_enabled & 2)) - serial_process_txsr(dev); - - /* We have processed (data bits) BAUDOUT cycles. */ - if ((dev->baud_cycles == delay) && (dev->transmit_enabled & 1)) - serial_move_to_txsr(dev); - - if (dev->transmit_enabled & 3) - timer_on_auto(&dev->transmit_timer, dev->transmit_period); - } else { - dev->baud_cycles = 0; - return; - } -} - -static void -serial_timeout_timer(void *priv) -{ - serial_t *dev = (serial_t *) priv; - -#ifdef ENABLE_SERIAL_LOG - serial_log("serial_timeout_timer()\n"); -#endif - - dev->lsr |= 0x01; - dev->int_status |= SERIAL_INT_TIMEOUT; - serial_update_ints(dev); -} - -void -serial_device_timeout(void *priv) -{ - serial_t *dev = (serial_t *) priv; - -#ifdef ENABLE_SERIAL_LOG - serial_log("serial_device_timeout()\n"); -#endif - - if (!dev->fifo_enabled) { - dev->lsr |= 0x10; - dev->int_status |= SERIAL_INT_LSR; - serial_update_ints(dev); - } -} - -static void -serial_update_speed(serial_t *dev) -{ - // pclog("serial_update_speed(%lf)\n", dev->transmit_period); - timer_on_auto(&dev->receive_timer, /* dev->bits * */ dev->transmit_period); - - if (dev->transmit_enabled & 3) - timer_on_auto(&dev->transmit_timer, dev->transmit_period); - - if (timer_is_enabled(&dev->timeout_timer)) - timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); -} - -static void -serial_reset_fifo(serial_t *dev) -{ - dev->lsr = (dev->lsr & 0x9f) | 0x60; - dev->int_status = (dev->int_status & ~SERIAL_INT_TRANSMIT) | SERIAL_INT_TRANSMIT; - dev->xmit_fifo_pos = 0; - - fifo_reset_evt(dev->rcvr_fifo); - - serial_update_ints(dev); -} - -void -serial_set_dsr(serial_t *dev, uint8_t enabled) -{ - if (dev->mctrl & 0x10) - return; - - dev->msr &= ~0x2; - dev->msr |= ((dev->msr & 0x20) ^ ((!!enabled) << 5)) >> 4; - dev->msr &= ~0x20; - dev->msr |= (!!enabled) << 5; - dev->msr_set &= ~0x20; - dev->msr_set |= (!!enabled) << 5; - - if (dev->msr & 0x2) { - dev->int_status |= SERIAL_INT_MSR; - serial_update_ints(dev); - } -} - -void -serial_set_cts(serial_t *dev, uint8_t enabled) -{ - if (dev->mctrl & 0x10) - return; - - dev->msr &= ~0x1; - dev->msr |= ((dev->msr & 0x10) ^ ((!!enabled) << 4)) >> 4; - dev->msr &= ~0x10; - dev->msr |= (!!enabled) << 4; - dev->msr_set &= ~0x10; - dev->msr_set |= (!!enabled) << 4; - - if (dev->msr & 0x1) { - dev->int_status |= SERIAL_INT_MSR; - serial_update_ints(dev); - } -} - -void -serial_set_dcd(serial_t *dev, uint8_t enabled) -{ - if (dev->mctrl & 0x10) - return; - - dev->msr &= ~0x8; - dev->msr |= ((dev->msr & 0x80) ^ ((!!enabled) << 7)) >> 4; - dev->msr &= ~0x80; - dev->msr |= (!!enabled) << 7; - dev->msr_set &= ~0x80; - dev->msr_set |= (!!enabled) << 7; - - if (dev->msr & 0x8) { - dev->int_status |= SERIAL_INT_MSR; - serial_update_ints(dev); - } -} - -void -serial_set_clock_src(serial_t *dev, double clock_src) -{ - dev->clock_src = clock_src; - - serial_transmit_period(dev); - serial_update_speed(dev); -} - -void -serial_write(uint16_t addr, uint8_t val, void *p) -{ - serial_t *dev = (serial_t *) p; - uint8_t new_msr; - uint8_t old; - - // serial_log("UART: Write %02X to port %02X\n", val, addr); - serial_log("UART: [%04X:%08X] Write %02X to port %02X\n", CS, cpu_state.pc, val, addr); - - cycles -= ISA_CYCLES(8); - - switch (addr & 7) { - case 0: - if (dev->lcr & 0x80) { - dev->dlab = (dev->dlab & 0xff00) | val; - serial_transmit_period(dev); - serial_update_speed(dev); - return; - } - - // pclog("Serial write: %02X\n", val); - - /* Indicate FIFO/THR is no longer empty. */ - dev->lsr &= 0x9f; - dev->int_status &= ~SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - - if (dev->fifo_enabled && (dev->xmit_fifo_pos < 16)) { - /* FIFO mode, begin transmitting. */ - timer_on_auto(&dev->transmit_timer, dev->transmit_period); - dev->transmit_enabled |= 1; /* Start moving. */ - dev->xmit_fifo[dev->xmit_fifo_pos++] = val; - } else if (!dev->fifo_enabled) { - /* Non-FIFO mode, begin transmitting. */ - timer_on_auto(&dev->transmit_timer, dev->transmit_period); - dev->transmit_enabled |= 1; /* Start moving. */ - dev->thr = val; - } - break; - case 1: - if (dev->lcr & 0x80) { - dev->dlab = (dev->dlab & 0x00ff) | (val << 8); - serial_transmit_period(dev); - serial_update_speed(dev); - return; - } - if ((val & 2) && (dev->lsr & 0x20)) - dev->int_status |= SERIAL_INT_TRANSMIT; - dev->ier = val & 0xf; - serial_update_ints(dev); - break; - case 2: - if (dev->type >= SERIAL_16550) { - if ((val ^ dev->fcr) & 0x01) - serial_reset_fifo(dev); - dev->fcr = val & 0xf9; - dev->fifo_enabled = val & 0x01; - /* TODO: When switching modes, shouldn't we reset the LSR - based on the new conditions? */ - if (!dev->fifo_enabled) { - memset(dev->xmit_fifo, 0, 16); - dev->xmit_fifo_pos = 0; - fifo_reset(dev->rcvr_fifo); - break; - } - if (val & 0x02) { - if (dev->fifo_enabled) - fifo_reset_evt(dev->rcvr_fifo); - else - fifo_reset(dev->rcvr_fifo); - } - if (val & 0x04) { - memset(dev->xmit_fifo, 0, 16); - dev->xmit_fifo_pos = 0; - } - switch ((val >> 6) & 0x03) { - case 0: - fifo_set_trigger_len(dev->rcvr_fifo, 1); - break; - case 1: - fifo_set_trigger_len(dev->rcvr_fifo, 4); - break; - case 2: - fifo_set_trigger_len(dev->rcvr_fifo, 8); - break; - case 3: - fifo_set_trigger_len(dev->rcvr_fifo, 14); - break; - } - dev->out_new = 0xffff; - serial_log("FIFO now %sabled, receive FIFO length = %i\n", dev->fifo_enabled ? "en" : "dis", dev->rcvr_fifo_len); - } - break; - case 3: - old = dev->lcr; - dev->lcr = val; - if ((old ^ val) & 0x3f) { - /* Data bits + start bit. */ - dev->bits = ((dev->lcr & 0x03) + 5) + 1; - /* Stop bits. */ - dev->bits++; /* First stop bit. */ - if (dev->lcr & 0x04) - dev->bits++; /* Second stop bit. */ - /* Parity bit. */ - if (dev->lcr & 0x08) - dev->bits++; - - serial_transmit_period(dev); - serial_update_speed(dev); - - if (dev->sd && dev->sd->lcr_callback) - dev->sd->lcr_callback(dev, dev->sd->priv, dev->lcr); - } - break; - case 4: - if ((val & 2) && !(dev->mctrl & 2)) { - if (dev->sd && dev->sd->rcr_callback) { - // pclog("RTS toggle callback\n"); - dev->sd->rcr_callback(dev, dev->sd->priv); - } - } - if (!(val & 8) && (dev->mctrl & 8)) - serial_do_irq(dev, 0); - if ((val ^ dev->mctrl) & 0x10) - serial_reset_fifo(dev); - dev->mctrl = val; - if (val & 0x10) { - new_msr = (val & 0x0c) << 4; - new_msr |= (val & 0x02) ? 0x10 : 0; - new_msr |= (val & 0x01) ? 0x20 : 0; - - if ((dev->msr ^ new_msr) & 0x10) - new_msr |= 0x01; - if ((dev->msr ^ new_msr) & 0x20) - new_msr |= 0x02; - if ((dev->msr ^ new_msr) & 0x80) - new_msr |= 0x08; - if ((dev->msr & 0x40) && !(new_msr & 0x40)) - new_msr |= 0x04; - - dev->msr = new_msr; - - dev->xmit_fifo_pos = 0; - /* TODO: Why reset the FIFO's here?! */ - fifo_reset(dev->rcvr_fifo); - } - break; - case 5: - dev->lsr = (dev->lsr & 0xe0) | (val & 0x1f); - if (dev->lsr & 0x01) - dev->int_status |= SERIAL_INT_RECEIVE; - if (dev->lsr & 0x1e) - dev->int_status |= SERIAL_INT_LSR; - if (dev->lsr & 0x20) - dev->int_status |= SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - break; - case 6: -#if 0 - dev->msr = (val & 0xf0) | (dev->msr & 0x0f); - dev->msr = val; -#endif - /* The actual condition bits of the MSR are read-only, but the delta bits are - undocumentedly writable, and the PCjr BIOS uses them to raise MSR interrupts. */ - dev->msr = (dev->msr & 0xf0) | (val & 0x0f); - if (dev->msr & 0x0f) - dev->int_status |= SERIAL_INT_MSR; - serial_update_ints(dev); - break; - case 7: - if (dev->type >= SERIAL_16450) - dev->scratch = val; - break; - default: - break; - } -} - -uint8_t -serial_read(uint16_t addr, void *p) -{ - serial_t *dev = (serial_t *) p; - uint8_t ret = 0; - - cycles -= ISA_CYCLES(8); - - switch (addr & 7) { - case 0: - if (dev->lcr & 0x80) { - ret = dev->dlab & 0xff; - break; - } - - if (dev->fifo_enabled) { - /* FIFO mode. */ - serial_clear_timeout(dev); - ret = fifo_read_evt(dev->rcvr_fifo); - - if (dev->lsr & 0x01) - timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); - } else { - /* Non-FIFO mode. */ - ret = dev->dat; - - // ret = (uint8_t) (dev->out_new & 0xffff); - dev->out_new = 0xffff; - - /* Always clear Data Ready interrupt. */ - dev->lsr &= 0xfe; - dev->int_status &= ~SERIAL_INT_RECEIVE; - serial_update_ints(dev); - } - - // pclog("Serial read : %02X\n", ret); - - // serial_log("Read data: %02X\n", ret); - break; - case 1: - if (dev->lcr & 0x80) - ret = (dev->dlab >> 8) & 0xff; - else - ret = dev->ier; - break; - case 2: - ret = dev->iir; - if ((ret & 0xe) == 2) { - dev->int_status &= ~SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - } - if (dev->fcr & 1) - ret |= 0xc0; - break; - case 3: - ret = dev->lcr; - break; - case 4: - ret = dev->mctrl; - break; - case 5: - ret = dev->lsr; - if (dev->lsr & 0x1f) - dev->lsr &= ~0x1e; - dev->int_status &= ~SERIAL_INT_LSR; - serial_update_ints(dev); - break; - case 6: - ret = dev->msr | dev->msr_set; - dev->msr &= ~0x0f; - dev->int_status &= ~SERIAL_INT_MSR; - serial_update_ints(dev); - break; - case 7: - ret = dev->scratch; - break; - default: - break; - } - - // serial_log("UART: Read %02X from port %02X\n", ret, addr); - serial_log("UART: [%04X:%08X] Read %02X from port %02X\n", CS, cpu_state.pc, ret, addr); - return ret; -} - -void -serial_remove(serial_t *dev) -{ - if (dev == NULL) - return; - - if (!com_ports[dev->inst].enabled) - return; - - if (!dev->base_address) - return; - - serial_log("Removing serial port %i at %04X...\n", dev->inst, dev->base_address); - - io_removehandler(dev->base_address, 0x0008, - serial_read, NULL, NULL, serial_write, NULL, NULL, dev); - dev->base_address = 0x0000; -} - -void -serial_setup(serial_t *dev, uint16_t addr, uint8_t irq) -{ - serial_log("Adding serial port %i at %04X...\n", dev->inst, addr); - - if (dev == NULL) - return; - - if (!com_ports[dev->inst].enabled) - return; - if (dev->base_address != 0x0000) - serial_remove(dev); - dev->base_address = addr; - if (addr != 0x0000) - io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, dev); - dev->irq = irq; -} - -static void -serial_rcvr_d_empty_evt(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - dev->lsr = (dev->lsr & 0xfe) | !fifo_get_empty(dev->rcvr_fifo); -} - -static void -serial_rcvr_d_overrun_evt(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - dev->lsr = (dev->lsr & 0xfd) | (fifo_get_overrun(dev->rcvr_fifo) << 1); -} - -static void -serial_rcvr_d_ready_evt(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | - (fifo_get_ready(dev->rcvr_fifo) ? SERIAL_INT_RECEIVE : 0); - serial_update_ints(dev); -} - -serial_t * -serial_attach_ex(int port, - void (*rcr_callback)(struct serial_s *serial, void *p), - void (*dev_write)(struct serial_s *serial, void *p, uint8_t data), - void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period), - void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits), - void *priv) -{ - serial_device_t *sd = &serial_devices[port]; - - sd->rcr_callback = rcr_callback; - sd->dev_write = dev_write; - sd->transmit_period_callback = transmit_period_callback; - sd->lcr_callback = lcr_callback; - sd->priv = priv; - - return sd->serial; -} - -static void -serial_speed_changed(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - serial_update_speed(dev); -} - -static void -serial_close(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - next_inst--; - - if (com_ports[dev->inst].enabled) - fifo_close(dev->rcvr_fifo); - - free(dev); -} - -static void -serial_reset(void *priv) -{ - serial_t *dev = (serial_t *) priv; - - if (com_ports[dev->inst].enabled) { - timer_disable(&dev->transmit_timer); - timer_disable(&dev->timeout_timer); - timer_disable(&dev->receive_timer); - - dev->lsr = dev->thr = dev->mctrl = dev->rcr = 0x00; - dev->iir = dev->ier = dev->lcr = dev->msr = 0x00; - dev->dat = dev->int_status = dev->scratch = dev->fcr = 0x00; - dev->fifo_enabled = dev->rcvr_fifo_len = dev->bits = dev->data_bits = 0x00; - dev->baud_cycles = dev->rcvr_fifo_full = dev->txsr = dev->out = 0x00; - - dev->dlab = dev->out_new = 0x0000; - - dev->xmit_fifo_pos = dev->xmit_fifo_end = 0x00; - - if (dev->rcvr_fifo != NULL) - fifo_reset(dev->rcvr_fifo); - - serial_reset_port(dev); - - dev->dlab = 96; - dev->fcr = 0x06; - - serial_transmit_period(dev); - serial_update_speed(dev); - } -} - -static void * -serial_init(const device_t *info) -{ - serial_t *dev = (serial_t *) malloc(sizeof(serial_t)); - memset(dev, 0, sizeof(serial_t)); - - dev->inst = next_inst; - - if (com_ports[next_inst].enabled) { - serial_log("Adding serial port %i...\n", next_inst); - dev->type = info->local; - memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t)); - dev->sd = &(serial_devices[next_inst]); - dev->sd->serial = dev; - serial_reset_port(dev); - if (next_inst == 3) - serial_setup(dev, COM4_ADDR, COM4_IRQ); - else if (next_inst == 2) - serial_setup(dev, COM3_ADDR, COM3_IRQ); - else if ((next_inst == 1) || (info->flags & DEVICE_PCJR)) - serial_setup(dev, COM2_ADDR, COM2_IRQ); - else if (next_inst == 0) - serial_setup(dev, COM1_ADDR, COM1_IRQ); - - /* Default to 1200,N,7. */ - dev->dlab = 96; - dev->fcr = 0x06; - if (info->local == SERIAL_8250_PCJR) - dev->clock_src = 1789500.0; - else - dev->clock_src = 1843200.0; - timer_add(&dev->transmit_timer, serial_transmit_timer, dev, 0); - timer_add(&dev->timeout_timer, serial_timeout_timer, dev, 0); - timer_add(&dev->receive_timer, serial_receive_timer, dev, 0); - serial_transmit_period(dev); - serial_update_speed(dev); - - dev->rcvr_fifo = fifo64_init(); - fifo_set_priv(dev->rcvr_fifo, dev); - fifo_set_d_empty_evt(dev->rcvr_fifo, serial_rcvr_d_empty_evt); - fifo_set_d_overrun_evt(dev->rcvr_fifo, serial_rcvr_d_overrun_evt); - fifo_set_d_ready_evt(dev->rcvr_fifo, serial_rcvr_d_ready_evt); - fifo_reset_evt(dev->rcvr_fifo); - fifo_set_len(dev->rcvr_fifo, 16); - } - - next_inst++; - - return dev; -} - -void -serial_set_next_inst(int ni) -{ - next_inst = ni; -} - -void -serial_standalone_init(void) -{ - while (next_inst < SERIAL_MAX) - device_add_inst(&ns8250_device, next_inst + 1); -}; - -const device_t ns8250_device = { - .name = "National Semiconductor 8250(-compatible) UART", - .internal_name = "ns8250", - .flags = 0, - .local = SERIAL_8250, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns8250_pcjr_device = { - .name = "National Semiconductor 8250(-compatible) UART for PCjr", - .internal_name = "ns8250_pcjr", - .flags = DEVICE_PCJR, - .local = SERIAL_8250_PCJR, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns16450_device = { - .name = "National Semiconductor NS16450(-compatible) UART", - .internal_name = "ns16450", - .flags = 0, - .local = SERIAL_16450, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns16550_device = { - .name = "National Semiconductor NS16550(-compatible) UART", - .internal_name = "ns16550", - .flags = 0, - .local = SERIAL_16550, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns16650_device = { - .name = "Startech Semiconductor 16650(-compatible) UART", - .internal_name = "ns16650", - .flags = 0, - .local = SERIAL_16650, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns16750_device = { - .name = "Texas Instruments 16750(-compatible) UART", - .internal_name = "ns16750", - .flags = 0, - .local = SERIAL_16750, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns16850_device = { - .name = "Exar Corporation NS16850(-compatible) UART", - .internal_name = "ns16850", - .flags = 0, - .local = SERIAL_16850, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; - -const device_t ns16950_device = { - .name = "Oxford Semiconductor NS16950(-compatible) UART", - .internal_name = "ns16950", - .flags = 0, - .local = SERIAL_16950, - .init = serial_init, - .close = serial_close, - .reset = serial_reset, - { .available = NULL }, - .speed_changed = serial_speed_changed, - .force_redraw = NULL, - .config = NULL -}; diff --git a/src/include/86box/serial - Cópia.h b/src/include/86box/serial - Cópia.h deleted file mode 100644 index dca8c4481..000000000 --- a/src/include/86box/serial - Cópia.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Definitions for the NS8250/16450/16550/16650/16750/16850/16950 - * UART emulation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - */ - -#ifndef EMU_SERIAL_H -#define EMU_SERIAL_H - -#define SERIAL_8250 0 -#define SERIAL_8250_PCJR 1 -#define SERIAL_16450 2 -#define SERIAL_16550 3 -#define SERIAL_16650 4 -#define SERIAL_16750 5 -#define SERIAL_16850 6 -#define SERIAL_16950 7 - -#define SERIAL_FIFO_SIZE 16 - -/* Default settings for the standard ports. */ -#define COM1_ADDR 0x03f8 -#define COM1_IRQ 4 -#define COM2_ADDR 0x02f8 -#define COM2_IRQ 3 -#define COM3_ADDR 0x03e8 -#define COM3_IRQ 4 -#define COM4_ADDR 0x02e8 -#define COM4_IRQ 3 - -struct serial_device_s; -struct serial_s; - -typedef struct serial_s { - uint8_t lsr; - uint8_t thr; - uint8_t mctrl; - uint8_t rcr; - uint8_t iir; - uint8_t ier; - uint8_t lcr; - uint8_t msr; - uint8_t dat; - uint8_t int_status; - uint8_t scratch; - uint8_t fcr; - uint8_t irq; - uint8_t type; - uint8_t inst; - uint8_t transmit_enabled; - uint8_t fifo_enabled; - uint8_t rcvr_fifo_len; - uint8_t bits; - uint8_t data_bits; - uint8_t baud_cycles; - uint8_t rcvr_fifo_full; - uint8_t txsr; - uint8_t out; - uint8_t msr_set; - uint8_t pad; - uint8_t irq_state; - uint8_t pad0; - - uint16_t dlab; - uint16_t base_address; - uint16_t out_new; - uint16_t pad1; - - uint8_t xmit_fifo_pos; - uint8_t xmit_fifo_end; - - uint8_t xmit_fifo[SERIAL_FIFO_SIZE]; - - void *rcvr_fifo; - - pc_timer_t transmit_timer; - pc_timer_t timeout_timer; - pc_timer_t receive_timer; - double clock_src; - double transmit_period; - - struct serial_device_s *sd; -} serial_t; - -typedef struct serial_device_s { - void (*rcr_callback)(struct serial_s *serial, void *p); - void (*dev_write)(struct serial_s *serial, void *p, uint8_t data); - void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t lcr); - void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period); - void *priv; - serial_t *serial; -} serial_device_t; - -typedef struct serial_port_s { - uint8_t enabled; -} serial_port_t; - -extern serial_port_t com_ports[SERIAL_MAX]; - -extern serial_t *serial_attach_ex(int port, - void (*rcr_callback)(struct serial_s *serial, void *p), - void (*dev_write)(struct serial_s *serial, void *p, uint8_t data), - void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period), - void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits), - void *priv); - -#define serial_attach(port, rcr_callback, dev_write, priv) \ - serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv); - -extern void serial_remove(serial_t *dev); -extern void serial_set_type(serial_t *dev, int type); -extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq); -extern void serial_clear_fifo(serial_t *dev); -extern void serial_write_fifo(serial_t *dev, uint8_t dat); -extern void serial_set_next_inst(int ni); -extern void serial_standalone_init(void); -extern void serial_set_clock_src(serial_t *dev, double clock_src); -extern void serial_reset_port(serial_t *dev); -extern void serial_device_timeout(void *priv); - -extern void serial_set_cts(serial_t *dev, uint8_t enabled); -extern void serial_set_dsr(serial_t *dev, uint8_t enabled); -extern void serial_set_dcd(serial_t *dev, uint8_t enabled); - -extern const device_t ns8250_device; -extern const device_t ns8250_pcjr_device; -extern const device_t ns16450_device; -extern const device_t ns16550_device; -extern const device_t ns16650_device; -extern const device_t ns16750_device; -extern const device_t ns16850_device; -extern const device_t ns16950_device; - -#endif /*EMU_SERIAL_H*/ diff --git a/src/include/86box/timer - Cópia.h b/src/include/86box/timer - Cópia.h deleted file mode 100644 index e33d6cbff..000000000 --- a/src/include/86box/timer - Cópia.h +++ /dev/null @@ -1,194 +0,0 @@ -#ifndef _TIMER_H_ -#define _TIMER_H_ - -#include "cpu.h" - -/* Maximum period, currently 1 second. */ -#define MAX_USEC64 1000000ULL -#define MAX_USEC 1000000.0 - -#define TIMER_PROCESS 4 -#define TIMER_SPLIT 2 -#define TIMER_ENABLED 1 - -#pragma pack(push, 1) -typedef struct ts_struct_t -{ - uint32_t frac; - uint32_t integer; -} ts_struct_t; -#pragma pack(pop) - -typedef union ts_t { - uint64_t ts64; - ts_struct_t ts32; -} ts_t; - -/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a - 32:32 fixed point format, with the integer part compared against the TSC. The - fractional part is used when advancing the timestamp to ensure a more accurate - period. - - As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits, - the timer period can only be at most 0x7fffffff CPU cycles. To allow room for - (optimistic) CPU frequency growth, timer period must be at most 1 second. - - When a timer callback is called, the timer has been disabled. If the timer is - to repeat, the callback must call timer_advance_u64(). This is a change from - the old timer API.*/ -typedef struct pc_timer_t { -#ifdef USE_PCEM_TIMER - uint32_t ts_integer; - uint32_t ts_frac; -#else - ts_t ts; -#endif - int flags; /* The flags are defined above. */ - int pad; - double period; /* This is used for large period timers to count - the microseconds and split the period. */ - - void (*callback)(void *priv); - void *priv; - - struct pc_timer_t *prev; - struct pc_timer_t *next; -} pc_timer_t; - -#ifdef __cplusplus -extern "C" { -#endif - -/*Timestamp of nearest enabled timer. CPU emulation must call timer_process() - when TSC matches or exceeds this.*/ -extern uint32_t timer_target; - -/*Enable timer, without updating timestamp*/ -extern void timer_enable(pc_timer_t *timer); -/*Disable timer*/ -extern void timer_disable(pc_timer_t *timer); - -/*Process any pending timers*/ -extern void timer_process(void); - -/*Reset timer system*/ -extern void timer_close(void); -extern void timer_init(void); - -/*Add new timer. If start_timer is set, timer will be enabled with a zero - timestamp - this is useful for permanently enabled timers*/ -extern void timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start_timer); - -/*1us in 32:32 format*/ -extern uint64_t TIMER_USEC; - -/*True if timer a expires before timer b*/ -#define TIMER_LESS_THAN(a, b) ((int64_t) ((a)->ts.ts64 - (b)->ts.ts64) <= 0) -/*True if timer a expires before 32 bit integer timestamp b*/ -#define TIMER_LESS_THAN_VAL(a, b) ((int32_t) ((a)->ts.ts32.integer - (b)) <= 0) -/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/ -#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t) ((a) - (b)) <= 0) - -/*Advance timer by delay, specified in 32:32 format. This should be used to - resume a recurring timer in a callback routine*/ -static __inline void -timer_advance_u64(pc_timer_t *timer, uint64_t delay) -{ - timer->ts.ts64 += delay; - - timer_enable(timer); -} - -/*Set a timer to the given delay, specified in 32:32 format. This should be used - when starting a timer*/ -static __inline void -timer_set_delay_u64(pc_timer_t *timer, uint64_t delay) -{ - timer->ts.ts64 = 0ULL; - timer->ts.ts32.integer = tsc; - timer->ts.ts64 += delay; - - timer_enable(timer); -} - -/*True if timer currently enabled*/ -static __inline int -timer_is_enabled(pc_timer_t *timer) -{ - return !!(timer->flags & TIMER_ENABLED); -} - -/*True if timer currently on*/ -static __inline int -timer_is_on(pc_timer_t *timer) -{ - // return ((timer->flags & TIMER_SPLIT) || (timer->flags & TIMER_ENABLED)); - return !!(timer->flags & TIMER_ENABLED); -} - -/*Return integer timestamp of timer*/ -static __inline uint32_t -timer_get_ts_int(pc_timer_t *timer) -{ - return timer->ts.ts32.integer; -} - -/*Return remaining time before timer expires, in us. If the timer has already - expired then return 0*/ -static __inline uint32_t -timer_get_remaining_us(pc_timer_t *timer) -{ - int64_t remaining; - - if (timer->flags & TIMER_ENABLED) { - remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32)); - - if (remaining < 0) - return 0; - return remaining / TIMER_USEC; - } - - return 0; -} - -/*Return remaining time before timer expires, in 32:32 timestamp format. If the - timer has already expired then return 0*/ -static __inline uint64_t -timer_get_remaining_u64(pc_timer_t *timer) -{ - int64_t remaining; - - if (timer->flags & TIMER_ENABLED) { - remaining = (int64_t) (timer->ts.ts64 - (uint64_t) (tsc << 32)); - - if (remaining < 0) - return 0; - return remaining; - } - - return 0; -} - -/*Set timer callback function*/ -static __inline void -timer_set_callback(pc_timer_t *timer, void (*callback)(void *priv)) -{ - timer->callback = callback; -} - -/*Set timer private data*/ -static __inline void -timer_set_p(pc_timer_t *timer, void *priv) -{ - timer->priv = priv; -} - -/* The API for big timer periods starts here. */ -extern void timer_stop(pc_timer_t *timer); -extern void timer_on_auto(pc_timer_t *timer, double period); - -#ifdef __cplusplus -} -#endif - -#endif /*_TIMER_H_*/ diff --git a/src/include/86box/vid_mda - Cópia.h b/src/include/86box/vid_mda - Cópia.h deleted file mode 100644 index 5a381b3f0..000000000 --- a/src/include/86box/vid_mda - Cópia.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ - -#ifndef VIDEO_MDA_H -#define VIDEO_MDA_H - -typedef struct mda_t { - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; - - uint8_t ctrl; - uint8_t stat; - - uint64_t dispontime; - uint64_t dispofftime; - pc_timer_t timer; - pc_timer_t dot_timer; - - int firstline; - int lastline; - - int linepos; - int displine; - int vc; - int sc; - uint16_t ma; - uint16_t maback; - int con; - int coff; - int cursoron; - int dispon; - int blink; - int vsynctime; - int vadj; - int monitor_index; - int prev_monitor_index; - - uint8_t *vram; -} mda_t; - -#define VIDEO_MONITOR_PROLOGUE() \ - { \ - mda->prev_monitor_index = monitor_index_global; \ - monitor_index_global = mda->monitor_index; \ - } -#define VIDEO_MONITOR_EPILOGUE() \ - { \ - monitor_index_global = mda->prev_monitor_index; \ - } - -void mda_init(mda_t *mda); -void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink); -void mda_out(uint16_t addr, uint8_t val, void *priv); -uint8_t mda_in(uint16_t addr, void *priv); -void mda_write(uint32_t addr, uint8_t val, void *priv); -uint8_t mda_read(uint32_t addr, void *priv); -void mda_recalctimings(mda_t *mda); -void mda_poll(void *priv); - -#ifdef EMU_DEVICE_H -extern const device_t mda_device; -#endif - -#endif /*VIDEO_MDA_H*/ diff --git a/src/timer - Cópia.c b/src/timer - Cópia.c deleted file mode 100644 index 61dbbaa5e..000000000 --- a/src/timer - Cópia.c +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/timer.h> - -uint64_t TIMER_USEC; -uint32_t timer_target; - -/*Enabled timers are stored in a linked list, with the first timer to expire at - the head.*/ -pc_timer_t *timer_head = NULL; - -/* Are we initialized? */ -int timer_inited = 0; - -static void timer_advance_ex(pc_timer_t *timer, int start); - -void -timer_enable(pc_timer_t *timer) -{ - pc_timer_t *timer_node = timer_head; - - if (!timer_inited || (timer == NULL)) - return; - - if (timer->flags & TIMER_ENABLED) - timer_disable(timer); - - if (timer->next || timer->prev) - fatal("timer_enable - timer->next\n"); - - timer->flags |= TIMER_ENABLED; - - /*List currently empty - add to head*/ - if (!timer_head) { - timer_head = timer; - timer->next = timer->prev = NULL; - timer_target = timer_head->ts.ts32.integer; - return; - } - - if (TIMER_LESS_THAN(timer, timer_head)) { - timer->next = timer_head; - timer->prev = NULL; - timer_head->prev = timer; - timer_head = timer; - timer_target = timer_head->ts.ts32.integer; - return; - } - - if (!timer_head->next) { - timer_head->next = timer; - timer->prev = timer_head; - return; - } - - pc_timer_t *prev = timer_head; - timer_node = timer_head->next; - - while (1) { - /*Timer expires before timer_node. Add to list in front of timer_node*/ - if (TIMER_LESS_THAN(timer, timer_node)) { - timer->next = timer_node; - timer->prev = prev; - timer_node->prev = timer; - prev->next = timer; - return; - } - - /*timer_node is last in the list. Add timer to end of list*/ - if (!timer_node->next) { - timer_node->next = timer; - timer->prev = timer_node; - return; - } - - prev = timer_node; - timer_node = timer_node->next; - } -} - -void -timer_disable(pc_timer_t *timer) -{ - if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED)) - return; - - if (!timer->next && !timer->prev && timer != timer_head) - fatal("timer_disable - !timer->next\n"); - - timer->flags &= ~TIMER_ENABLED; - - if (timer->prev) - timer->prev->next = timer->next; - else - timer_head = timer->next; - if (timer->next) - timer->next->prev = timer->prev; - timer->prev = timer->next = NULL; -} - -void -timer_process(void) -{ - pc_timer_t *timer; - - if (!timer_head) - return; - - while (1) { - timer = timer_head; - - if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc)) - break; - - timer_head = timer->next; - if (timer_head) - timer_head->prev = NULL; - - timer->next = timer->prev = NULL; - timer->flags &= ~TIMER_ENABLED; - - if (timer->flags & TIMER_SPLIT) - timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */ - else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */ - timer->callback(timer->priv); - } - - timer_target = timer_head->ts.ts32.integer; -} - -void -timer_close(void) -{ - pc_timer_t *t = timer_head; - pc_timer_t *r; - - /* Set all timers' prev and next to NULL so it is assured that - timers that are not in malloc'd structs don't keep pointing - to timers that may be in malloc'd structs. */ - while (t != NULL) { - r = t; - r->prev = r->next = NULL; - t = r->next; - } - - timer_head = NULL; - - timer_inited = 0; -} - -void -timer_init(void) -{ - timer_target = 0ULL; - tsc = 0; - - timer_inited = 1; -} - -void -timer_add(pc_timer_t *timer, void (*callback)(void *priv), void *priv, int start_timer) -{ - memset(timer, 0, sizeof(pc_timer_t)); - - timer->callback = callback; - timer->priv = priv; - timer->flags = 0; - timer->prev = timer->next = NULL; - if (start_timer) - timer_set_delay_u64(timer, 0); -} - -/* The API for big timer periods starts here. */ -void -timer_stop(pc_timer_t *timer) -{ - if (!timer_inited || (timer == NULL)) - return; - - timer->period = 0.0; - timer_disable(timer); - timer->flags &= ~TIMER_SPLIT; -} - -static void -timer_do_period(pc_timer_t *timer, uint64_t period, int start) -{ - if (!timer_inited || (timer == NULL)) - return; - - if (start) - timer_set_delay_u64(timer, period); - else - timer_advance_u64(timer, period); -} - -void -timer_advance_ex(pc_timer_t *timer, int start) -{ - if (!timer_inited || (timer == NULL)) - return; - - if (timer->period > MAX_USEC) { - timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start); - timer->period -= MAX_USEC; - timer->flags |= TIMER_SPLIT; - } else { - if (timer->period > 0.0) - timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start); - else - timer_disable(timer); - timer->period = 0.0; - timer->flags &= ~TIMER_SPLIT; - } -} - -static void -timer_on(pc_timer_t *timer, double period, int start) -{ - if (!timer_inited || (timer == NULL)) - return; - - timer->period = period; - timer_advance_ex(timer, start); -} - -void -timer_on_auto(pc_timer_t *timer, double period) -{ - if (!timer_inited || (timer == NULL)) - return; - - if (period > 0.0) { - // timer_on(timer, period, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0)); - timer->period = period; - timer_advance_ex(timer, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0)); - } else - timer_stop(timer); -} diff --git a/src/video/vid_cga - Cópia.c b/src/video/vid_cga - Cópia.c deleted file mode 100644 index e6559722f..000000000 --- a/src/video/vid_cga - Cópia.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Emulation of the old and new IBM CGA graphics cards. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/pit.h> -#include <86box/mem.h> -#include <86box/rom.h> -#include <86box/device.h> -#include <86box/video.h> -#include <86box/vid_cga.h> -#include <86box/vid_cga_comp.h> - -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 - -#define COMPOSITE_OLD 0 -#define COMPOSITE_NEW 1 - -static uint8_t crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - -void cga_recalctimings(cga_t *cga); - -void -cga_out(uint16_t addr, uint8_t val, void *p) -{ - cga_t *cga = (cga_t *) p; - uint8_t old; - - if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; - - switch (addr) { - case 0x3D4: - cga->crtcreg = val & 31; - return; - case 0x3D5: - old = cga->crtc[cga->crtcreg]; - cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; - if (old != val) { - if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) { - cga->fullchange = changeframecount; - cga_recalctimings(cga); - } - } - return; - case 0x3D8: - old = cga->cgamode; - cga->cgamode = val; - - if (old ^ val) { - if ((old ^ val) & 0x07) - update_cga16_color(val); - - cga_recalctimings(cga); - } - return; - case 0x3D9: - old = cga->cgacol; - cga->cgacol = val; - if (old ^ val) - cga_recalctimings(cga); - return; - } -} - -uint8_t -cga_in(uint16_t addr, void *p) -{ - cga_t *cga = (cga_t *) p; - - uint8_t ret = 0xff; - - if ((addr >= 0x3d0) && (addr <= 0x3d7)) - addr = (addr & 0xff9) | 0x004; - - switch (addr) { - case 0x3D4: - ret = cga->crtcreg; - break; - case 0x3D5: - ret = cga->crtc[cga->crtcreg]; - break; - case 0x3DA: - ret = cga->cgastat; - break; - } - - return ret; -} - -void -cga_pravetz_out(uint16_t addr, uint8_t val, void *p) -{ - cga_t *cga = (cga_t *) p; - - cga->fontbase = (((unsigned int) val) << 8); -} - -uint8_t -cga_pravetz_in(uint16_t addr, void *p) -{ - cga_t *cga = (cga_t *) p; - - return (cga->fontbase >> 8); -} - -void -cga_waitstates(void *p) -{ - cga_t *cga = (cga_t *) p; - int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 }; - int ws; - int q_array[16] = { 5, 5, 4, 4, 4, 3, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5 }; - int q; - - if (is286) { - ws = ws_array[cycles & 0xf]; - cycles -= ws; - } else { - q = 15 - (((int) (timer_get_remaining_u64(&cga->q_timer) >> 32ULL)) & 0x0f); - cycles -= q_array[q]; - // pclog("Subtracting %i cycles at index %i\n", q_array[q], q); - } -} - -void -cga_write(uint32_t addr, uint8_t val, void *p) -{ - cga_t *cga = (cga_t *) p; - - cga->vram[addr & 0x3fff] = val; - if (cga->snow_enabled) { - int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; - cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; - cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; - } - cga_waitstates(cga); -} - -uint8_t -cga_read(uint32_t addr, void *p) -{ - cga_t *cga = (cga_t *) p; - - cga_waitstates(cga); - if (cga->snow_enabled) { - int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc; - cga->charbuffer[offset] = cga->vram[addr & 0x3fff]; - cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff]; - } - return cga->vram[addr & 0x3fff]; -} - -void -cga_recalctimings(cga_t *cga) -{ - double disptime; - double _dispontime; - double _dispofftime; - - if (cga->cgamode & 1) { - disptime = (double) (cga->crtc[0] + 1); - _dispontime = (double) cga->crtc[1]; - } else { - disptime = (double) ((cga->crtc[0] + 1) << 1); - _dispontime = (double) (cga->crtc[1] << 1); - } - _dispofftime = disptime - _dispontime; - _dispontime = _dispontime * CGACONST; - _dispofftime = _dispofftime * CGACONST; - cga->dispontime = (uint64_t) (_dispontime); - cga->dispofftime = (uint64_t) (_dispofftime); -} - -void -cga_q_tick(void *p) -{ - cga_t *cga = (cga_t *) p; - - timer_advance_u64(&cga->q_timer, CGACONST << 1); -} - -void -cga_poll(void *p) -{ - cga_t *cga = (cga_t *) p; - uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x; - int c; - int xs_temp; - int ys_temp; - int oldvc; - uint8_t chr; - uint8_t attr; - uint8_t border; - uint16_t dat; - int cols[4]; - int col; - int oldsc; - - if (!cga->linepos) { - timer_advance_u64(&cga->timer, cga->dispofftime); - cga->cgastat |= 1; - cga->linepos = 1; - oldsc = cga->sc; - if ((cga->crtc[8] & 3) == 3) - cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; - if (cga->cgadispon) { - if (cga->displine < cga->firstline) { - cga->firstline = cga->displine; - video_wait_for_buffer(); - } - cga->lastline = cga->displine; - for (c = 0; c < 8; c++) { - if ((cga->cgamode & 0x12) == 0x12) { - buffer32->line[cga->displine << 1][c] = buffer32->line[(cga->displine << 1) + 1][c] = 0; - if (cga->cgamode & 1) { - buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 3) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = 0; - } else { - buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 4) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = 0; - } - } else { - buffer32->line[cga->displine << 1][c] = buffer32->line[(cga->displine << 1) + 1][c] = (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) { - buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 3) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; - } else { - buffer32->line[cga->displine << 1][c + (cga->crtc[1] << 4) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16; - } - } - } - if (cga->cgamode & 1) { - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) { - chr = cga->charbuffer[x << 1]; - attr = cga->charbuffer[(x << 1) + 1]; - } else - chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - cols[1] = (attr & 15) + 16; - if (cga->cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor) - cols[1] = cols[0]; - } else - cols[0] = (attr >> 4) + 16; - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[cga->displine << 1][(x << 3) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[cga->displine << 1][(x << 3) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - cga->ma++; - } - } else if (!(cga->cgamode & 2)) { - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) { - chr = cga->vram[(cga->ma << 1) & 0x3fff]; - attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff]; - } else - chr = attr = 0; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - cols[1] = (attr & 15) + 16; - if (cga->cgamode & 0x20) { - cols[0] = ((attr >> 4) & 7) + 16; - if ((cga->cgablink & 8) && (attr & 0x80)) - cols[1] = cols[0]; - } else - cols[0] = (attr >> 4) + 16; - cga->ma++; - if (drawcursor) { - for (c = 0; c < 8; c++) { - buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - } else { - for (c = 0; c < 8; c++) { - buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } else if (!(cga->cgamode & 16)) { - cols[0] = (cga->cgacol & 15) | 16; - col = (cga->cgacol & 16) ? 24 : 16; - if (cga->cgamode & 4) { - cols[1] = col | 3; /* Cyan */ - cols[2] = col | 4; /* Red */ - cols[3] = col | 7; /* White */ - } else if (cga->cgacol & 32) { - cols[1] = col | 3; /* Cyan */ - cols[2] = col | 5; /* Magenta */ - cols[3] = col | 7; /* White */ - } else { - cols[1] = col | 2; /* Green */ - cols[2] = col | 4; /* Red */ - cols[3] = col | 6; /* Yellow */ - } - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - else - dat = 0; - cga->ma++; - for (c = 0; c < 8; c++) { - buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[cga->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - cols[0] = 0; - cols[1] = (cga->cgacol & 15) + 16; - for (x = 0; x < cga->crtc[1]; x++) { - if (cga->cgamode & 8) - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - else - dat = 0; - cga->ma++; - for (c = 0; c < 16; c++) { - buffer32->line[cga->displine << 1][(x << 4) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; - dat <<= 1; - } - } - } - } else { - cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) { - hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 3) + 16) << 2, cols[0]); - hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 3) + 16) << 2, cols[0]); - } else { - hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 4) + 16) << 2, cols[0]); - hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 4) + 16) << 2, cols[0]); - } - } - - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; - else - x = (cga->crtc[1] << 4) + 16; - - if (cga->composite) { - border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15); - - Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[cga->displine << 1]); - Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1) + 1]); - } else { - video_process_8(x, cga->displine << 1); - video_process_8(x, (cga->displine << 1) + 1); - } - - cga->sc = oldsc; - if (cga->vc == cga->crtc[7] && !cga->sc) - cga->cgastat |= 8; - cga->displine++; - if (cga->displine >= 360) - cga->displine = 0; - } else { - timer_advance_u64(&cga->timer, cga->dispontime); - cga->linepos = 0; - if (cga->vsynctime) { - cga->vsynctime--; - if (!cga->vsynctime) - cga->cgastat &= ~8; - } - if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) { - cga->con = 0; - cga->coff = 1; - } - if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) - cga->maback = cga->ma; - if (cga->vadj) { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - cga->vadj--; - if (!cga->vadj) { - cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - cga->sc = 0; - } - } else if (cga->sc == cga->crtc[9]) { - cga->maback = cga->ma; - cga->sc = 0; - oldvc = cga->vc; - cga->vc++; - cga->vc &= 127; - - if (cga->vc == cga->crtc[6]) - cga->cgadispon = 0; - - if (oldvc == cga->crtc[4]) { - cga->vc = 0; - cga->vadj = cga->crtc[5]; - if (!cga->vadj) { - cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - } - switch (cga->crtc[10] & 0x60) { - case 0x20: - cga->cursoron = 0; - break; - case 0x60: - cga->cursoron = cga->cgablink & 0x10; - break; - default: - cga->cursoron = cga->cgablink & 0x08; - break; - } - } - - if (cga->vc == cga->crtc[7]) { - cga->cgadispon = 0; - cga->displine = 0; - cga->vsynctime = 16; - if (cga->crtc[7]) { - if (cga->cgamode & 1) - x = (cga->crtc[1] << 3) + 16; - else - x = (cga->crtc[1] << 4) + 16; - cga->lastline++; - - xs_temp = x; - ys_temp = (cga->lastline - cga->firstline) << 1; - - if ((xs_temp > 0) && (ys_temp > 0)) { - if (xs_temp < 64) - xs_temp = 656; - if (ys_temp < 32) - ys_temp = 400; - if (!enable_overscan) - xs_temp -= 16; - - if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) { - xsize = xs_temp; - ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (enable_overscan) { - video_blit_memtoscreen(0, (cga->firstline - 4) << 1, - xsize, ((cga->lastline - cga->firstline) + 8) << 1); - } else { - video_blit_memtoscreen(8, cga->firstline << 1, - xsize, (cga->lastline - cga->firstline) << 1); - } - } - - frames++; - - video_res_x = xsize; - video_res_y = ysize; - if (cga->cgamode & 1) { - video_res_x /= 8; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } else if (!(cga->cgamode & 2)) { - video_res_x /= 16; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } else if (!(cga->cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else - video_bpp = 1; - } - cga->firstline = 1000; - cga->lastline = 0; - cga->cgablink++; - cga->oddeven ^= 1; - } - } else { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - } - if (cga->cgadispon) - cga->cgastat &= ~1; - if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))) - cga->con = 1; - if (cga->cgadispon && (cga->cgamode & 1)) { - for (x = 0; x < (cga->crtc[1] << 1); x++) - cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff]; - } - } -} - -void -cga_init(cga_t *cga) -{ - timer_add(&cga->timer, cga_poll, cga, 1); - cga->composite = 0; -} - -void * -cga_standalone_init(const device_t *info) -{ - int display_type; - cga_t *cga = malloc(sizeof(cga_t)); - - memset(cga, 0, sizeof(cga_t)); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_cga); - - display_type = device_get_config_int("display_type"); - cga->composite = (display_type != CGA_RGB); - cga->revision = device_get_config_int("composite_type"); - cga->snow_enabled = device_get_config_int("snow_enabled"); - - cga->vram = malloc(0x4000); - - cga_comp_init(cga->revision); - timer_add(&cga->timer, cga_poll, cga, 1); - if (!is286) - timer_add(&cga->q_timer, cga_q_tick, cga, 1); - mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL /*cga->vram*/, MEM_MAPPING_EXTERNAL, cga); - io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); - - overscan_x = overscan_y = 16; - - cga->rgb_type = device_get_config_int("rgb_type"); - cga_palette = (cga->rgb_type << 1); - cgapal_rebuild(); - update_cga16_color(cga->cgamode); - - return cga; -} - -void * -cga_pravetz_init(const device_t *info) -{ - cga_t *cga = cga_standalone_init(info); - - loadfont("roms/video/cga/PRAVETZ-VDC2.BIN", 10); - - io_removehandler(0x03dd, 0x0001, cga_in, NULL, NULL, cga_out, NULL, NULL, cga); - io_sethandler(0x03dd, 0x0001, cga_pravetz_in, NULL, NULL, cga_pravetz_out, NULL, NULL, cga); - - cga->fontbase = 0x0300; - - return cga; -} - -void -cga_close(void *p) -{ - cga_t *cga = (cga_t *) p; - - free(cga->vram); - free(cga); -} - -void -cga_speed_changed(void *p) -{ - cga_t *cga = (cga_t *) p; - - cga_recalctimings(cga); -} - -// clang-format off -const device_config_t cga_config[] = { - { - .name = "display_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = CGA_RGB, - .selection = { - { - .description = "RGB", - .value = CGA_RGB - }, - { - .description = "Composite", - .value = CGA_COMPOSITE - }, - { - .description = "" - } - } - }, - { - .name = "composite_type", - .description = "Composite type", - .type = CONFIG_SELECTION, - .default_int = COMPOSITE_OLD, - .selection = { - { - .description = "Old", - .value = COMPOSITE_OLD - }, - { - .description = "New", - .value = COMPOSITE_NEW - }, - { - .description = "" - } - } - }, - { - .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Color", - .value = 0 - }, - { - .description = "Green Monochrome", - .value = 1 - }, - { - .description = "Amber Monochrome", - .value = 2 - }, - { - .description = "Gray Monochrome", - .value = 3 - }, - { - .description = "Color (no brown)", - .value = 4 - }, - { - .description = "" - } - } - }, - { - .name = "snow_enabled", - .description = "Snow emulation", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .type = CONFIG_END - } -}; -// clang-format on - -const device_t cga_device = { - .name = "CGA", - .internal_name = "cga", - .flags = DEVICE_ISA, - .local = 0, - .init = cga_standalone_init, - .close = cga_close, - .reset = NULL, - { .available = NULL }, - .speed_changed = cga_speed_changed, - .force_redraw = NULL, - .config = cga_config -}; - -const device_t cga_pravetz_device = { - .name = "Pravetz VDC-2", - .internal_name = "cga_pravetz", - .flags = DEVICE_ISA, - .local = 0, - .init = cga_pravetz_init, - .close = cga_close, - .reset = NULL, - { .available = NULL }, - .speed_changed = cga_speed_changed, - .force_redraw = NULL, - .config = cga_config -}; diff --git a/src/video/vid_mda - Cópia.c b/src/video/vid_mda - Cópia.c deleted file mode 100644 index bee5907c9..000000000 --- a/src/video/vid_mda - Cópia.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * MDA emulation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/lpt.h> -#include <86box/pit.h> -#include <86box/mem.h> -#include <86box/rom.h> -#include <86box/device.h> -#include <86box/video.h> -#include <86box/vid_mda.h> -#include <86box/plat_unused.h> - -static int mdacols[256][2][2]; - -static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; - -static double dot_clock = 0.0; - -void mda_recalctimings(mda_t *mda); - -void -mda_out(uint16_t addr, uint8_t val, void *priv) -{ - mda_t *mda = (mda_t *) priv; - - // pclog("[W] %04X = %02X\n", addr, val); - - switch (addr) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - mda->crtcreg = val & 31; - return; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - mda->crtc[mda->crtcreg] = val; -#if 0 - if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - mda->crtc[10] = 0xb; - mda->crtc[11] = 0xc; - } -#endif - mda_recalctimings(mda); - return; - case 0x3b8: - mda->ctrl = val; - return; - - default: - break; - } -} - -uint8_t -mda_in(uint16_t addr, void *priv) -{ - const mda_t *mda = (mda_t *) priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x3b0: - case 0x3b2: - case 0x3b4: - case 0x3b6: - ret = mda->crtcreg; - break; - case 0x3b1: - case 0x3b3: - case 0x3b5: - case 0x3b7: - ret = mda->crtc[mda->crtcreg]; - break; - case 0x3ba: - ret = mda->stat; - // if (mda->ctrl & 0x08) - // ret |= (mda->stat & 0x80) ? 0x08 : 0x00; - // return mda->stat | 0xF0; - break; - - default: - break; - } - - // pclog("[R] %04X = %02X\n", addr, ret); - - return ret; -} - -void -mda_write(uint32_t addr, uint8_t val, void *priv) -{ - mda_t *mda = (mda_t *) priv; - mda->vram[addr & 0xfff] = val; -} - -uint8_t -mda_read(uint32_t addr, void *priv) -{ - const mda_t *mda = (mda_t *) priv; - - return mda->vram[addr & 0xfff]; -} - -void -mda_recalctimings(mda_t *mda) -{ - double _dispontime; - double _dispofftime; - double disptime; - disptime = mda->crtc[0] + 1; - _dispontime = mda->crtc[1] + 1; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - mda->dispontime = (uint64_t) (_dispontime); - mda->dispofftime = (uint64_t) (_dispofftime); - dot_clock = ((double) MDACONST) / 9.0; -} - -void -mda_dot_poll(void *priv) -{ - mda_t *mda = (mda_t *) priv; - - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int blink; - - timer_advance_u64(&mda->dot_timer, (uint64_t) dot_clock); - - static uint8_t chr; - static uint8_t attr; - static uint8_t color; - static uint16_t dot = 0x0008; - static uint16_t ch = 0x0000; - static uint16_t line = 0x0000; - static uint16_t sc = 0x0000; - static int sctotal; - static int vtotal; - static int hslast; - static int vslast; - static int ma = 0x000; - - sctotal = ((int) mda->crtc[0x09]) + 1; - vtotal = (((int) mda->crtc[0x04]) + ((int) mda->crtc[0x05])) * sctotal; - hslast = ((int) mda->crtc[0x02]) + ((int) mda->crtc[0x03]) - 1; - vslast = ((int) mda->crtc[0x07]) + 16 - 1; - - chr = mda->vram[ma & 0xfff]; - attr = mda->vram[(ma + 1) & 0xfff]; - drawcursor = (mda->ctrl & 0x08) ? ((ma == ca) && mda->con && mda->cursoron) : 0x00; - blink = (mda->ctrl & 0x08) ? ((mda->blink & 16) && (mda->ctrl & 0x20) && - (attr & 0x80) && !drawcursor) : 0x00; - - if ((mda->sc == 12) && ((attr & 7) == 1)) - color = mdacols[attr][blink][1]; - else { - if (dot == 0) { - if ((chr & ~0x1f) == 0xc0) - color = mdacols[attr][blink][fontdatm[chr][sc] & 1]; - else - color = mdacols[attr][blink][0]; - } else - color = mdacols[attr][blink][(fontdatm[chr][sc] & (1 << (dot - 1))) ? 1 : 0]; - } - - if (drawcursor) - color ^= mdacols[attr][0][1]; - - if (!(mda->ctrl & 0x08) || !(mda->stat & 0x81) || (ch > mda->crtc[1]) || (line > mda->crtc[6])) - mda->stat &= 0xe7; - else - mda->stat = (mda->stat & 0xe7) | ((color & 0x01) << 3) | ((color & 0x08) << 1); - - dot--; - if (dot == 0xffff) { - dot = 8; - - if (ch == mda->crtc[0x00]) { - ch = 0; - line++; - - if (line == vtotal) - line = 0; - - sc++; - - if (sc == sctotal) - sc = 0; - } else - ch++; - } - - if (ch >= mda->crtc[0x02]) - mda->stat &= 0xfe; - else if ((hslast >= mda->crtc[0x02]) && (ch >= mda->crtc[0x02]) && (ch <= hslast)) - mda->stat &= 0xfe; - else if ((hslast < mda->crtc[0x02]) && (ch <= hslast)) - mda->stat &= 0xfe; - else - mda->stat |= 0x01; - - if (line >= mda->crtc[0x07]) - mda->stat &= 0x7f; - else if ((vslast >= mda->crtc[0x07]) && (line >= mda->crtc[0x07]) && (line <= vslast)) - mda->stat &= 0x7f; - else if ((vslast < mda->crtc[0x07]) && (line <= vslast)) - mda->stat &= 0x7f; - else - mda->stat |= 0x80; - - ma += 2; - if (ma > 0xfff) - ma = 0; - - if (!(mda->stat & 0x81)) - ma = 0; -} - -void -mda_poll(void *priv) -{ - mda_t *mda = (mda_t *) priv; - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x; - int c; - int oldvc; - uint8_t chr; - uint8_t attr; - int oldsc; - int blink; - - VIDEO_MONITOR_PROLOGUE() - if (!mda->linepos) { - timer_advance_u64(&mda->timer, mda->dispofftime); - // mda->stat |= 1; - mda->linepos = 1; - oldsc = mda->sc; - if ((mda->crtc[8] & 3) == 3) - mda->sc = (mda->sc << 1) & 7; - if (mda->dispon) { - if (mda->displine < mda->firstline) { - mda->firstline = mda->displine; - video_wait_for_buffer(); - } - mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[1]; x++) { - chr = (mda->ctrl & 0x08) ? mda->vram[(mda->ma << 1) & 0xfff] : 0x00; - attr = (mda->ctrl & 0x08) ? mda->vram[((mda->ma << 1) + 1) & 0xfff] : 0x00; - drawcursor = (mda->ctrl & 0x08) ? ((mda->ma == ca) && mda->con && mda->cursoron) : 0x00; - blink = (mda->ctrl & 0x08) ? ((mda->blink & 16) && (mda->ctrl & 0x20) && - (attr & 0x80) && !drawcursor) : 0x00; - if (mda->sc == 12 && ((attr & 7) == 1)) { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; - } else { - for (c = 0; c < 8; c++) - buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0]; - if ((chr & ~0x1f) == 0xc0) - buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1]; - else - buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0]; - } - mda->ma++; - if (drawcursor) { - for (c = 0; c < 9; c++) - buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1]; - } - } - - video_process_8(mda->crtc[1] * 9, mda->displine); - } - mda->sc = oldsc; - // if (mda->vc == mda->crtc[7] && !mda->sc) { - // mda->stat |= 0x80; - // } - mda->displine++; - if (mda->displine >= 500) - mda->displine = 0; - } else { - timer_advance_u64(&mda->timer, mda->dispontime); - // if (mda->dispon) - // mda->stat &= ~1; - mda->linepos = 0; - if (mda->vsynctime) { - mda->vsynctime--; - // if (!mda->vsynctime) { - // mda->stat &= ~0x80; - // } - } - if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) { - mda->con = 0; - mda->coff = 1; - } - if (mda->vadj) { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - mda->vadj--; - if (!mda->vadj) { - mda->dispon = 1; - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - mda->sc = 0; - } - } else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) { - mda->maback = mda->ma; - mda->sc = 0; - oldvc = mda->vc; - mda->vc++; - mda->vc &= 127; - if (mda->vc == mda->crtc[6]) - mda->dispon = 0; - if (oldvc == mda->crtc[4]) { - mda->vc = 0; - mda->vadj = mda->crtc[5]; - if (!mda->vadj) - mda->dispon = 1; - if (!mda->vadj) - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - if ((mda->crtc[10] & 0x60) == 0x20) - mda->cursoron = 0; - else - mda->cursoron = mda->blink & 16; - } - if (mda->vc == mda->crtc[7]) { - mda->dispon = 0; - mda->displine = 0; - mda->vsynctime = 16; - if (mda->crtc[7]) { - x = mda->crtc[1] * 9; - mda->lastline++; - if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) { - xsize = x; - ysize = mda->lastline - mda->firstline; - if (xsize < 64) - xsize = 656; - if (ysize < 32) - ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, mda->firstline, xsize, ysize); - frames++; - video_res_x = mda->crtc[1]; - video_res_y = mda->crtc[6]; - video_bpp = 0; - } - mda->firstline = 1000; - mda->lastline = 0; - mda->blink++; - } - } else { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - } - if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) { - mda->con = 1; - } - } - VIDEO_MONITOR_EPILOGUE(); -} - -void -mda_init(mda_t *mda) -{ - for (uint16_t c = 0; c < 256; c++) { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) - mdacols[c][0][1] = 15 + 16; - else - mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - - overscan_x = overscan_y = 0; - mda->monitor_index = monitor_index_global; - - cga_palette = device_get_config_int("rgb_type") << 1; - if (cga_palette > 6) { - cga_palette = 0; - } - cgapal_rebuild(); - - timer_add(&mda->timer, mda_poll, mda, 1); - timer_add(&mda->dot_timer, mda_dot_poll, mda, 1); -} - -void * -mda_standalone_init(UNUSED(const device_t *info)) -{ - mda_t *mda = malloc(sizeof(mda_t)); - memset(mda, 0, sizeof(mda_t)); - video_inform(VIDEO_FLAG_TYPE_MDA, &timing_mda); - - mda->vram = malloc(0x1000); - - mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); - io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); - - mda_init(mda); - - lpt3_init(0x3BC); - - return mda; -} - -void -mda_setcol(int chr, int blink, int fg, uint8_t cga_ink) -{ - mdacols[chr][blink][fg] = 16 + cga_ink; -} - -void -mda_close(void *priv) -{ - mda_t *mda = (mda_t *) priv; - - free(mda->vram); - free(mda); -} - -void -mda_speed_changed(void *priv) -{ - mda_t *mda = (mda_t *) priv; - - mda_recalctimings(mda); -} - -static const device_config_t mda_config[] = { - // clang-format off - { - .name = "rgb_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_int = 0, - .selection = { - { - .description = "Default", - .value = 0 - }, - { - .description = "Green", - .value = 1 - }, - { - .description = "Amber", - .value = 2 - }, - { - .description = "Gray", - .value = 3 - }, - { - .description = "" - } - } - }, - { - .type = CONFIG_END - } - // clang-format on -}; - -const device_t mda_device = { - .name = "MDA", - .internal_name = "mda", - .flags = DEVICE_ISA, - .local = 0, - .init = mda_standalone_init, - .close = mda_close, - .reset = NULL, - { .available = NULL }, - .speed_changed = mda_speed_changed, - .force_redraw = NULL, - .config = mda_config -}; diff --git a/src/video/vid_oak_oti - Cópia.c b/src/video/vid_oak_oti - Cópia.c deleted file mode 100644 index 28bf0fc06..000000000 --- a/src/video/vid_oak_oti - Cópia.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Oak OTI037C/67/077 emulation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/mem.h> -#include <86box/rom.h> -#include <86box/device.h> -#include <86box/video.h> -#include <86box/vid_svga.h> -#include <86box/vid_svga_render.h> -#include <86box/plat_unused.h> - -#define BIOS_037C_PATH "roms/video/oti/bios.bin" -#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN" -#define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM" -#define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM" -#define BIOS_077_PATH "roms/video/oti/oti077.vbi" - -enum { - OTI_037C = 0, - OTI_067 = 2, - OTI_067_AMA932J = 3, - OTI_067_M300 = 4, - OTI_077 = 5 -}; - -typedef struct { - svga_t svga; - - rom_t bios_rom; - - int index; - uint8_t regs[32]; - - uint8_t chip_id; - uint8_t pos; - uint8_t enable_register; - uint8_t dipswitch_val; - - uint32_t vram_size; - uint32_t vram_mask; -} oti_t; - -static video_timings_t timing_oti = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; - -static void -oti_out(uint16_t addr, uint8_t val, void *priv) -{ - oti_t *oti = (oti_t *) priv; - svga_t *svga = &oti->svga; - uint8_t old; - uint8_t idx; - uint8_t enable = 0; - uint16_t page = 0x0000; - - if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3)) - return; - - if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) { - case 0x3C3: - if (!oti->chip_id) { - oti->enable_register = val & 1; - return; - } - svga_out(addr, val, svga); - return; - - case 0x3c6: - case 0x3c7: - case 0x3c8: - case 0x3c9: - if (oti->chip_id == OTI_077) - sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); - else - svga_out(addr, val, svga); - return; - - case 0x3D4: - if (oti->chip_id) - svga->crtcreg = val & 0x3f; - else - svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */ - return; - - case 0x3D5: - if (oti->chip_id && (svga->crtcreg & 0x20)) - return; - idx = svga->crtcreg; - if (!oti->chip_id) - idx &= 0x1f; - if ((idx < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((idx == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[idx]; - svga->crtc[idx] = val; - if (old != val) { - if ((idx < 0x0e) || (idx > 0x10)) { - if (idx == 0x0c || idx == 0x0d) { - svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); - } else { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - } - break; - - case 0x3DE: - if (oti->chip_id) - oti->index = val & 0x1f; - else - oti->index = val; - return; - - case 0x3DF: - idx = oti->index; - if (!oti->chip_id) - idx &= 0x1f; - oti->regs[idx] = val; - switch (idx) { - case 0xD: - if (oti->chip_id == OTI_067) { - svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; - - switch ((val & 0x80) >> 7) { - case 0x00: /* 256 kB of memory */ - default: - enable = (oti->vram_size >= 256); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff); - break; - case 0x01: /* 512 kB of memory */ - enable = (oti->vram_size >= 512); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff); - break; - } - - if (enable) - mem_mapping_enable(&svga->mapping); - else - mem_mapping_disable(&svga->mapping); - } else if (oti->chip_id == OTI_077) { - svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; - - switch ((val & 0xc0) >> 6) { - default: - case 0x00: /* 256 kB of memory */ - enable = (oti->vram_size >= 256); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff); - break; - case 0x01: /* 1 MB of memory */ - case 0x03: - enable = (oti->vram_size >= 1024); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0xfffff); - break; - case 0x02: /* 512 kB of memory */ - enable = (oti->vram_size >= 512); - if (val & 0x0c) - svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff); - break; - } - } else { - if (val & 0x80) - mem_mapping_disable(&svga->mapping); - else - mem_mapping_enable(&svga->mapping); - } - break; - - case 0x11: - if (oti->chip_id >= OTI_067) { - page = (((uint16_t) oti->regs[0x14] & 0x40) >> 6); - if (oti->chip_id == OTI_077) - page |= (((uint16_t) oti->regs[0x16] & 0x40) >> 5); - page <<= 18; - } - svga->read_bank = ((uint16_t) oti->regs[0x11] & 0xf) << 14; - svga->write_bank = ((uint16_t) oti->regs[0x11] >> 4) << 14; - svga->read_bank |= page; - svga->write_bank |= page; - break; - - case 0x14: - if (oti->chip_id >= OTI_067) { - page = (((uint16_t) oti->regs[0x14] & 0x40) >> 6); - if (oti->chip_id == OTI_077) - page |= (((uint16_t) oti->regs[0x16] & 0x40) >> 5); - page <<= 18; - svga->read_bank = ((uint16_t) oti->regs[0x11] & 0xf) << 14; - svga->write_bank = ((uint16_t) oti->regs[0x11] >> 4) << 14; - svga->read_bank |= page; - svga->write_bank |= page; - } - break; - case 0x16: - if (oti->chip_id == OTI_077) { - page = (((uint16_t) oti->regs[0x14] & 0x40) >> 6); - page |= (((uint16_t) oti->regs[0x16] & 0x40) >> 5); - page <<= 18; - svga->read_bank = ((uint16_t) oti->regs[0x11] & 0xf) << 14; - svga->write_bank = ((uint16_t) oti->regs[0x11] >> 4) << 14; - svga->read_bank |= page; - svga->write_bank |= page; - } - break; - - default: - break; - } - return; - - default: - break; - } - - svga_out(addr, val, svga); -} - -static uint8_t -oti_in(uint16_t addr, void *priv) -{ - oti_t *oti = (oti_t *) priv; - svga_t *svga = &oti->svga; - uint8_t idx; - uint8_t temp; - - if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3)) - return 0xff; - - if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) { - case 0x3C2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) - temp = 0; - else - temp = 0x10; - break; - - case 0x3C3: - if (oti->chip_id) - temp = svga_in(addr, svga); - else - temp = oti->enable_register; - break; - - case 0x3c6: - case 0x3c7: - case 0x3c8: - case 0x3c9: - if (oti->chip_id == OTI_077) - return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); - return svga_in(addr, svga); - - case 0x3CF: - return svga->gdcreg[svga->gdcaddr & 0xf]; - - case 0x3D4: - temp = svga->crtcreg; - break; - - case 0x3D5: - if (oti->chip_id) { - if (svga->crtcreg & 0x20) - temp = 0xff; - else - temp = svga->crtc[svga->crtcreg]; - } else - temp = svga->crtc[svga->crtcreg & 0x1f]; - break; - - case 0x3DA: - if (oti->chip_id) { - temp = svga_in(addr, svga); - break; - } - - svga->attrff = 0; - /*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again - and expects the diagnostic bits to equal the current border colour. As I understand - it, the 0x3da active enable status does not include the border time, so this may be - an area where OTI-037C is not entirely VGA compatible.*/ - svga->cgastat &= ~0x30; - /* copy color diagnostic info from the overscan color register */ - switch (svga->attrregs[0x12] & 0x30) { - case 0x00: /* P0 and P2 */ - if (svga->attrregs[0x11] & 0x01) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x04) - svga->cgastat |= 0x20; - break; - case 0x10: /* P4 and P5 */ - if (svga->attrregs[0x11] & 0x10) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x20) - svga->cgastat |= 0x20; - break; - case 0x20: /* P1 and P3 */ - if (svga->attrregs[0x11] & 0x02) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x08) - svga->cgastat |= 0x20; - break; - case 0x30: /* P6 and P7 */ - if (svga->attrregs[0x11] & 0x40) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x80) - svga->cgastat |= 0x20; - break; - - default: - break; - } - temp = svga->cgastat; - break; - - case 0x3DE: - temp = oti->index; - if (oti->chip_id) - temp |= (oti->chip_id << 5); - break; - - case 0x3DF: - idx = oti->index; - if (!oti->chip_id) - idx &= 0x1f; - if (idx == 0x10) - temp = oti->dipswitch_val; - else - temp = oti->regs[idx]; - break; - - default: - temp = svga_in(addr, svga); - break; - } - - return temp; -} - -static void -oti_pos_out(UNUSED(uint16_t addr), uint8_t val, void *priv) -{ - oti_t *oti = (oti_t *) priv; - - if ((val ^ oti->pos) & 8) { - if (val & 8) - io_sethandler(0x03c0, 32, oti_in, NULL, NULL, - oti_out, NULL, NULL, oti); - else - io_removehandler(0x03c0, 32, oti_in, NULL, NULL, - oti_out, NULL, NULL, oti); - } - - oti->pos = val; -} - -static uint8_t -oti_pos_in(UNUSED(uint16_t addr), void *priv) -{ - const oti_t *oti = (oti_t *) priv; - - return (oti->pos); -} - -static float -oti_getclock(int clock) -{ - float ret = 0.0; - - switch (clock) { - default: - case 0: - ret = 25175000.0; - break; - case 1: - ret = 28322000.0; - break; - case 4: - ret = 14318000.0; - break; - case 5: - ret = 16257000.0; - break; - case 7: - ret = 35500000.0; - break; - } - - return ret; -} - -static void -oti_recalctimings(svga_t *svga) -{ - const oti_t *oti = (oti_t *) svga->priv; - int clk_sel = ((svga->miscout >> 2) & 3) | ((oti->regs[0x0d] & 0x20) >> 3); - - svga->clock = (cpuclock * (double) (1ULL << 32)) / oti_getclock(clk_sel); - - if (oti->chip_id > 0) { - if (oti->regs[0x14] & 0x08) - svga->ma_latch |= 0x10000; - if (oti->regs[0x16] & 0x08) - svga->ma_latch |= 0x20000; - - if (oti->regs[0x14] & 0x01) - svga->vtotal += 0x400; - if (oti->regs[0x14] & 0x02) - svga->dispend += 0x400; - if (oti->regs[0x14] & 0x04) - svga->vsyncstart += 0x400; - - svga->interlace = oti->regs[0x14] & 0x80; - } - - if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10)) - svga->rowoffset <<= 1; - - if (svga->bpp == 16) { - svga->render = svga_render_16bpp_highres; - svga->hdisp >>= 1; - } else if (svga->bpp == 15) { - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - } -} - -static void * -oti_init(const device_t *info) -{ - oti_t *oti = malloc(sizeof(oti_t)); - const char *romfn = NULL; - - memset(oti, 0x00, sizeof(oti_t)); - oti->chip_id = info->local; - - oti->dipswitch_val = 0x18; - - switch (oti->chip_id) { - case OTI_037C: - romfn = BIOS_037C_PATH; - oti->vram_size = 256; - oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */ -#if 0 - io_sethandler(0x03c0, 32, - oti_in, NULL, NULL, oti_out, NULL, NULL, oti); -#endif - break; - - case OTI_067_AMA932J: - romfn = BIOS_067_AMA932J_PATH; - oti->chip_id = 2; - oti->vram_size = device_get_config_int("memory"); - oti->dipswitch_val |= 0x20; - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; - - case OTI_067_M300: - if (rom_present(BIOS_067_M300_15_PATH)) - romfn = BIOS_067_M300_15_PATH; - else - romfn = BIOS_067_M300_08_PATH; - oti->vram_size = device_get_config_int("memory"); - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; - - case OTI_067: - case OTI_077: - romfn = BIOS_077_PATH; - oti->vram_size = device_get_config_int("memory"); - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; - - default: - break; - } - - if (romfn != NULL) { - rom_init(&oti->bios_rom, romfn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); - - svga_init(info, &oti->svga, oti, oti->vram_size << 10, - oti_recalctimings, oti_in, oti_out, NULL, NULL); - - oti->vram_mask = (oti->vram_size << 10) - 1; - - if (oti->chip_id == OTI_077) - oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ - - io_sethandler(0x03c0, 32, - oti_in, NULL, NULL, oti_out, NULL, NULL, oti); - - oti->svga.miscout = 1; - oti->svga.packed_chain4 = 1; - - return oti; -} - -static void -oti_close(void *priv) -{ - oti_t *oti = (oti_t *) priv; - - svga_close(&oti->svga); - - free(oti); -} - -static void -oti_speed_changed(void *priv) -{ - oti_t *oti = (oti_t *) priv; - - svga_recalctimings(&oti->svga); -} - -static void -oti_force_redraw(void *priv) -{ - oti_t *oti = (oti_t *) priv; - - oti->svga.fullchange = changeframecount; -} - -static int -oti037c_available(void) -{ - return (rom_present(BIOS_037C_PATH)); -} - -static int -oti067_ama932j_available(void) -{ - return (rom_present(BIOS_067_AMA932J_PATH)); -} - -static int -oti067_077_available(void) -{ - return (rom_present(BIOS_077_PATH)); -} - -static int -oti067_m300_available(void) -{ - if (rom_present(BIOS_067_M300_15_PATH)) - return (rom_present(BIOS_067_M300_15_PATH)); - else - return (rom_present(BIOS_067_M300_08_PATH)); -} - -// clang-format off -static const device_config_t oti067_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 512, - .selection = { - { - .description = "256 kB", - .value = 256 - }, - { - .description = "512 kB", - .value = 512 - }, - { - .description = "" - } - } - }, - { - .type = CONFIG_END - } -}; - -static const device_config_t oti067_ama932j_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 256, - .selection = { - { - .description = "256 kB", - .value = 256 - }, - { - .description = "512 kB", - .value = 512 - }, - { - .description = "" - } - } - }, - { - .type = CONFIG_END - } -}; - -static const device_config_t oti077_config[] = { - { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .default_int = 1024, - .selection = { - { - .description = "256 kB", - .value = 256 - }, - { - .description = "512 kB", - .value = 512 - }, - { - .description = "1 MB", - .value = 1024 - }, - { - .description = "" - } - } - }, - { - .type = CONFIG_END - } -}; -// clang-format on - -const device_t oti037c_device = { - .name = "Oak OTI-037C", - .internal_name = "oti037c", - .flags = DEVICE_ISA, - .local = 0, - .init = oti_init, - .close = oti_close, - .reset = NULL, - { .available = oti037c_available }, - .speed_changed = oti_speed_changed, - .force_redraw = oti_force_redraw, - .config = NULL -}; - -const device_t oti067_device = { - .name = "Oak OTI-067", - .internal_name = "oti067", - .flags = DEVICE_ISA, - .local = 2, - .init = oti_init, - .close = oti_close, - .reset = NULL, - { .available = oti067_077_available }, - .speed_changed = oti_speed_changed, - .force_redraw = oti_force_redraw, - .config = oti067_config -}; - -const device_t oti067_m300_device = { - .name = "Oak OTI-067 (Olivetti M300-08/15)", - .internal_name = "oti067_m300", - .flags = DEVICE_ISA, - .local = 4, - .init = oti_init, - .close = oti_close, - .reset = NULL, - { .available = oti067_m300_available }, - .speed_changed = oti_speed_changed, - .force_redraw = oti_force_redraw, - .config = oti067_config -}; - -const device_t oti067_ama932j_device = { - .name = "Oak OTI-067 (AMA-932J)", - .internal_name = "oti067_ama932j", - .flags = DEVICE_ISA, - .local = 3, - .init = oti_init, - .close = oti_close, - .reset = NULL, - { .available = oti067_ama932j_available }, - .speed_changed = oti_speed_changed, - .force_redraw = oti_force_redraw, - .config = oti067_ama932j_config -}; - -const device_t oti077_device = { - .name = "Oak OTI-077", - .internal_name = "oti077", - .flags = DEVICE_ISA, - .local = 5, - .init = oti_init, - .close = oti_close, - .reset = NULL, - { .available = oti067_077_available }, - .speed_changed = oti_speed_changed, - .force_redraw = oti_force_redraw, - .config = oti077_config -};