From 9e77acf6557dbad69c91b6a886b921cbc35371d6 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 19 Nov 2022 09:49:14 -0500 Subject: [PATCH] clang format in codegen & codegen_new --- src/codegen/codegen.c | 22 +- src/codegen/codegen.h | 422 +- src/codegen/codegen_accumulate.h | 7 +- src/codegen/codegen_accumulate_x86-64.c | 86 +- src/codegen/codegen_accumulate_x86.c | 80 +- src/codegen/codegen_ops.c | 4 +- src/codegen/codegen_ops.h | 32 +- src/codegen/codegen_ops_arith.h | 1834 ++- src/codegen/codegen_ops_fpu.h | 726 +- src/codegen/codegen_ops_logic.h | 1058 +- src/codegen/codegen_ops_misc.h | 469 +- src/codegen/codegen_ops_mmx.h | 406 +- src/codegen/codegen_ops_mov.h | 1135 +- src/codegen/codegen_ops_shift.h | 190 +- src/codegen/codegen_ops_stack.h | 388 +- src/codegen/codegen_ops_x86-64.h | 11193 ++++++++-------- src/codegen/codegen_ops_x86.h | 6984 +++++----- src/codegen/codegen_ops_xchg.h | 115 +- src/codegen/codegen_x86-64.c | 2146 ++- src/codegen/codegen_x86-64.h | 21 +- src/codegen/codegen_x86.c | 4072 +++--- src/codegen/codegen_x86.h | 21 +- src/codegen_new/codegen.c | 1191 +- src/codegen_new/codegen.h | 452 +- src/codegen_new/codegen_accumulate.c | 36 +- src/codegen_new/codegen_accumulate.h | 7 +- src/codegen_new/codegen_allocator.c | 182 +- src/codegen_new/codegen_allocator.h | 6 +- src/codegen_new/codegen_backend.h | 17 +- src/codegen_new/codegen_backend_arm.c | 578 +- src/codegen_new/codegen_backend_arm.h | 12 +- src/codegen_new/codegen_backend_arm64.c | 593 +- src/codegen_new/codegen_backend_arm64.h | 13 +- src/codegen_new/codegen_backend_arm64_defs.h | 212 +- src/codegen_new/codegen_backend_arm64_imm.c | 2633 ++-- src/codegen_new/codegen_backend_arm64_ops.c | 1886 +-- src/codegen_new/codegen_backend_arm64_ops.h | 10 +- src/codegen_new/codegen_backend_arm64_uops.c | 5515 ++++---- src/codegen_new/codegen_backend_arm_defs.h | 121 +- src/codegen_new/codegen_backend_arm_ops.c | 1701 +-- src/codegen_new/codegen_backend_arm_ops.h | 38 +- src/codegen_new/codegen_backend_arm_uops.c | 6273 +++++---- src/codegen_new/codegen_backend_x86-64.c | 646 +- src/codegen_new/codegen_backend_x86-64.h | 12 +- src/codegen_new/codegen_backend_x86-64_defs.h | 84 +- src/codegen_new/codegen_backend_x86-64_ops.c | 3337 +++-- .../codegen_backend_x86-64_ops_helpers.h | 151 +- .../codegen_backend_x86-64_ops_sse.c | 1202 +- src/codegen_new/codegen_backend_x86-64_uops.c | 5943 ++++---- src/codegen_new/codegen_backend_x86.c | 573 +- src/codegen_new/codegen_backend_x86.h | 12 +- src/codegen_new/codegen_backend_x86_defs.h | 38 +- src/codegen_new/codegen_backend_x86_ops.c | 2387 ++-- src/codegen_new/codegen_backend_x86_ops.h | 2 +- src/codegen_new/codegen_backend_x86_ops_fpu.c | 124 +- .../codegen_backend_x86_ops_helpers.h | 118 +- src/codegen_new/codegen_backend_x86_ops_sse.c | 989 +- src/codegen_new/codegen_backend_x86_uops.c | 5938 ++++---- src/codegen_new/codegen_block.c | 1353 +- src/codegen_new/codegen_ir.c | 312 +- src/codegen_new/codegen_ir_defs.h | 934 +- src/codegen_new/codegen_ops.h | 32 +- src/codegen_new/codegen_ops_3dnow.c | 297 +- src/codegen_new/codegen_ops_arith.c | 4415 +++--- src/codegen_new/codegen_ops_arith.h | 1 - src/codegen_new/codegen_ops_branch.c | 1885 ++- src/codegen_new/codegen_ops_fpu_arith.c | 908 +- src/codegen_new/codegen_ops_fpu_constant.c | 30 +- src/codegen_new/codegen_ops_fpu_loadstore.c | 331 +- src/codegen_new/codegen_ops_fpu_misc.c | 134 +- src/codegen_new/codegen_ops_helpers.c | 91 +- src/codegen_new/codegen_ops_helpers.h | 169 +- src/codegen_new/codegen_ops_jump.c | 435 +- src/codegen_new/codegen_ops_logic.c | 1184 +- src/codegen_new/codegen_ops_misc.c | 1042 +- src/codegen_new/codegen_ops_mmx_arith.c | 47 +- src/codegen_new/codegen_ops_mmx_cmp.c | 47 +- src/codegen_new/codegen_ops_mmx_loadstore.c | 148 +- src/codegen_new/codegen_ops_mmx_logic.c | 144 +- src/codegen_new/codegen_ops_mmx_pack.c | 47 +- src/codegen_new/codegen_ops_mmx_shift.c | 135 +- src/codegen_new/codegen_ops_mov.c | 1349 +- src/codegen_new/codegen_ops_shift.c | 2133 ++- src/codegen_new/codegen_ops_stack.c | 646 +- src/codegen_new/codegen_reg.c | 1391 +- src/codegen_new/codegen_reg.h | 568 +- 86 files changed, 46864 insertions(+), 47787 deletions(-) diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 355653e63..f2d678067 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -16,21 +16,23 @@ void (*codegen_timing_block_start)(void); void (*codegen_timing_block_end)(void); int (*codegen_timing_jump_cycles)(void); -void codegen_timing_set(codegen_timing_t *timing) +void +codegen_timing_set(codegen_timing_t *timing) { - codegen_timing_start = timing->start; - codegen_timing_prefix = timing->prefix; - codegen_timing_opcode = timing->opcode; - codegen_timing_block_start = timing->block_start; - codegen_timing_block_end = timing->block_end; - codegen_timing_jump_cycles = timing->jump_cycles; + codegen_timing_start = timing->start; + codegen_timing_prefix = timing->prefix; + codegen_timing_opcode = timing->opcode; + codegen_timing_block_start = timing->block_start; + codegen_timing_block_end = timing->block_end; + codegen_timing_jump_cycles = timing->jump_cycles; } int codegen_in_recompile; /* This is for compatibility with new x87 code. */ -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - /* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */ - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); + /* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */ + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10); } diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h index a0740e27d..af602427d 100644 --- a/src/codegen/codegen.h +++ b/src/codegen/codegen.h @@ -41,11 +41,11 @@ #include "x86_ops.h" #ifdef __amd64__ -#include "codegen_x86-64.h" +# include "codegen_x86-64.h" #elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64 -#include "codegen_x86.h" +# include "codegen_x86.h" #else -#error Dynamic recompiler not implemented on your platform +# error Dynamic recompiler not implemented on your platform #endif /*Handling self-modifying code (of which there is a lot on x86) : @@ -73,38 +73,37 @@ same page). */ -typedef struct codeblock_t -{ - uint64_t page_mask, page_mask2; - uint64_t *dirty_mask, *dirty_mask2; - uint64_t cmp; +typedef struct codeblock_t { + uint64_t page_mask, page_mask2; + uint64_t *dirty_mask, *dirty_mask2; + uint64_t cmp; - /*Previous and next pointers, for the codeblock list associated with - each physical page. Two sets of pointers, as a codeblock can be - present in two pages.*/ - struct codeblock_t *prev, *next; - struct codeblock_t *prev_2, *next_2; + /*Previous and next pointers, for the codeblock list associated with + each physical page. Two sets of pointers, as a codeblock can be + present in two pages.*/ + struct codeblock_t *prev, *next; + struct codeblock_t *prev_2, *next_2; - /*Pointers for codeblock tree, used to search for blocks when hash lookup - fails.*/ - struct codeblock_t *parent, *left, *right; + /*Pointers for codeblock tree, used to search for blocks when hash lookup + fails.*/ + struct codeblock_t *parent, *left, *right; - int pnt; - int ins; + int pnt; + int ins; int valid; - int was_recompiled; - int TOP; + int was_recompiled; + int TOP; - uint32_t pc; - uint32_t _cs; - uint32_t endpc; - uint32_t phys, phys_2; - uint32_t status; - uint32_t flags; + uint32_t pc; + uint32_t _cs; + uint32_t endpc; + uint32_t phys, phys_2; + uint32_t status; + uint32_t flags; - uint8_t data[2048]; + uint8_t data[2048]; } codeblock_t; /*Code block uses FPU*/ @@ -112,181 +111,155 @@ typedef struct codeblock_t /*Code block is always entered with the same FPU top-of-stack*/ #define CODEBLOCK_STATIC_TOP 2 -static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) +static inline codeblock_t * +codeblock_tree_find(uint32_t phys, uint32_t _cs) { - codeblock_t *block = pages[phys >> 12].head; - uint64_t a = _cs | ((uint64_t)phys << 32); + codeblock_t *block = pages[phys >> 12].head; + uint64_t a = _cs | ((uint64_t) phys << 32); - while (block) - { - if (a == block->cmp) - { - if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) - break; - } - if (a < block->cmp) - block = block->left; - else - block = block->right; - } - - return block; -} - -static inline void codeblock_tree_add(codeblock_t *new_block) -{ - codeblock_t *block = pages[new_block->phys >> 12].head; - uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); - new_block->cmp = a; - - if (!block) - { - pages[new_block->phys >> 12].head = new_block; - new_block->parent = new_block->left = new_block->right = NULL; + while (block) { + if (a == block->cmp) { + if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) + break; } + if (a < block->cmp) + block = block->left; else - { - codeblock_t *old_block = NULL; + block = block->right; + } - while (block) - { - old_block = block; - if (a < old_block->cmp) - block = block->left; - else - block = block->right; - } - - if (a < old_block->cmp) - old_block->left = new_block; - else - old_block->right = new_block; - - new_block->parent = old_block; - new_block->left = new_block->right = NULL; - } + return block; } -static inline void codeblock_tree_delete(codeblock_t *block) +static inline void +codeblock_tree_add(codeblock_t *new_block) { - codeblock_t *parent = block->parent; + codeblock_t *block = pages[new_block->phys >> 12].head; + uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32); + new_block->cmp = a; - if (!block->left && !block->right) - { - /*Easy case - remove from parent*/ - if (!parent) - pages[block->phys >> 12].head = NULL; - else - { - if (parent->left == block) - parent->left = NULL; - if (parent->right == block) - parent->right = NULL; - } - return; - } - else if (!block->left) - { - /*Only right node*/ - if (!parent) - { - pages[block->phys >> 12].head = block->right; - pages[block->phys >> 12].head->parent = NULL; - } - else - { - if (parent->left == block) - { - parent->left = block->right; - parent->left->parent = parent; - } - if (parent->right == block) - { - parent->right = block->right; - parent->right->parent = parent; - } - } - return; - } - else if (!block->right) - { - /*Only left node*/ - if (!parent) - { - pages[block->phys >> 12].head = block->left; - pages[block->phys >> 12].head->parent = NULL; - } - else - { - if (parent->left == block) - { - parent->left = block->left; - parent->left->parent = parent; - } - if (parent->right == block) - { - parent->right = block->left; - parent->right->parent = parent; - } - } - return; + if (!block) { + pages[new_block->phys >> 12].head = new_block; + new_block->parent = new_block->left = new_block->right = NULL; + } else { + codeblock_t *old_block = NULL; + + while (block) { + old_block = block; + if (a < old_block->cmp) + block = block->left; + else + block = block->right; } + + if (a < old_block->cmp) + old_block->left = new_block; else - { - /*Difficult case - node has two children. Walk right child to find lowest node*/ - codeblock_t *lowest = block->right, *highest; - codeblock_t *old_parent; + old_block->right = new_block; - while (lowest->left) - lowest = lowest->left; - - old_parent = lowest->parent; - - /*Replace deleted node with lowest node*/ - if (!parent) - pages[block->phys >> 12].head = lowest; - else - { - if (parent->left == block) - parent->left = lowest; - if (parent->right == block) - parent->right = lowest; - } - - lowest->parent = parent; - lowest->left = block->left; - if (lowest->left) - lowest->left->parent = lowest; - - old_parent->left = NULL; - - highest = lowest->right; - if (!highest) - { - if (lowest != block->right) - { - lowest->right = block->right; - block->right->parent = lowest; - } - return; - } - - while (highest->right) - highest = highest->right; - - if (block->right && block->right != lowest) - { - highest->right = block->right; - block->right->parent = highest; - } - } + new_block->parent = old_block; + new_block->left = new_block->right = NULL; + } } -#define PAGE_MASK_INDEX_MASK 3 +static inline void +codeblock_tree_delete(codeblock_t *block) +{ + codeblock_t *parent = block->parent; + + if (!block->left && !block->right) { + /*Easy case - remove from parent*/ + if (!parent) + pages[block->phys >> 12].head = NULL; + else { + if (parent->left == block) + parent->left = NULL; + if (parent->right == block) + parent->right = NULL; + } + return; + } else if (!block->left) { + /*Only right node*/ + if (!parent) { + pages[block->phys >> 12].head = block->right; + pages[block->phys >> 12].head->parent = NULL; + } else { + if (parent->left == block) { + parent->left = block->right; + parent->left->parent = parent; + } + if (parent->right == block) { + parent->right = block->right; + parent->right->parent = parent; + } + } + return; + } else if (!block->right) { + /*Only left node*/ + if (!parent) { + pages[block->phys >> 12].head = block->left; + pages[block->phys >> 12].head->parent = NULL; + } else { + if (parent->left == block) { + parent->left = block->left; + parent->left->parent = parent; + } + if (parent->right == block) { + parent->right = block->left; + parent->right->parent = parent; + } + } + return; + } else { + /*Difficult case - node has two children. Walk right child to find lowest node*/ + codeblock_t *lowest = block->right, *highest; + codeblock_t *old_parent; + + while (lowest->left) + lowest = lowest->left; + + old_parent = lowest->parent; + + /*Replace deleted node with lowest node*/ + if (!parent) + pages[block->phys >> 12].head = lowest; + else { + if (parent->left == block) + parent->left = lowest; + if (parent->right == block) + parent->right = lowest; + } + + lowest->parent = parent; + lowest->left = block->left; + if (lowest->left) + lowest->left->parent = lowest; + + old_parent->left = NULL; + + highest = lowest->right; + if (!highest) { + if (lowest != block->right) { + lowest->right = block->right; + block->right->parent = lowest; + } + return; + } + + while (highest->right) + highest = highest->right; + + if (block->right && block->right != lowest) { + highest->right = block->right; + block->right->parent = highest; + } + } +} + +#define PAGE_MASK_INDEX_MASK 3 #define PAGE_MASK_INDEX_SHIFT 10 -#define PAGE_MASK_MASK 63 -#define PAGE_MASK_SHIFT 4 +#define PAGE_MASK_MASK 63 +#define PAGE_MASK_SHIFT 4 extern codeblock_t *codeblock; @@ -305,7 +278,7 @@ extern void codegen_set_op32(void); extern void codegen_flush(void); extern void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr); -extern int cpu_block_end; +extern int cpu_block_end; extern uint32_t codegen_endpc; extern int codegen_block_cycles; @@ -317,14 +290,13 @@ extern void (*codegen_timing_block_start)(void); extern void (*codegen_timing_block_end)(void); extern int (*codegen_timing_jump_cycles)(void); -typedef struct codegen_timing_t -{ - void (*start)(void); - void (*prefix)(uint8_t prefix, uint32_t fetchdat); - void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); - void (*block_start)(void); - void (*block_end)(void); - int (*jump_cycles)(void); +typedef struct codegen_timing_t { + void (*start)(void); + void (*prefix)(uint8_t prefix, uint32_t fetchdat); + void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); + void (*block_start)(void); + void (*block_end)(void); + int (*jump_cycles)(void); } codegen_timing_t; extern codegen_timing_t codegen_timing_pentium; @@ -342,53 +314,53 @@ extern int block_pos; #define CPU_BLOCK_END() cpu_block_end = 1 -static inline void addbyte(uint8_t val) +static inline void +addbyte(uint8_t val) { - codeblock[block_current].data[block_pos++] = val; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + codeblock[block_current].data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } -static inline void addword(uint16_t val) +static inline void +addword(uint16_t val) { uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos]; - *p = val; - block_pos += 2; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + *p = val; + block_pos += 2; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } -static inline void addlong(uint32_t val) +static inline void +addlong(uint32_t val) { uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos]; - *p = val; - block_pos += 4; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + *p = val; + block_pos += 4; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } -static inline void addquad(uint64_t val) +static inline void +addquad(uint64_t val) { uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos]; - *p = val; - block_pos += 8; - if (block_pos >= BLOCK_MAX) - { - CPU_BLOCK_END(); - } + *p = val; + block_pos += 8; + if (block_pos >= BLOCK_MAX) { + CPU_BLOCK_END(); + } } /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; -extern x86seg *op_ea_seg; -extern int op_ssegs; +extern x86seg *op_ea_seg; +extern int op_ssegs; extern uint32_t op_old_pc; /*Set to 1 if flags have been changed in the block being recompiled, and hence diff --git a/src/codegen/codegen_accumulate.h b/src/codegen/codegen_accumulate.h index 4d85ec0b4..3e8261748 100644 --- a/src/codegen/codegen_accumulate.h +++ b/src/codegen/codegen_accumulate.h @@ -1,8 +1,7 @@ -enum -{ - ACCREG_cycles = 0, +enum { + ACCREG_cycles = 0, - ACCREG_COUNT + ACCREG_COUNT }; struct ir_data_t; diff --git a/src/codegen/codegen_accumulate_x86-64.c b/src/codegen/codegen_accumulate_x86-64.c index e7f584f29..6e88487ba 100644 --- a/src/codegen/codegen_accumulate_x86-64.c +++ b/src/codegen/codegen_accumulate_x86-64.c @@ -9,59 +9,61 @@ static struct { - int count; - uintptr_t dest_reg; -} acc_regs[] = -{ - [ACCREG_cycles] = {0, (uintptr_t) &(cycles)}, + int count; + uintptr_t dest_reg; +} acc_regs[] = { + [ACCREG_cycles] = {0, (uintptr_t) & (cycles)}, }; -void codegen_accumulate(int acc_reg, int delta) +void +codegen_accumulate(int acc_reg, int delta) { - acc_regs[acc_reg].count += delta; + acc_regs[acc_reg].count += delta; #ifdef USE_ACYCS - if ((acc_reg == ACCREG_cycles) && (delta != 0)) { - if (delta == -1) { - /* -delta = 1 */ - addbyte(0xff); /*inc dword ptr[&acycs]*/ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else if (delta == 1) { - /* -delta = -1 */ - addbyte(0xff); /*dec dword ptr[&acycs]*/ - addbyte(0x0c); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else { - addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &(acycs)); - addlong(-delta); - } - } + if ((acc_reg == ACCREG_cycles) && (delta != 0)) { + if (delta == -1) { + /* -delta = 1 */ + addbyte(0xff); /*inc dword ptr[&acycs]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else if (delta == 1) { + /* -delta = -1 */ + addbyte(0xff); /*dec dword ptr[&acycs]*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else { + addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) & (acycs)); + addlong(-delta); + } + } #endif } -void codegen_accumulate_flush(void) +void +codegen_accumulate_flush(void) { - if (acc_regs[0].count) { - /* To reduce the size of the generated code, we take advantage of - the fact that the target offset points to _cycles within cpu_state, - so we can just use our existing infrastracture for variables - relative to cpu_state. */ - addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addlong(acc_regs[0].count); - } + if (acc_regs[0].count) { + /* To reduce the size of the generated code, we take advantage of + the fact that the target offset points to _cycles within cpu_state, + so we can just use our existing infrastracture for variables + relative to cpu_state. */ + addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addlong(acc_regs[0].count); + } - acc_regs[0].count = 0; + acc_regs[0].count = 0; } -void codegen_accumulate_reset(void) +void +codegen_accumulate_reset(void) { - acc_regs[0].count = 0; + acc_regs[0].count = 0; } diff --git a/src/codegen/codegen_accumulate_x86.c b/src/codegen/codegen_accumulate_x86.c index fb383846d..8d56c4c14 100644 --- a/src/codegen/codegen_accumulate_x86.c +++ b/src/codegen/codegen_accumulate_x86.c @@ -9,56 +9,58 @@ static struct { - int count; - uintptr_t dest_reg; -} acc_regs[] = -{ - [ACCREG_cycles] = {0, (uintptr_t) &(cycles)} + int count; + uintptr_t dest_reg; +} acc_regs[] = { + [ACCREG_cycles] = {0, (uintptr_t) & (cycles)} }; -void codegen_accumulate(int acc_reg, int delta) +void +codegen_accumulate(int acc_reg, int delta) { - acc_regs[acc_reg].count += delta; + acc_regs[acc_reg].count += delta; #ifdef USE_ACYCS - if ((acc_reg == ACCREG_cycles) && (delta != 0)) { - if (delta == -1) { - /* -delta = 1 */ - addbyte(0xff); /*inc dword ptr[&acycs]*/ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else if (delta == 1) { - /* -delta = -1 */ - addbyte(0xff); /*dec dword ptr[&acycs]*/ - addbyte(0x0d); - addlong((uint32_t) (uintptr_t) &(acycs)); - } else { - addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(acycs)); - addlong((uintptr_t) -delta); - } - } + if ((acc_reg == ACCREG_cycles) && (delta != 0)) { + if (delta == -1) { + /* -delta = 1 */ + addbyte(0xff); /*inc dword ptr[&acycs]*/ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else if (delta == 1) { + /* -delta = -1 */ + addbyte(0xff); /*dec dword ptr[&acycs]*/ + addbyte(0x0d); + addlong((uint32_t) (uintptr_t) & (acycs)); + } else { + addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) & (acycs)); + addlong((uintptr_t) -delta); + } + } #endif } -void codegen_accumulate_flush(void) +void +codegen_accumulate_flush(void) { - if (acc_regs[0].count) { - /* To reduce the size of the generated code, we take advantage of - the fact that the target offset points to _cycles within cpu_state, - so we can just use our existing infrastracture for variables - relative to cpu_state. */ - addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(_cycles)); - addlong(acc_regs[0].count); - } + if (acc_regs[0].count) { + /* To reduce the size of the generated code, we take advantage of + the fact that the target offset points to _cycles within cpu_state, + so we can just use our existing infrastracture for variables + relative to cpu_state. */ + addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(_cycles)); + addlong(acc_regs[0].count); + } - acc_regs[0].count = 0; + acc_regs[0].count = 0; } -void codegen_accumulate_reset(void) +void +codegen_accumulate_reset(void) { - acc_regs[0].count = 0; + acc_regs[0].count = 0; } diff --git a/src/codegen/codegen_ops.c b/src/codegen/codegen_ops.c index aedeb88a9..a81e0c6a2 100644 --- a/src/codegen/codegen_ops.c +++ b/src/codegen/codegen_ops.c @@ -16,9 +16,9 @@ #include "codegen_ops.h" #if defined __amd64__ || defined _M_X64 -#include "codegen_ops_x86-64.h" +# include "codegen_ops_x86-64.h" #elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include "codegen_ops_x86.h" +# include "codegen_ops_x86.h" #endif #include "codegen_ops_arith.h" diff --git a/src/codegen/codegen_ops.h b/src/codegen/codegen_ops.h index fe54cb9a4..f92ba4f6d 100644 --- a/src/codegen/codegen_ops.h +++ b/src/codegen/codegen_ops.h @@ -26,21 +26,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512]; #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 -#define REG_AX 0 -#define REG_CX 1 -#define REG_DX 2 -#define REG_BX 3 -#define REG_SP 4 -#define REG_BP 5 -#define REG_SI 6 -#define REG_DI 7 -#define REG_AL 0 -#define REG_AH 4 -#define REG_CL 1 -#define REG_CH 5 -#define REG_DL 2 -#define REG_DH 6 -#define REG_BL 3 -#define REG_BH 7 +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 +#define REG_AL 0 +#define REG_AH 4 +#define REG_CL 1 +#define REG_CH 5 +#define REG_DL 2 +#define REG_DH 6 +#define REG_BL 3 +#define REG_BH 7 #endif diff --git a/src/codegen/codegen_ops_arith.h b/src/codegen/codegen_ops_arith.h index 2e497f17c..f1c426838 100644 --- a/src/codegen/codegen_ops_arith.h +++ b/src/codegen/codegen_ops_arith.h @@ -1,1032 +1,956 @@ -static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - CALL_FUNC((uintptr_t)flags_rebuild_c); + CALL_FUNC((uintptr_t) flags_rebuild_c); - host_reg = LOAD_REG_W(opcode & 7); + host_reg = LOAD_REG_W(opcode & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - // ADD_HOST_REG_IMM_W(host_reg, 1); - INC_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + // ADD_HOST_REG_IMM_W(host_reg, 1); + INC_HOST_REG_W(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); - codegen_flags_changed = 1; + codegen_flags_changed = 1; - return op_pc; + return op_pc; } -static uint32_t ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - CALL_FUNC((uintptr_t)flags_rebuild_c); + CALL_FUNC((uintptr_t) flags_rebuild_c); - host_reg = LOAD_REG_L(opcode & 7); + host_reg = LOAD_REG_L(opcode & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - // ADD_HOST_REG_IMM(host_reg, 1); - INC_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + // ADD_HOST_REG_IMM(host_reg, 1); + INC_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); - codegen_flags_changed = 1; + codegen_flags_changed = 1; - return op_pc; + return op_pc; } -static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - CALL_FUNC((uintptr_t)flags_rebuild_c); + CALL_FUNC((uintptr_t) flags_rebuild_c); - host_reg = LOAD_REG_W(opcode & 7); + host_reg = LOAD_REG_W(opcode & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - // SUB_HOST_REG_IMM_W(host_reg, 1); - DEC_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + // SUB_HOST_REG_IMM_W(host_reg, 1); + DEC_HOST_REG_W(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); - codegen_flags_changed = 1; + codegen_flags_changed = 1; - return op_pc; + return op_pc; } -static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - CALL_FUNC((uintptr_t)flags_rebuild_c); + CALL_FUNC((uintptr_t) flags_rebuild_c); - host_reg = LOAD_REG_L(opcode & 7); + host_reg = LOAD_REG_L(opcode & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - // SUB_HOST_REG_IMM(host_reg, 1); - DEC_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + // SUB_HOST_REG_IMM(host_reg, 1); + DEC_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); - codegen_flags_changed = 1; + codegen_flags_changed = 1; - return op_pc; + return op_pc; } -#define ROP_ARITH_RMW(name, op, writeback) \ - static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \ - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_B_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_W(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \ - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_W_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_L(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \ - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_L_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } +#define ROP_ARITH_RMW(name, op, writeback) \ + static uint32_t rop##name##_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##8); \ + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_B_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_W(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##16); \ + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_W_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_L(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##32); \ + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_L_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } -#define ROP_ARITH_RM(name, op, writeback) \ - static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_B(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_B_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_W_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_L_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - codegen_flags_changed = 1; \ - return op_pc + 1; \ - } +#define ROP_ARITH_RM(name, op, writeback) \ + static uint32_t rop##name##_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_B(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##8); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_B_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##16); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_W_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_##op##32); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_L_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + codegen_flags_changed = 1; \ + return op_pc + 1; \ + } ROP_ARITH_RMW(ADD, ADD, 1) ROP_ARITH_RMW(SUB, SUB, 1) ROP_ARITH_RM(ADD, ADD, 1) ROP_ARITH_RM(SUB, SUB, 1) -static uint32_t ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - src_reg = 0; - } + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_B(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + src_reg = 0; + } - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -static uint32_t ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - src_reg = 0; - } + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_W(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + src_reg = 0; + } - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -static uint32_t ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - src_reg = 0; - } + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_L(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + src_reg = 0; + } - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -static uint32_t ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_B(fetchdat & 7); + if ((fetchdat & 0xc0) == 0xc0) { + dst_reg = LOAD_REG_B(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + dst_reg = 0; + } + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + dst_reg = LOAD_REG_W(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + dst_reg = 0; + } + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + dst_reg = LOAD_REG_L(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + dst_reg = 0; + } + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +static uint32_t +ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; +} +static uint32_t +ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + fetchdat = fastreadl(cs + op_pc); + ADD_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 4; +} + +static uint32_t +ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; +} +static uint32_t +ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + fetchdat = fastreadl(cs + op_pc); + host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 4; +} + +static uint32_t +ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t +ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; +} +static uint32_t +ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + fetchdat = fastreadl(cs + op_pc); + SUB_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + codegen_flags_changed = 1; + return op_pc + 4; +} + +static uint32_t +rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_B(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE(target_seg); + host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - dst_reg = 0; + imm = fastreadb(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_B(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_B(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD8); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm | 0xffffff00); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_B(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_B(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + break; + } + + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_B_RELEASE(host_reg); } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - dst_reg = 0; - } \ - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int src_reg, dst_reg; - - if ((fetchdat & 0xc0) == 0xc0) - { - dst_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - dst_reg = 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, dst_reg); - dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} - - -static uint32_t ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - ADD_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); + } else RELEASE_REG(host_reg); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 2; } -static uint32_t ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); +static uint32_t +rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_W(target_seg); + host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); + } + imm = fastreadw(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_W(fetchdat & 7); + imm = (fetchdat >> 8) & 0xffff; + } + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD16); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + } + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_W_RELEASE(host_reg); + } + } else RELEASE_REG(host_reg); - codegen_flags_changed = 1; - return op_pc + 2; + codegen_flags_changed = 1; + return op_pc + 3; } -static uint32_t ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_L(REG_EAX); + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); + if ((fetchdat & 0x30) == 0x10) + return 0; + + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE(target_seg); + host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); + } + } else { + host_reg = LOAD_REG_L(fetchdat & 7); + } + imm = fastreadl(cs + op_pc + 1); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD32); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + } + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_L_RELEASE(host_reg); + } + } else RELEASE_REG(host_reg); - codegen_flags_changed = 1; - return op_pc + 4; + codegen_flags_changed = 1; + return op_pc + 5; } -static uint32_t ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_B(REG_AL); + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); + if ((fetchdat & 0x30) == 0x10) + return 0; - codegen_flags_changed = 1; - return op_pc + 1; + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_W(target_seg); + host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); + } + imm = fastreadb(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_W(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } + + if (imm & 0x80) + imm |= 0xff80; + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD16); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + break; + } + + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_W_RELEASE(host_reg); + } + } else + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; } -static uint32_t ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_W(REG_AX); + int host_reg; + uint32_t imm; + x86seg *target_seg = NULL; - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); + if ((fetchdat & 0x30) == 0x10) + return 0; - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - fetchdat = fastreadl(cs + op_pc); - SUB_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - codegen_flags_changed = 1; - return op_pc + 4; -} - -static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_B(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_B(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD8); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffffff00); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_B(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - break; - } - - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_B_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} - -static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - imm = fastreadw(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xffff; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - } - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_W_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 3; -} -static uint32_t rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - } - else - { - host_reg = LOAD_REG_L(fetchdat & 7); - } - imm = fastreadl(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - } - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_L_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 5; -} - -static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - if (imm & 0x80) - imm |= 0xff80; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD16); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - break; - } - - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_W_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; -} -static uint32_t rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - uint32_t imm; - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) - return 0; - - if ((fetchdat & 0xc0) != 0xc0) - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - if ((fetchdat & 0x38) == 0x38) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_L(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - imm = fastreadb(cs + op_pc + 1); - } - else - { - host_reg = LOAD_REG_L(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - - if (imm & 0x80) - imm |= 0xffffff80; - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ADD32); - break; - case 0x08: /*OR*/ - OR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - case 0x30: /*XOR*/ - XOR_HOST_REG_IMM(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - break; - case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, imm); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - break; - } - - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0x38) != 0x38) - { - if ((fetchdat & 0xc0) != 0xc0) - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - else - { - STORE_REG_L_RELEASE(host_reg); - } - } - else - RELEASE_REG(host_reg); - - codegen_flags_changed = 1; - return op_pc + 2; + if ((fetchdat & 0xc0) != 0xc0) { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0x38) == 0x38) { + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_L(target_seg); + host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); + } + imm = fastreadb(cs + op_pc + 1); + } else { + host_reg = LOAD_REG_L(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } + + if (imm & 0x80) + imm |= 0xffffff80; + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ADD32); + break; + case 0x08: /*OR*/ + OR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x20: /*AND*/ + AND_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x28: /*SUB*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + case 0x30: /*XOR*/ + XOR_HOST_REG_IMM(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + break; + case 0x38: /*CMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, imm); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + break; + } + + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0x38) != 0x38) { + if ((fetchdat & 0xc0) != 0xc0) { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } else { + STORE_REG_L_RELEASE(host_reg); + } + } else + RELEASE_REG(host_reg); + + codegen_flags_changed = 1; + return op_pc + 2; } diff --git a/src/codegen/codegen_ops_fpu.h b/src/codegen/codegen_ops_fpu.h index 930e0182c..58a5adf7d 100644 --- a/src/codegen/codegen_ops_fpu.h +++ b/src/codegen/codegen_ops_fpu.h @@ -1,256 +1,268 @@ -static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FXCH(opcode & 7); + FP_FXCH(opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FLD(opcode & 7); + FP_FLD(opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FST(opcode & 7); + FP_FST(opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); + FP_ENTER(); - FP_FST(opcode & 7); - FP_POP(); + FP_FST(opcode & 7); + FP_POP(); - return op_pc; + return op_pc; } - -static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); - FP_LOAD_S(); + FP_LOAD_S(); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_Q(target_seg); - FP_LOAD_D(); + FP_LOAD_D(); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_W(target_seg); - FP_LOAD_IW(); + FP_LOAD_IW(); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_L(target_seg); - FP_LOAD_IL(); + FP_LOAD_IL(); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_Q(target_seg); - FP_LOAD_IQ(); + FP_LOAD_IQ(); - codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1; + codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1; - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg; + x86seg *target_seg; + int host_reg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - host_reg = FP_LOAD_REG(0); + host_reg = FP_LOAD_REG(0); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); + CHECK_SEG_WRITE(target_seg); - MEM_STORE_ADDR_EA_L(target_seg, host_reg); + MEM_STORE_ADDR_EA_L(target_seg, host_reg); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg1, host_reg2 = 0; + x86seg *target_seg; + int host_reg1, host_reg2 = 0; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_REG_D(0, &host_reg1, &host_reg2); + FP_LOAD_REG_D(0, &host_reg1, &host_reg2); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 7); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 7); - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block); + uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block); - FP_POP(); + FP_POP(); - return new_pc; + return new_pc; } -static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block); + uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block); - FP_POP(); + FP_POP(); - return new_pc; + return new_pc; } -#define ropFarith(name, size, load, op) \ -static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(FPU_ ## name); \ - \ - return op_pc + 1; \ -} +#define ropFarith(name, size, load, op) \ + static uint32_t ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + x86seg *target_seg; \ + \ + FP_ENTER(); \ + op_pc--; \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + load(target_seg); \ + \ + op(FPU_##name); \ + \ + return op_pc + 1; \ + } -ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); +ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S); -ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); +ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D); -ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); +ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW); -ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); +ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL); -#define ropFcompare(name, size, load, op) \ -static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - x86seg *target_seg; \ - \ - FP_ENTER(); \ - op_pc--; \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - \ - CHECK_SEG_READ(target_seg); \ - load(target_seg); \ - \ - op(); \ - \ - return op_pc + 1; \ -} \ -static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \ - \ - FP_POP(); \ - \ - return new_pc; \ -} +#define ropFcompare(name, size, load, op) \ + static uint32_t ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + x86seg *target_seg; \ + \ + FP_ENTER(); \ + op_pc--; \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + \ + CHECK_SEG_READ(target_seg); \ + load(target_seg); \ + \ + op(); \ + \ + return op_pc + 1; \ + } \ + static uint32_t ropF##name##P##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + uint32_t new_pc = ropF##name##size(opcode, fetchdat, op_32, op_pc, block); \ + \ + FP_POP(); \ + \ + return new_pc; \ + } ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S); ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D); @@ -326,320 +338,346 @@ static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint return op_pc + 1; }*/ - -static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_ADD, 0, opcode & 7); + FP_ENTER(); + FP_OP_REG(FPU_ADD, 0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_COMPARE_REG(0, opcode & 7); + FP_ENTER(); + FP_COMPARE_REG(0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIV, 0, opcode & 7); + FP_ENTER(); + FP_OP_REG(FPU_DIV, 0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIVR, 0, opcode & 7); + FP_ENTER(); + FP_OP_REG(FPU_DIVR, 0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_MUL, 0, opcode & 7); + FP_ENTER(); + FP_OP_REG(FPU_MUL, 0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUB, 0, opcode & 7); + FP_ENTER(); + FP_OP_REG(FPU_SUB, 0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUBR, 0, opcode & 7); + FP_ENTER(); + FP_OP_REG(FPU_SUBR, 0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_ADD, opcode & 7, 0); + FP_ENTER(); + FP_OP_REG(FPU_ADD, opcode & 7, 0); - return op_pc; + return op_pc; } -static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIV, opcode & 7, 0); + FP_ENTER(); + FP_OP_REG(FPU_DIV, opcode & 7, 0); - return op_pc; + return op_pc; } -static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIVR, opcode & 7, 0); + FP_ENTER(); + FP_OP_REG(FPU_DIVR, opcode & 7, 0); - return op_pc; + return op_pc; } -static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_MUL, opcode & 7, 0); + FP_ENTER(); + FP_OP_REG(FPU_MUL, opcode & 7, 0); - return op_pc; + return op_pc; } -static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUB, opcode & 7, 0); + FP_ENTER(); + FP_OP_REG(FPU_SUB, opcode & 7, 0); - return op_pc; + return op_pc; } -static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUBR, opcode & 7, 0); + FP_ENTER(); + FP_OP_REG(FPU_SUBR, opcode & 7, 0); - return op_pc; + return op_pc; } -static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_ADD, opcode & 7, 0); - FP_POP(); + FP_ENTER(); + FP_OP_REG(FPU_ADD, opcode & 7, 0); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_COMPARE_REG(0, opcode & 7); - FP_POP(); + FP_ENTER(); + FP_COMPARE_REG(0, opcode & 7); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIV, opcode & 7, 0); - FP_POP(); + FP_ENTER(); + FP_OP_REG(FPU_DIV, opcode & 7, 0); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_DIVR, opcode & 7, 0); - FP_POP(); + FP_ENTER(); + FP_OP_REG(FPU_DIVR, opcode & 7, 0); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_MUL, opcode & 7, 0); - FP_POP(); + FP_ENTER(); + FP_OP_REG(FPU_MUL, opcode & 7, 0); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUB, opcode & 7, 0); - FP_POP(); + FP_ENTER(); + FP_OP_REG(FPU_SUB, opcode & 7, 0); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_OP_REG(FPU_SUBR, opcode & 7, 0); - FP_POP(); + FP_ENTER(); + FP_OP_REG(FPU_SUBR, opcode & 7, 0); + FP_POP(); - return op_pc; + return op_pc; } -static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_COMPARE_REG(0, 1); - FP_POP2(); + FP_ENTER(); + FP_COMPARE_REG(0, 1); + FP_POP2(); - return op_pc; + return op_pc; } -static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - FP_ENTER(); - host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs); - STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); + FP_ENTER(); + host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxs); + STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); - return op_pc; + return op_pc; } - -static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg; + x86seg *target_seg; + int host_reg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - host_reg = FP_LOAD_REG_INT_W(0); + host_reg = FP_LOAD_REG_INT_W(0); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); + CHECK_SEG_WRITE(target_seg); - MEM_STORE_ADDR_EA_W(target_seg, host_reg); + MEM_STORE_ADDR_EA_W(target_seg, host_reg); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg; + x86seg *target_seg; + int host_reg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - host_reg = FP_LOAD_REG_INT(0); + host_reg = FP_LOAD_REG_INT(0); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); + CHECK_SEG_WRITE(target_seg); - MEM_STORE_ADDR_EA_L(target_seg, host_reg); + MEM_STORE_ADDR_EA_L(target_seg, host_reg); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block); + uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block); - FP_POP(); + FP_POP(); - return new_pc; + return new_pc; } -static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block); + uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block); - FP_POP(); + FP_POP(); - return new_pc; + return new_pc; } -static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; - int host_reg1, host_reg2; + x86seg *target_seg; + int host_reg1, host_reg2; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2); + FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); + CHECK_SEG_WRITE(target_seg); - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - FP_POP(); + FP_POP(); - return op_pc + 1; + return op_pc + 1; } - -static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_READ(target_seg); + CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); - STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0); - UPDATE_NPXC(0); + MEM_LOAD_ADDR_EA_W(target_seg); + STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.npxc, 0); + UPDATE_NPXC(0); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; - x86seg *target_seg; + int host_reg; + x86seg *target_seg; - FP_ENTER(); - op_pc--; - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + FP_ENTER(); + op_pc--; + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_WRITE(target_seg); + CHECK_SEG_WRITE(target_seg); - host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc); - MEM_STORE_ADDR_EA_W(target_seg, host_reg); + host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxc); + MEM_STORE_ADDR_EA_W(target_seg, host_reg); - return op_pc + 1; + return op_pc + 1; } - -static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_FCHS(); + FP_ENTER(); + FP_FCHS(); - return op_pc; + return op_pc; } -#define opFLDimm(name, v) \ - static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - static double fp_imm = v; \ - \ - FP_ENTER(); \ - FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \ - \ - return op_pc; \ - } +#define opFLDimm(name, v) \ + static uint32_t ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + static double fp_imm = v; \ + \ + FP_ENTER(); \ + FP_LOAD_IMM_Q(*(uint64_t *) &fp_imm); \ + \ + return op_pc; \ + } opFLDimm(1, 1.0) -opFLDimm(L2T, 3.3219280948873623) -opFLDimm(L2E, 1.4426950408889634); + opFLDimm(L2T, 3.3219280948873623) + opFLDimm(L2E, 1.4426950408889634); opFLDimm(PI, 3.141592653589793); opFLDimm(EG2, 0.3010299956639812); opFLDimm(Z, 0.0) -static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) + static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - FP_ENTER(); - FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull); + FP_ENTER(); + FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull); - return op_pc; + return op_pc; } diff --git a/src/codegen/codegen_ops_logic.h b/src/codegen/codegen_ops_logic.h index 117b19d97..55b4e117d 100644 --- a/src/codegen/codegen_ops_logic.h +++ b/src/codegen/codegen_ops_logic.h @@ -1,564 +1,540 @@ -#define ROP_LOGIC(name, op, writeback) \ - static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \ - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_B_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_W(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \ - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_W_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - dst_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_L(target_seg); \ - dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \ - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) \ - { \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_L_RELEASE(dst_reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ - } \ - } \ - else \ - RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_B(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_B(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \ - op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_B_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_W(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \ - op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_W_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } \ - static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int src_reg, dst_reg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - src_reg = LOAD_REG_L(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - src_reg = 0; \ - } \ - \ - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \ - if (writeback) STORE_REG_L_RELEASE(dst_reg); \ - else RELEASE_REG(dst_reg); \ - RELEASE_REG(src_reg); \ - \ - return op_pc + 1; \ - } +#define ROP_LOGIC(name, op, writeback) \ + static uint32_t rop##name##_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); \ + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_B_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_W(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); \ + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_W_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + dst_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_L(target_seg); \ + dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); \ + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) { \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_L_RELEASE(dst_reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \ + } \ + } else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_B(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_B(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); \ + op##_HOST_REG_B(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_B_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_W(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); \ + op##_HOST_REG_W(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_W_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } \ + static uint32_t rop##name##_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int src_reg, dst_reg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) { \ + src_reg = LOAD_REG_L(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + src_reg = 0; \ + } \ + \ + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); \ + op##_HOST_REG_L(dst_reg, src_reg); \ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); \ + if (writeback) \ + STORE_REG_L_RELEASE(dst_reg); \ + else \ + RELEASE_REG(dst_reg); \ + RELEASE_REG(src_reg); \ + \ + return op_pc + 1; \ + } ROP_LOGIC(AND, AND, 1) ROP_LOGIC(OR, OR, 1) ROP_LOGIC(XOR, XOR, 1) -static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_B(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_B(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + dst_reg = TEST_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} +static uint32_t +ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_W(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + dst_reg = TEST_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} +static uint32_t +ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) { + src_reg = LOAD_REG_L(fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + dst_reg = TEST_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} + +static uint32_t +ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + return op_pc + 1; +} +static uint32_t +ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + return op_pc + 2; +} +static uint32_t +ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + AND_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + OR_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + return op_pc + 1; +} +static uint32_t +ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + return op_pc + 2; +} +static uint32_t +ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + OR_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + return op_pc + 1; +} +static uint32_t +ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + return op_pc + 2; +} +static uint32_t +ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_B(REG_AL); + + XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_B_RELEASE(host_reg); + + return op_pc + 1; +} +static uint32_t +ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_W(REG_AX); + + XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_W_RELEASE(host_reg); + + return op_pc + 2; +} +static uint32_t +ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg = LOAD_REG_L(REG_EAX); + + fetchdat = fastreadl(cs + op_pc); + XOR_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + STORE_REG_L_RELEASE(host_reg); + + return op_pc + 4; +} + +static uint32_t +ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + x86seg *target_seg; + int host_reg; + uint8_t imm; + + switch (fetchdat & 0x38) { + case 0x00: /*TEST b,#8*/ + if ((fetchdat & 0xc0) == 0xc0) { + host_reg = LOAD_REG_B(fetchdat & 7); + imm = (fetchdat >> 8) & 0xff; + } else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + imm = fastreadb(cs + op_pc + 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); MEM_LOAD_ADDR_EA_B(target_seg); - src_reg = 0; - } + host_reg = 0; + } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN8); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + return op_pc + 2; - dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - dst_reg = TEST_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + case 0x10: /*NOT b*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + host_reg = LOAD_REG_B(fetchdat & 7); + XOR_HOST_REG_IMM(host_reg, 0xff); + STORE_REG_B_RELEASE(host_reg); + return op_pc + 1; - return op_pc + 1; + case 0x18: /*NEG b*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB8); + host_reg = LOAD_REG_B(fetchdat & 7); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op2, host_reg); + NEG_HOST_REG_B(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op1, 0); + STORE_REG_B_RELEASE(host_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + return op_pc + 1; + } + + return 0; } -static uint32_t ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + x86seg *target_seg; + int host_reg; + uint16_t imm; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_W(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + switch (fetchdat & 0x38) { + case 0x00: /*TEST w,#*/ + if ((fetchdat & 0xc0) == 0xc0) { + host_reg = LOAD_REG_W(fetchdat & 7); + imm = (fetchdat >> 8) & 0xffff; + } else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + imm = fastreadw(cs + op_pc + 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); MEM_LOAD_ADDR_EA_W(target_seg); - src_reg = 0; - } + host_reg = 0; + } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN16); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + return op_pc + 3; - dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - dst_reg = TEST_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + case 0x10: /*NOT w*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + host_reg = LOAD_REG_W(fetchdat & 7); + XOR_HOST_REG_IMM(host_reg, 0xffff); + STORE_REG_W_RELEASE(host_reg); + return op_pc + 1; - return op_pc + 1; + case 0x18: /*NEG w*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB16); + host_reg = LOAD_REG_W(fetchdat & 7); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op2, host_reg); + NEG_HOST_REG_W(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op1, 0); + STORE_REG_W_RELEASE(host_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + return op_pc + 1; + } + + return 0; } -static uint32_t ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + x86seg *target_seg; + int host_reg; + uint32_t imm; - if ((fetchdat & 0xc0) == 0xc0) - { - src_reg = LOAD_REG_L(fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + switch (fetchdat & 0x38) { + case 0x00: /*TEST l,#*/ + if ((fetchdat & 0xc0) == 0xc0) { + host_reg = LOAD_REG_L(fetchdat & 7); + imm = fastreadl(cs + op_pc + 1); + } else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + imm = fastreadl(cs + op_pc + 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); MEM_LOAD_ADDR_EA_L(target_seg); - src_reg = 0; - } + host_reg = 0; + } + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_ZN32); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + RELEASE_REG(host_reg); + return op_pc + 5; - dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - dst_reg = TEST_HOST_REG_L(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); - RELEASE_REG(dst_reg); - RELEASE_REG(src_reg); + case 0x10: /*NOT l*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + host_reg = LOAD_REG_L(fetchdat & 7); + XOR_HOST_REG_IMM(host_reg, 0xffffffff); + STORE_REG_L_RELEASE(host_reg); + return op_pc + 1; - return op_pc + 1; -} - -static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - AND_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - OR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - OR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 1; -} -static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 2; -} -static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - - return op_pc + 4; -} - -static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_B(REG_AL); - - XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_B_RELEASE(host_reg); - - return op_pc + 1; -} -static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W(REG_AX); - - XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_W_RELEASE(host_reg); - - return op_pc + 2; -} -static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_L(REG_EAX); - - fetchdat = fastreadl(cs + op_pc); - XOR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - STORE_REG_L_RELEASE(host_reg); - - return op_pc + 4; -} - -static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint8_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_B(fetchdat & 7); - imm = (fetchdat >> 8) & 0xff; - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadb(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 2; - - case 0x10: /*NOT b*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_B(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xff); - STORE_REG_B_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG b*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8); - host_reg = LOAD_REG_B(fetchdat & 7); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_B(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_B_RELEASE(host_reg); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} -static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint16_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST w,#*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_W(fetchdat & 7); - imm = (fetchdat >> 8) & 0xffff; - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadw(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 3; - - case 0x10: /*NOT w*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_W(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xffff); - STORE_REG_W_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG w*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16); - host_reg = LOAD_REG_W(fetchdat & 7); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_W(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_W_RELEASE(host_reg); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; -} -static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - x86seg *target_seg; - int host_reg; - uint32_t imm; - - switch (fetchdat & 0x38) - { - case 0x00: /*TEST l,#*/ - if ((fetchdat & 0xc0) == 0xc0) - { - host_reg = LOAD_REG_L(fetchdat & 7); - imm = fastreadl(cs + op_pc + 1); - } - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - imm = fastreadl(cs + op_pc + 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); - host_reg = TEST_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - RELEASE_REG(host_reg); - return op_pc + 5; - - case 0x10: /*NOT l*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - host_reg = LOAD_REG_L(fetchdat & 7); - XOR_HOST_REG_IMM(host_reg, 0xffffffff); - STORE_REG_L_RELEASE(host_reg); - return op_pc + 1; - - case 0x18: /*NEG l*/ - if ((fetchdat & 0xc0) != 0xc0) - return 0; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32); - host_reg = LOAD_REG_L(fetchdat & 7); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, host_reg); - NEG_HOST_REG_L(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0); - STORE_REG_L_RELEASE(host_reg); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - return op_pc + 1; - } - - return 0; + case 0x18: /*NEG l*/ + if ((fetchdat & 0xc0) != 0xc0) + return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SUB32); + host_reg = LOAD_REG_L(fetchdat & 7); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op2, host_reg); + NEG_HOST_REG_L(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op1, 0); + STORE_REG_L_RELEASE(host_reg); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + return op_pc + 1; + } + + return 0; } diff --git a/src/codegen/codegen_ops_misc.h b/src/codegen/codegen_ops_misc.h index 9438da2d3..61854ab37 100644 --- a/src/codegen/codegen_ops_misc.h +++ b/src/codegen/codegen_ops_misc.h @@ -1,272 +1,263 @@ -static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - return op_pc; + return op_pc; } -static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - CLEAR_BITS((uintptr_t)&cpu_state.flags, D_FLAG); - return op_pc; + CLEAR_BITS((uintptr_t) &cpu_state.flags, D_FLAG); + return op_pc; } -static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - SET_BITS((uintptr_t)&cpu_state.flags, D_FLAG); - return op_pc; + SET_BITS((uintptr_t) &cpu_state.flags, D_FLAG); + return op_pc; } -static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; - CLEAR_BITS((uintptr_t)&cpu_state.flags, I_FLAG); + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; + CLEAR_BITS((uintptr_t) &cpu_state.flags, I_FLAG); #ifdef CHECK_INT - CLEAR_BITS((uintptr_t)&pic_pending, 0xffffffff); + CLEAR_BITS((uintptr_t) &pic_pending, 0xffffffff); #endif - return op_pc; + return op_pc; } -static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; - SET_BITS((uintptr_t)&cpu_state.flags, I_FLAG); - return op_pc; + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; + SET_BITS((uintptr_t) &cpu_state.flags, I_FLAG); + return op_pc; } -static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int host_reg; + x86seg *target_seg = NULL; + int host_reg; - if ((fetchdat & 0x30) != 0x00) - return 0; + if ((fetchdat & 0x30) != 0x00) + return 0; - CALL_FUNC((uintptr_t)flags_rebuild_c); + CALL_FUNC((uintptr_t) flags_rebuild_c); - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_B(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_B(fetchdat & 7); + else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - SAVE_EA(); - MEM_CHECK_WRITE(target_seg); - host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); - } + SAVE_EA(); + MEM_CHECK_WRITE(target_seg); + host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); + } - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_B(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - break; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8); - STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg); - break; - } + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_B(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + break; + case 0x08: /*DEC*/ + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_B(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC8); + STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg); + break; + } - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_B_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_B_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; - return op_pc + 1; + return op_pc + 1; } static uint32_t codegen_temp; -static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int host_reg; + x86seg *target_seg = NULL; + int host_reg; - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) - return 0; - - if ((fetchdat & 0x30) == 0x00) - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_W(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0x30) != 0x00) - { - MEM_LOAD_ADDR_EA_W(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_W(target_seg); - host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); - } - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_W_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_W_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - - case 0x10: /*CALL*/ - STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg); - RELEASE_REG(host_reg); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(op_pc + 1); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - - host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); - STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x20: /*JMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x30: /*PUSH*/ - if (!host_reg) - host_reg = LOAD_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - return op_pc + 1; - } + if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) return 0; + + if ((fetchdat & 0x30) == 0x00) + CALL_FUNC((uintptr_t) flags_rebuild_c); + + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_W(fetchdat & 7); + else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + if ((fetchdat & 0x30) != 0x00) { + MEM_LOAD_ADDR_EA_W(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_W(target_seg); + host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); + } + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM_W(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_W_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + case 0x08: /*DEC*/ + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM_W(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC16); + STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_W_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + + case 0x10: /*CALL*/ + STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, host_reg); + RELEASE_REG(host_reg); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(op_pc + 1); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + + host_reg = LOAD_VAR_W((uintptr_t) &codegen_temp); + STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x20: /*JMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x30: /*PUSH*/ + if (!host_reg) + host_reg = LOAD_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + return op_pc + 1; + } + return 0; } -static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int host_reg; + x86seg *target_seg = NULL; + int host_reg; - if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) - return 0; - - if ((fetchdat & 0x30) == 0x00) - CALL_FUNC((uintptr_t)flags_rebuild_c); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_L(fetchdat & 7); - else - { - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0x30) != 0x00) - { - MEM_LOAD_ADDR_EA_L(target_seg); - host_reg = 0; - } - else - { - SAVE_EA(); - MEM_CHECK_WRITE_L(target_seg); - host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); - } - } - - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - ADD_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_L_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - case 0x08: /*DEC*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg); - if ((fetchdat & 0xc0) == 0xc0) - STORE_REG_L_RELEASE(host_reg); - else - { - LOAD_EA(); - MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); - } - codegen_flags_changed = 1; - return op_pc + 1; - - case 0x10: /*CALL*/ - STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg); - RELEASE_REG(host_reg); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(op_pc + 1); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - - host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x20: /*JMP*/ - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg); - return -1; - - case 0x30: /*PUSH*/ - if (!host_reg) - host_reg = LOAD_HOST_REG(host_reg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - return op_pc + 1; - } + if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08)) return 0; + + if ((fetchdat & 0x30) == 0x00) + CALL_FUNC((uintptr_t) flags_rebuild_c); + + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_L(fetchdat & 7); + else { + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + if ((fetchdat & 0x30) != 0x00) { + MEM_LOAD_ADDR_EA_L(target_seg); + host_reg = 0; + } else { + SAVE_EA(); + MEM_CHECK_WRITE_L(target_seg); + host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); + } + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + ADD_HOST_REG_IMM(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_L_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + case 0x08: /*DEC*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg); + SUB_HOST_REG_IMM(host_reg, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC32); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg); + if ((fetchdat & 0xc0) == 0xc0) + STORE_REG_L_RELEASE(host_reg); + else { + LOAD_EA(); + MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg); + } + codegen_flags_changed = 1; + return op_pc + 1; + + case 0x10: /*CALL*/ + STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, host_reg); + RELEASE_REG(host_reg); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(op_pc + 1); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + + host_reg = LOAD_VAR_L((uintptr_t) &codegen_temp); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x20: /*JMP*/ + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg); + return -1; + + case 0x30: /*PUSH*/ + if (!host_reg) + host_reg = LOAD_HOST_REG(host_reg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + return op_pc + 1; + } + return 0; } diff --git a/src/codegen/codegen_ops_mmx.h b/src/codegen/codegen_ops_mmx.h index 4cdb080fb..edb5b0586 100644 --- a/src/codegen/codegen_ops_mmx.h +++ b/src/codegen/codegen_ops_mmx.h @@ -1,277 +1,267 @@ -static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg1, host_reg2 = 0; + int host_reg1, host_reg2 = 0; - MMX_ENTER(); + MMX_ENTER(); - LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2); + LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2); - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 7); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 7); - MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); - } + MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2); + } - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - MMX_ENTER(); + MMX_ENTER(); - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg1, host_reg2; + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg1, host_reg2; - LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2); - STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2); + STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); + CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_Q(target_seg); - STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2); - } + MEM_LOAD_ADDR_EA_Q(target_seg); + STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2); + } - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - MMX_ENTER(); + MMX_ENTER(); - host_reg = LOAD_MMX_D((fetchdat >> 3) & 7); + host_reg = LOAD_MMX_D((fetchdat >> 3) & 7); - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 3); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 3); - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - } + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + } - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - MMX_ENTER(); + MMX_ENTER(); - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_L(fetchdat & 7); - STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_L(fetchdat & 7); + STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); + CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_L(target_seg); - STORE_MMX_LQ((fetchdat >> 3) & 7, 0); - } + MEM_LOAD_ADDR_EA_L(target_seg); + STORE_MMX_LQ((fetchdat >> 3) & 7, 0); + } - return op_pc + 1; + return op_pc + 1; } #define MMX_OP(name, func) \ -static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ + static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ int src_reg1, src_reg2; \ int xmm_src, xmm_dst; \ \ MMX_ENTER(); \ \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ - } \ - else \ - { \ - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \ + } else { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ \ - CHECK_SEG_READ(target_seg); \ + CHECK_SEG_READ(target_seg); \ \ - MEM_LOAD_ADDR_EA_Q(target_seg); \ - src_reg1 = LOAD_Q_REG_1; \ - src_reg2 = LOAD_Q_REG_2; \ - xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ + MEM_LOAD_ADDR_EA_Q(target_seg); \ + src_reg1 = LOAD_Q_REG_1; \ + src_reg2 = LOAD_Q_REG_2; \ + xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \ } \ xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \ - func(xmm_dst, xmm_src); \ + func(xmm_dst, xmm_src); \ STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \ \ return op_pc + 1; \ -} + } -MMX_OP(ropPAND, MMX_AND) +MMX_OP(ropPAND, MMX_AND) MMX_OP(ropPANDN, MMX_ANDN) -MMX_OP(ropPOR, MMX_OR) -MMX_OP(ropPXOR, MMX_XOR) +MMX_OP(ropPOR, MMX_OR) +MMX_OP(ropPXOR, MMX_XOR) -MMX_OP(ropPADDB, MMX_ADDB) -MMX_OP(ropPADDW, MMX_ADDW) -MMX_OP(ropPADDD, MMX_ADDD) -MMX_OP(ropPADDSB, MMX_ADDSB) -MMX_OP(ropPADDSW, MMX_ADDSW) -MMX_OP(ropPADDUSB, MMX_ADDUSB) -MMX_OP(ropPADDUSW, MMX_ADDUSW) +MMX_OP(ropPADDB, MMX_ADDB) +MMX_OP(ropPADDW, MMX_ADDW) +MMX_OP(ropPADDD, MMX_ADDD) +MMX_OP(ropPADDSB, MMX_ADDSB) +MMX_OP(ropPADDSW, MMX_ADDSW) +MMX_OP(ropPADDUSB, MMX_ADDUSB) +MMX_OP(ropPADDUSW, MMX_ADDUSW) -MMX_OP(ropPSUBB, MMX_SUBB) -MMX_OP(ropPSUBW, MMX_SUBW) -MMX_OP(ropPSUBD, MMX_SUBD) -MMX_OP(ropPSUBSB, MMX_SUBSB) -MMX_OP(ropPSUBSW, MMX_SUBSW) -MMX_OP(ropPSUBUSB, MMX_SUBUSB) -MMX_OP(ropPSUBUSW, MMX_SUBUSW) +MMX_OP(ropPSUBB, MMX_SUBB) +MMX_OP(ropPSUBW, MMX_SUBW) +MMX_OP(ropPSUBD, MMX_SUBD) +MMX_OP(ropPSUBSB, MMX_SUBSB) +MMX_OP(ropPSUBSW, MMX_SUBSW) +MMX_OP(ropPSUBUSB, MMX_SUBUSB) +MMX_OP(ropPSUBUSW, MMX_SUBUSW) MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW); MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD); MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ); -MMX_OP(ropPACKSSWB, MMX_PACKSSWB); -MMX_OP(ropPCMPGTB, MMX_PCMPGTB); -MMX_OP(ropPCMPGTW, MMX_PCMPGTW); -MMX_OP(ropPCMPGTD, MMX_PCMPGTD); -MMX_OP(ropPACKUSWB, MMX_PACKUSWB); +MMX_OP(ropPACKSSWB, MMX_PACKSSWB); +MMX_OP(ropPCMPGTB, MMX_PCMPGTB); +MMX_OP(ropPCMPGTW, MMX_PCMPGTW); +MMX_OP(ropPCMPGTD, MMX_PCMPGTD); +MMX_OP(ropPACKUSWB, MMX_PACKUSWB); MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW); MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD); MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ); -MMX_OP(ropPACKSSDW, MMX_PACKSSDW); +MMX_OP(ropPACKSSDW, MMX_PACKSSDW); -MMX_OP(ropPCMPEQB, MMX_PCMPEQB); -MMX_OP(ropPCMPEQW, MMX_PCMPEQW); -MMX_OP(ropPCMPEQD, MMX_PCMPEQD); +MMX_OP(ropPCMPEQB, MMX_PCMPEQB); +MMX_OP(ropPCMPEQW, MMX_PCMPEQW); +MMX_OP(ropPCMPEQD, MMX_PCMPEQD); -MMX_OP(ropPSRLW, MMX_PSRLW) -MMX_OP(ropPSRLD, MMX_PSRLD) -MMX_OP(ropPSRLQ, MMX_PSRLQ) -MMX_OP(ropPSRAW, MMX_PSRAW) -MMX_OP(ropPSRAD, MMX_PSRAD) -MMX_OP(ropPSLLW, MMX_PSLLW) -MMX_OP(ropPSLLD, MMX_PSLLD) -MMX_OP(ropPSLLQ, MMX_PSLLQ) +MMX_OP(ropPSRLW, MMX_PSRLW) +MMX_OP(ropPSRLD, MMX_PSRLD) +MMX_OP(ropPSRLQ, MMX_PSRLQ) +MMX_OP(ropPSRAW, MMX_PSRAW) +MMX_OP(ropPSRAD, MMX_PSRAD) +MMX_OP(ropPSLLW, MMX_PSLLW) +MMX_OP(ropPSLLD, MMX_PSLLD) +MMX_OP(ropPSLLQ, MMX_PSLLQ) -MMX_OP(ropPMULLW, MMX_PMULLW); -MMX_OP(ropPMULHW, MMX_PMULHW); -MMX_OP(ropPMADDWD, MMX_PMADDWD); +MMX_OP(ropPMULLW, MMX_PMULLW); +MMX_OP(ropPMULHW, MMX_PMULHW); +MMX_OP(ropPMADDWD, MMX_PMADDWD); -static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLW*/ - MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAW*/ - MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLW*/ - MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} -static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLD*/ - MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAD*/ - MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLD*/ - MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} -static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int xmm_dst; - - if ((fetchdat & 0xc0) != 0xc0) - return 0; - if ((fetchdat & 0x08) || !(fetchdat & 0x30)) - return 0; - - MMX_ENTER(); - - xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); - switch (fetchdat & 0x38) - { - case 0x10: /*PSRLQ*/ - MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x20: /*PSRAQ*/ - MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - case 0x30: /*PSLLQ*/ - MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); - break; - } - STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); - - return op_pc + 2; -} - -static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - codegen_mmx_entered = 0; + int xmm_dst; + if ((fetchdat & 0xc0) != 0xc0) return 0; + if ((fetchdat & 0x08) || !(fetchdat & 0x30)) + return 0; + + MMX_ENTER(); + + xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); + switch (fetchdat & 0x38) { + case 0x10: /*PSRLW*/ + MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x20: /*PSRAW*/ + MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x30: /*PSLLW*/ + MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + } + STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); + + return op_pc + 2; +} +static uint32_t +ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int xmm_dst; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + if ((fetchdat & 0x08) || !(fetchdat & 0x30)) + return 0; + + MMX_ENTER(); + + xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); + switch (fetchdat & 0x38) { + case 0x10: /*PSRLD*/ + MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x20: /*PSRAD*/ + MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x30: /*PSLLD*/ + MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + } + STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); + + return op_pc + 2; +} +static uint32_t +ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int xmm_dst; + + if ((fetchdat & 0xc0) != 0xc0) + return 0; + if ((fetchdat & 0x08) || !(fetchdat & 0x30)) + return 0; + + MMX_ENTER(); + + xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7); + switch (fetchdat & 0x38) { + case 0x10: /*PSRLQ*/ + MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x20: /*PSRAQ*/ + MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + case 0x30: /*PSLLQ*/ + MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff); + break; + } + STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst); + + return op_pc + 2; +} + +static uint32_t +ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + codegen_mmx_entered = 0; + + return 0; } diff --git a/src/codegen/codegen_ops_mov.h b/src/codegen/codegen_ops_mov.h index df7a6a31b..f5e61eb60 100644 --- a/src/codegen/codegen_ops_mov.h +++ b/src/codegen/codegen_ops_mov.h @@ -1,653 +1,620 @@ -static uint32_t ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff); + STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff); + STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff); - return op_pc + 2; + return op_pc + 2; } -static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - fetchdat = fastreadl(cs + op_pc); + fetchdat = fastreadl(cs + op_pc); - STORE_IMM_REG_L(opcode & 7, fetchdat); + STORE_IMM_REG_L(opcode & 7, fetchdat); - return op_pc + 4; + return op_pc + 4; } - -static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); + int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 0); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 0); - MEM_STORE_ADDR_EA_B(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 1); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - host_reg = LOAD_REG_L((fetchdat >> 3) & 7); - - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 3); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - RELEASE_REG(host_reg); - - } - - return op_pc + 1; -} - -static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_L(fetchdat & 7); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_L(target_seg); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadb(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_B(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 2; -} -static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadw(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 3; -} -static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - uint32_t imm = fastreadl(cs + op_pc + 1); - - STORE_IMM_REG_L(fetchdat & 7, imm); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - uint32_t imm = fastreadl(cs + op_pc + 1); - int host_reg = LOAD_REG_IMM(imm); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - CHECK_SEG_WRITE(target_seg); - - MEM_STORE_ADDR_EA_L(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 5; -} - - -static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr); - STORE_REG_TARGET_B_RELEASE(0, REG_AL); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr); - STORE_REG_TARGET_W_RELEASE(0, REG_AX); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_READ(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr); - STORE_REG_TARGET_L_RELEASE(0, REG_EAX); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - uint32_t addr; - int host_reg; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - host_reg = LOAD_REG_B(REG_AL); - - MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg); + MEM_STORE_ADDR_EA_B(target_seg, host_reg); RELEASE_REG(host_reg); + } - return op_pc + ((op_32 & 0x200) ? 4 : 2); + return op_pc + 1; } -static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t addr; - int host_reg; + int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - host_reg = LOAD_REG_W(REG_AX); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 1); - MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg); + MEM_STORE_ADDR_EA_W(target_seg, host_reg); RELEASE_REG(host_reg); + } - return op_pc + ((op_32 & 0x200) ? 4 : 2); + return op_pc + 1; } -static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) + +static uint32_t +ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t addr; - int host_reg; + int host_reg; - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); + host_reg = LOAD_REG_L((fetchdat >> 3) & 7); - CHECK_SEG_WRITE(op_ea_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + if ((fetchdat & 0xc0) == 0xc0) { + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - host_reg = LOAD_REG_L(REG_EAX); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 3); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); RELEASE_REG(host_reg); + } - return op_pc + ((op_32 & 0x200) ? 4 : 2); + return op_pc + 1; } -static uint32_t ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int dest_reg = (fetchdat >> 3) & 7; + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - if ((fetchdat & 0xc0) == 0xc0) - return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + CHECK_SEG_READ(target_seg); - STORE_REG_TARGET_W_RELEASE(0, dest_reg); + MEM_LOAD_ADDR_EA_B(target_seg); + STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7); + } - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int dest_reg = (fetchdat >> 3) & 7; + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_W(fetchdat & 7); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - if ((fetchdat & 0xc0) == 0xc0) - return 0; + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + CHECK_SEG_READ(target_seg); - STORE_REG_TARGET_L_RELEASE(0, dest_reg); + MEM_LOAD_ADDR_EA_W(target_seg); + STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); + } - return op_pc + 1; + return op_pc + 1; +} +static uint32_t +ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_L(fetchdat & 7); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_L(target_seg); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; } -static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = ZERO_EXTEND_W_B(host_reg); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } + if ((fetchdat & 0xc0) == 0xc0) { + STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadb(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_B(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 2; +} +static uint32_t +ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadw(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 3; +} +static uint32_t +ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + uint32_t imm = fastreadl(cs + op_pc + 1); + + STORE_IMM_REG_L(fetchdat & 7, imm); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadl(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + RELEASE_REG(host_reg); + } + + return op_pc + 5; +} + +static uint32_t +ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr); + STORE_REG_TARGET_B_RELEASE(0, REG_AL); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr); + STORE_REG_TARGET_W_RELEASE(0, REG_AX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr); + STORE_REG_TARGET_L_RELEASE(0, REG_EAX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +static uint32_t +ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + host_reg = LOAD_REG_B(REG_AL); + + MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + host_reg = LOAD_REG_W(REG_AX); + + MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t +ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + host_reg = LOAD_REG_L(REG_EAX); + + MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +static uint32_t +ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + return 0; + + FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_REG_TARGET_W_RELEASE(0, dest_reg); + + return op_pc + 1; +} +static uint32_t +ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int dest_reg = (fetchdat >> 3) & 7; + + if ((fetchdat & 0xc0) == 0xc0) + return 0; + + FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_REG_TARGET_L_RELEASE(0, dest_reg); + + return op_pc + 1; +} + +static uint32_t +ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = ZERO_EXTEND_W_B(host_reg); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + ZERO_EXTEND_W_B(0); + STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = ZERO_EXTEND_L_B(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + ZERO_EXTEND_L_B(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_W(fetchdat & 7); + host_reg = ZERO_EXTEND_L_W(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + ZERO_EXTEND_L_W(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} + +static uint32_t +ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = SIGN_EXTEND_W_B(host_reg); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + SIGN_EXTEND_W_B(0); + STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_B(fetchdat & 7); + host_reg = SIGN_EXTEND_L_B(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + SIGN_EXTEND_L_B(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} +static uint32_t +ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int host_reg = LOAD_REG_W(fetchdat & 7); + host_reg = SIGN_EXTEND_L_W(host_reg); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + SIGN_EXTEND_L_W(0); + STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); + } + + return op_pc + 1; +} + +static uint32_t +ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int host_reg; + + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + host_reg = LOAD_VAR_WL((uintptr_t) &ES); + break; + case 0x08: /*CS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &CS); + break; + case 0x18: /*DS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &DS); + break; + case 0x10: /*SS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &SS); + break; + case 0x20: /*FS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &FS); + break; + case 0x28: /*GS*/ + host_reg = LOAD_VAR_WL((uintptr_t) &GS); + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) { + if (op_32 & 0x100) + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + } else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - CHECK_SEG_READ(target_seg); + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 1); - MEM_LOAD_ADDR_EA_B(target_seg); - ZERO_EXTEND_W_B(0); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); + } - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = ZERO_EXTEND_L_B(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + case 0x18: /*DS*/ + case 0x20: /*FS*/ + case 0x28: /*GS*/ + break; + case 0x10: /*SS*/ + default: + return 0; + } - CHECK_SEG_READ(target_seg); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); - MEM_LOAD_ADDR_EA_B(target_seg); - ZERO_EXTEND_L_B(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } + if ((fetchdat & 0xc0) == 0xc0) + host_reg = LOAD_REG_W(fetchdat & 7); + else { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - return op_pc + 1; -} -static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - host_reg = ZERO_EXTEND_L_W(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + CHECK_SEG_READ(target_seg); + MEM_LOAD_ADDR_EA_W(target_seg); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); + host_reg = 0; + } - CHECK_SEG_READ(target_seg); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + LOAD_SEG(host_reg, &cpu_state.seg_es); + break; + case 0x18: /*DS*/ + LOAD_SEG(host_reg, &cpu_state.seg_ds); + break; + case 0x20: /*FS*/ + LOAD_SEG(host_reg, &cpu_state.seg_fs); + break; + case 0x28: /*GS*/ + LOAD_SEG(host_reg, &cpu_state.seg_gs); + break; + } - MEM_LOAD_ADDR_EA_W(target_seg); - ZERO_EXTEND_L_W(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = SIGN_EXTEND_W_B(host_reg); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - SIGN_EXTEND_W_B(0); - STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_B(fetchdat & 7); - host_reg = SIGN_EXTEND_L_B(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_B(target_seg); - SIGN_EXTEND_L_B(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} -static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int host_reg = LOAD_REG_W(fetchdat & 7); - host_reg = SIGN_EXTEND_L_W(host_reg); - STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_READ(target_seg); - - MEM_LOAD_ADDR_EA_W(target_seg); - SIGN_EXTEND_L_W(0); - STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7); - } - - return op_pc + 1; -} - -static uint32_t ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - host_reg = LOAD_VAR_WL((uintptr_t)&ES); - break; - case 0x08: /*CS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&CS); - break; - case 0x18: /*DS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&DS); - break; - case 0x10: /*SS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&SS); - break; - case 0x20: /*FS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&FS); - break; - case 0x28: /*GS*/ - host_reg = LOAD_VAR_WL((uintptr_t)&GS); - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - if (op_32 & 0x100) - STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); - else - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); - } - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - CHECK_SEG_WRITE(target_seg); - CHECK_SEG_LIMITS(target_seg, 1); - - MEM_STORE_ADDR_EA_W(target_seg, host_reg); - RELEASE_REG(host_reg); - } - - return op_pc + 1; -} -static uint32_t ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) -{ - int host_reg; - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - case 0x18: /*DS*/ - case 0x20: /*FS*/ - case 0x28: /*GS*/ - break; - case 0x10: /*SS*/ - default: - return 0; - } - - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - - if ((fetchdat & 0xc0) == 0xc0) - host_reg = LOAD_REG_W(fetchdat & 7); - else - { - x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - - CHECK_SEG_READ(target_seg); - MEM_LOAD_ADDR_EA_W(target_seg); - - host_reg = 0; - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - LOAD_SEG(host_reg, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - LOAD_SEG(host_reg, &cpu_state.seg_ds); - break; - case 0x20: /*FS*/ - LOAD_SEG(host_reg, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - LOAD_SEG(host_reg, &cpu_state.seg_gs); - break; - } - - return op_pc + 1; -} - -#define ropLseg(seg, rseg) \ -static uint32_t ropL ## seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - x86seg *target_seg; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - SAVE_EA(); \ - \ - if (op_32 & 0x100) \ - { \ - MEM_LOAD_ADDR_EA_L(target_seg); \ - STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, 0); \ - LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ - } \ - else \ - { \ - MEM_LOAD_ADDR_EA_W(target_seg); \ - STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, 0); \ - LOAD_EA(); \ - MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ - } \ - LOAD_SEG(0, &rseg); \ - if (op_32 & 0x100) \ - { \ - \ - int host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); \ - STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \ - } \ - else \ - { \ - int host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); \ - STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \ - } \ - \ - if (&rseg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \ - return op_pc + 1; \ -} +#define ropLseg(seg, rseg) \ + static uint32_t ropL##seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + x86seg *target_seg; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + SAVE_EA(); \ + \ + if (op_32 & 0x100) { \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, 0); \ + LOAD_EA(); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \ + } else { \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, 0); \ + LOAD_EA(); \ + MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \ + } \ + LOAD_SEG(0, &rseg); \ + if (op_32 & 0x100) { \ + \ + int host_reg = LOAD_VAR_L((uintptr_t) &codegen_temp); \ + STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \ + } else { \ + int host_reg = LOAD_VAR_W((uintptr_t) &codegen_temp); \ + STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \ + } \ + \ + if (&rseg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \ + return op_pc + 1; \ + } ropLseg(DS, cpu_state.seg_ds) ropLseg(ES, cpu_state.seg_es) diff --git a/src/codegen/codegen_ops_shift.h b/src/codegen/codegen_ops_shift.h index 57a828232..d750bfcad 100644 --- a/src/codegen/codegen_ops_shift.h +++ b/src/codegen/codegen_ops_shift.h @@ -1,125 +1,129 @@ -#define SHIFT(size, size2, res_store, immediate) \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - reg = LOAD_REG_ ## size(fetchdat & 7); \ - if (immediate) count = (fetchdat >> 8) & 0x1f; \ - } \ - else \ - { \ - target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - SAVE_EA(); \ - MEM_CHECK_WRITE_ ## size(target_seg); \ - reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \ - if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \ - } \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \ - \ - res_store((uintptr_t)&cpu_state.flags_op1, reg); \ - \ - switch (fetchdat & 0x38) \ - { \ - case 0x20: case 0x30: /*SHL*/ \ - SHL_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \ - break; \ - \ - case 0x28: /*SHR*/ \ - SHR_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \ - break; \ - \ - case 0x38: /*SAR*/ \ - SAR_ ## size ## _IMM(reg, count); \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \ - break; \ - } \ - \ - res_store((uintptr_t)&cpu_state.flags_res, reg); \ - if ((fetchdat & 0xc0) == 0xc0) \ - STORE_REG_ ## size ## _RELEASE(reg); \ - else \ - { \ - LOAD_EA(); \ - MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \ - } +#define SHIFT(size, size2, res_store, immediate) \ + if ((fetchdat & 0xc0) == 0xc0) { \ + reg = LOAD_REG_##size(fetchdat & 7); \ + if (immediate) \ + count = (fetchdat >> 8) & 0x1f; \ + } else { \ + target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + SAVE_EA(); \ + MEM_CHECK_WRITE_##size(target_seg); \ + reg = MEM_LOAD_ADDR_EA_##size##_NO_ABRT(target_seg); \ + if (immediate) \ + count = fastreadb(cs + op_pc + 1) & 0x1f; \ + } \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, count); \ + \ + res_store((uintptr_t) &cpu_state.flags_op1, reg); \ + \ + switch (fetchdat & 0x38) { \ + case 0x20: \ + case 0x30: /*SHL*/ \ + SHL_##size##_IMM(reg, count); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHL##size2); \ + break; \ + \ + case 0x28: /*SHR*/ \ + SHR_##size##_IMM(reg, count); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHR##size2); \ + break; \ + \ + case 0x38: /*SAR*/ \ + SAR_##size##_IMM(reg, count); \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SAR##size2); \ + break; \ + } \ + \ + res_store((uintptr_t) &cpu_state.flags_res, reg); \ + if ((fetchdat & 0xc0) == 0xc0) \ + STORE_REG_##size##_RELEASE(reg); \ + else { \ + LOAD_EA(); \ + MEM_STORE_ADDR_EA_##size##_NO_ABRT(target_seg, reg); \ + } -static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count; - int reg; + x86seg *target_seg = NULL; + int count; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1); + SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1); - return op_pc + 2; + return op_pc + 2; } -static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count; - int reg; + x86seg *target_seg = NULL; + int count; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1); + SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1); - return op_pc + 2; + return op_pc + 2; } -static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count; - int reg; + x86seg *target_seg = NULL; + int count; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(L, 32, STORE_HOST_REG_ADDR, 1); + SHIFT(L, 32, STORE_HOST_REG_ADDR, 1); - return op_pc + 2; + return op_pc + 2; } -static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count = 1; - int reg; + x86seg *target_seg = NULL; + int count = 1; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0); + SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count = 1; - int reg; + x86seg *target_seg = NULL; + int count = 1; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0); + SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - x86seg *target_seg = NULL; - int count = 1; - int reg; + x86seg *target_seg = NULL; + int count = 1; + int reg; - if ((fetchdat & 0x38) < 0x20) - return 0; + if ((fetchdat & 0x38) < 0x20) + return 0; - SHIFT(L, 32, STORE_HOST_REG_ADDR, 0); + SHIFT(L, 32, STORE_HOST_REG_ADDR, 0); - return op_pc + 1; + return op_pc + 1; } diff --git a/src/codegen/codegen_ops_stack.h b/src/codegen/codegen_ops_stack.h index d2fc53aad..265369771 100644 --- a/src/codegen/codegen_ops_stack.h +++ b/src/codegen/codegen_ops_stack.h @@ -1,238 +1,254 @@ -static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_W(opcode & 7); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_W(opcode & 7); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); - return op_pc; + return op_pc; } -static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_L(opcode & 7); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_L(opcode & 7); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); - return op_pc; + return op_pc; } -static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t imm = fetchdat & 0xffff; - int host_reg; + uint16_t imm = fetchdat & 0xffff; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); - return op_pc+2; + return op_pc + 2; } -static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t imm = fastreadl(cs + op_pc); - int host_reg; + uint32_t imm = fastreadl(cs + op_pc); + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); - return op_pc+4; + return op_pc + 4; } -static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t imm = fetchdat & 0xff; - int host_reg; + uint16_t imm = fetchdat & 0xff; + int host_reg; - if (imm & 0x80) - imm |= 0xff00; + if (imm & 0x80) + imm |= 0xff00; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); - return op_pc+1; + return op_pc + 1; } -static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t imm = fetchdat & 0xff; - int host_reg; + uint32_t imm = fetchdat & 0xff; + int host_reg; - if (imm & 0x80) - imm |= 0xffffff00; + if (imm & 0x80) + imm |= 0xffffff00; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(imm); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(imm); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); - return op_pc+1; + return op_pc + 1; } -static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - SP_MODIFY(2); - STORE_REG_TARGET_W_RELEASE(0, opcode & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + SP_MODIFY(2); + STORE_REG_TARGET_W_RELEASE(0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - SP_MODIFY(4); - STORE_REG_TARGET_L_RELEASE(0, opcode & 7); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + SP_MODIFY(4); + STORE_REG_TARGET_L_RELEASE(0, opcode & 7); - return op_pc; + return op_pc; } -static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(2); - return -1; + return -1; } -static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(4); - return -1; + return -1; } -static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; + uint16_t offset = fetchdat & 0xffff; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(2+offset); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(2 + offset); - return -1; + return -1; } -static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; + uint16_t offset = fetchdat & 0xffff; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0); - SP_MODIFY(4+offset); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0); + SP_MODIFY(4 + offset); - return -1; + return -1; } -static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint16_t offset = fetchdat & 0xffff; - int host_reg; + uint16_t offset = fetchdat & 0xffff; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-2); - host_reg = LOAD_REG_IMM(op_pc+2); - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-2); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-2); + host_reg = LOAD_REG_IMM(op_pc + 2); + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-2); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff); - return -1; + return -1; } -static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - uint32_t offset = fastreadl(cs + op_pc); - int host_reg; + uint32_t offset = fastreadl(cs + op_pc); + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_STACK_TO_EA(-4); - host_reg = LOAD_REG_IMM(op_pc+4); - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); - SP_MODIFY(-4); - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_STACK_TO_EA(-4); + host_reg = LOAD_REG_IMM(op_pc + 4); + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); + SP_MODIFY(-4); + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset); - return -1; + return -1; } -static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_EBP_TO_EA(0); - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); - host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/ - ADD_HOST_REG_IMM_W(host_reg, 2); - STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP); - STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_EBP_TO_EA(0); + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); + host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/ + ADD_HOST_REG_IMM_W(host_reg, 2); + STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP); + STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ - return op_pc; + return op_pc; } -static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int host_reg; + int host_reg; - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); - LOAD_EBP_TO_EA(0); - MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); - host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/ - ADD_HOST_REG_IMM(host_reg, 4); - STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP); - STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); + LOAD_EBP_TO_EA(0); + MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss); + host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/ + ADD_HOST_REG_IMM(host_reg, 4); + STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP); + STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ - return op_pc; + return op_pc; } -#define ROP_PUSH_SEG(seg) \ -static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-2); \ - host_reg = LOAD_VAR_W((uintptr_t)&seg); \ - MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \ - SP_MODIFY(-2); \ - \ - return op_pc; \ -} \ -static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - int host_reg; \ - \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(-4); \ - host_reg = LOAD_VAR_W((uintptr_t)&seg); \ - MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \ - SP_MODIFY(-4); \ - \ - return op_pc; \ -} +#define ROP_PUSH_SEG(seg) \ + static uint32_t ropPUSH_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-2); \ + host_reg = LOAD_VAR_W((uintptr_t) &seg); \ + MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \ + SP_MODIFY(-2); \ + \ + return op_pc; \ + } \ + static uint32_t ropPUSH_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int host_reg; \ + \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(-4); \ + host_reg = LOAD_VAR_W((uintptr_t) &seg); \ + MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \ + SP_MODIFY(-4); \ + \ + return op_pc; \ + } ROP_PUSH_SEG(CS) ROP_PUSH_SEG(DS) @@ -241,27 +257,27 @@ ROP_PUSH_SEG(FS) ROP_PUSH_SEG(GS) ROP_PUSH_SEG(SS) -#define ROP_POP_SEG(seg, rseg) \ -static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(2); \ - \ - return op_pc; \ -} \ -static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ -{ \ - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \ - LOAD_STACK_TO_EA(0); \ - MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ - LOAD_SEG(0, &rseg); \ - SP_MODIFY(4); \ - \ - return op_pc; \ -} +#define ROP_POP_SEG(seg, rseg) \ + static uint32_t ropPOP_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(2); \ + \ + return op_pc; \ + } \ + static uint32_t ropPOP_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \ + LOAD_STACK_TO_EA(0); \ + MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \ + LOAD_SEG(0, &rseg); \ + SP_MODIFY(4); \ + \ + return op_pc; \ + } ROP_POP_SEG(DS, cpu_state.seg_ds) ROP_POP_SEG(ES, cpu_state.seg_es) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 67c24c99c..00518d9ba 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4,4519 +4,4148 @@ #include #define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 +#define HOST_REG_XMM_END 7 -#define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000) +#define IS_32_ADDR(x) !(((uintptr_t) x) & 0xffffffff00000000) -static __inline int find_host_xmm_reg(void) +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; - } + 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; + 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) +static __inline void +call(codeblock_t *block, uintptr_t func) { - intptr_t diff = (intptr_t)(func - (uintptr_t)&block->data[block_pos + 5]); + 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; + 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); - } + 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) +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; + 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); + 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) +static __inline void +load_param_1_32(codeblock_t *block, uint32_t param) { #if _WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ + addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ #else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ + addbyte(0xbf); /*MOVL $fetchdat,%edi*/ #endif - addlong(param); + addlong(param); } -static __inline void load_param_1_reg_32(int reg) +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)); + 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)); + 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 +# if _WIN64 addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else +# else addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif +# endif addquad(param); } #endif -static __inline void load_param_2_32(codeblock_t *block, uint32_t param) +static __inline void +load_param_2_32(codeblock_t *block, uint32_t param) { #if _WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ + addbyte(0xba); /*MOVL $fetchdat,%edx*/ #else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ + addbyte(0xbe); /*MOVL $fetchdat,%esi*/ #endif - addlong(param); + addlong(param); } -static __inline void load_param_2_reg_32(int reg) +static __inline void +load_param_2_reg_32(int reg) { #if _WIN64 - if (reg & 8) - addbyte(0x44); - addbyte(0x89); /*MOV EDX, EAX*/ + 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)); -#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); + } else { #if _WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ + addbyte(0x41); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); #else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ + addbyte(0x90); + addbyte(0x89); /*MOV EDX, reg*/ + addbyte(0xc0 | REG_EDX | (reg << 3)); #endif - addquad(param); + } } -static __inline void load_param_2_reg_64(int reg) +static __inline void +load_param_3_reg_64(int reg) { - if (reg & 8) - { + if (reg & 8) { #if _WIN64 - addbyte(0x4c); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); + addbyte(0x4d); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); #else - addbyte(0x4c); /*MOVL ESI,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); + addbyte(0x4c); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); #endif - } - else - { + } else { #if _WIN64 - addbyte(0x48); /*MOVL EDX,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); + addbyte(0x49); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); #else - addbyte(0x48); /*MOVL ESI,reg*/ - addbyte(0x89); - addbyte(0xc0 | REG_ESI | ((reg & 7) << 3)); + 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)); } -} - -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 + 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); } - 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(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(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(0xc0 | ((host_reg & 3) << 3)); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x41); /*MOV dest_reg, AL*/ addbyte(0x88); - addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].b)); + 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_W_RELEASE(int host_reg) +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)); -} -static __inline void STORE_REG_L_RELEASE(int host_reg) -{ - addbyte(0x44); /*MOVL [reg],host_reg*/ - addbyte(0x89); + } else { + addbyte(0x44); /*MOVB [reg],host_reg*/ + addbyte(0x88); addbyte(0x45 | ((host_reg & 7) << 3)); - addbyte(cpu_state_offset(regs[host_reg & 7].l)); + 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) +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*/ + if (reg & 4) { + int host_reg = LOAD_REG_W(reg & 3) & 7; + addbyte(0x66); /*AND host_reg, 0x00ff*/ addbyte(0x41); - addbyte(0xb8 | reg); - addword(val); - addbyte(0x66); /*MOVW reg, regs[reg].w*/ + 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].w)); + addbyte(cpu_state_offset(regs[reg & 7].b)); + } } -static __inline void STORE_IMM_REG_L(int reg, uint32_t val) +static __inline void +STORE_IMM_REG_W(int reg, uint16_t val) { - addbyte(0x41); /*MOVL reg, imm*/ - addbyte(0xb8 | reg); + 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); - addbyte(0x44); /*MOVL reg, regs[reg].l*/ - addbyte(0x89); - addbyte(0x45 | (reg << 3)); - addbyte(cpu_state_offset(regs[reg & 7].l)); + } 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 __inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) +static x86seg * +FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { - 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); + 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, 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; } - else if (addr < 0x100000000) - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x04); - addbyte(0x25); - addlong(addr); - addlong(val); + if (!(rm & 4)) { + if (rm & 1) + index_reg = LOAD_REG_W(REG_DI); + else + index_reg = LOAD_REG_W(REG_SI); } - else - { - addbyte(0x48); /*MOV ESI, &addr*/ - addbyte(0xb8 | REG_ESI); - addquad(addr); - addbyte(0xc7); /*MOVL [ESI], val*/ - addbyte(0x00 | REG_ESI); - addlong(val); - } -} + base_reg &= 7; + index_reg &= 7; - - - -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, 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; + 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)); + } } - if (!(rm & 4)) - { - if (rm & 1) - index_reg = LOAD_REG_W(REG_DI); - else - index_reg = LOAD_REG_W(REG_SI); + 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); } - 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, 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; - } + 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); } - 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; + (*op_pc) += 2; + break; + } + if (mod || !(rm & 4)) { + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); } - else - { - int base_reg; - if (!mod && rm == 5) - { + 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, 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); /*MOVL EAX, new_eaaddr*/ + addbyte(0xb8); /*MOV EAX, imm32*/ 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 - { + } 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; + } } - return op_ea_seg; + 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) +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); + 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) +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; + /*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); - } - 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); + 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); - 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); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); - addbyte(0x34); - addbyte(0x08); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xf7); - addbyte(0xc1); /*SHR ESI, 12*/ + } 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(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:*/ + addbyte(0xff); + } + addbyte(0x0f); /*JE GPF_BLOCK_OFFSET*/ + addbyte(0x84); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + + seg->checked = 1; } -static __inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +static __inline void +CHECK_SEG_WRITE(x86seg *seg) { - addbyte(0x83); /*ADD EAX, offset*/ + /*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(offset); - MEM_LOAD_ADDR_EA_W(seg); + 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_L(x86seg *seg) + +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); - } - 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); - } - 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]*/ + 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); + } + 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(0x04); + 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); + } + 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); + } + 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); + } + 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); + } + 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)); - 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:*/ + } 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_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +static __inline void +MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) { - 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); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); + 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); + } + 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(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); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); + 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(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:*/ + 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) +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); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); + 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); + } + 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(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); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); + 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(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); + 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); + } + 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(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(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) -{ + addbyte(0xc1); /*SHR temp_reg, 8*/ + addbyte(0xe8 | temp_reg); + addbyte(8); + } else { 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); - } + 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; - return host_reg; + 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 OR_HOST_REG_B(int dst_reg, int src_reg) +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); - } - 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)); - } + 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); /*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 (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(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 (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); } - 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)); - } + 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 OR_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +AND_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)); - } + 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 OR_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +AND_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)); - } + 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 OR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +AND_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); - } + 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 void XOR_HOST_REG_B(int dst_reg, int src_reg) +static __inline int +TEST_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)); - } - } + 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 void XOR_HOST_REG_W(int dst_reg, int src_reg) +static __inline int +TEST_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)); - } + 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 void XOR_HOST_REG_L(int dst_reg, int src_reg) +static __inline int +TEST_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)); - } + 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 void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline int +TEST_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); - } + 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 ADD_HOST_REG_B(int dst_reg, int src_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); /*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)); - } + 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); /*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 (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 (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 if (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); } - else - fatal("!(dst_reg & src_reg & 8)\n"); + 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 ADD_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +OR_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"); + 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 ADD_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +OR_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"); + 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 SUB_HOST_REG_B(int dst_reg, int src_reg) +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); /*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)); - } + 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); /*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 (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(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 (src_reg & 8) { + if (dst_reg & 0x10) { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); } - 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)); - } + 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 SUB_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +XOR_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)); - } + 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 SUB_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +XOR_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)); - } + 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 int CMP_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +ADD_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; + 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)); } - - SUB_HOST_REG_B(dst_reg, src_reg); - - return dst_reg & ~0x10; + } 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 int CMP_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +ADD_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; + 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 int CMP_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +ADD_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; + 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 ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline void +SUB_HOST_REG_B(int dst_reg, int src_reg) { - 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); + 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 (host_reg & 8) - addbyte(0x41); - addbyte(0x80); /*ADDB host_reg, imm*/ - addbyte(0xC0 | (host_reg & 7)); - addbyte(imm); + } 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 ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +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(0x41); addbyte(0x81); addbyte(0xC0 | (host_reg & 7)); - addword(imm); -} -static __inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ + addword(imm << 8); + } else { if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*ADDL host_reg, imm*/ + addbyte(0x41); + addbyte(0x80); /*ADDB host_reg, imm*/ addbyte(0xC0 | (host_reg & 7)); - addlong(imm); + 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) +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(0x41); addbyte(0x81); addbyte(0xE8 | (host_reg & 7)); - addword(imm); -} -static __inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ + addword(imm << 8); + } else { if (host_reg & 8) - addbyte(0x41); - addbyte(0x81); /*SUBL host_reg, imm*/ + addbyte(0x41); + addbyte(0x80); /*SUBB host_reg, imm*/ addbyte(0xE8 | (host_reg & 7)); - addlong(imm); + 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) +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)); + 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) +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)); + 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) +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)); + 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) +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)); + 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) +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); + if (host_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ addbyte(0x89); - addbyte(0xc0 | REG_ECX | ((src_reg & 7) << 3)); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - return REG_ECX | (src_reg & 0x10); + host_reg = (host_reg & 0x10) | REG_EDX; + } + + SUB_HOST_REG_IMM_B(host_reg, imm); + + return host_reg; } - -static __inline int LOAD_HOST_REG(int host_reg) +static __inline int +CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) { - if (host_reg & 8) - addbyte(0x44); + if (host_reg & 8) { + addbyte(0x44); /*MOV EDX, dst_reg*/ addbyte(0x89); - addbyte(0xc0 | REG_EBX | ((host_reg & 7) << 3)); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); - return REG_EBX | (host_reg & 0x10); + 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 int ZERO_EXTEND_W_B(int reg) +static __inline void +LOAD_STACK_TO_EA(int off) { - 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 (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); } - - 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*/ + } else { + addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ 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; + 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); } - - 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) +static __inline void +LOAD_EBP_TO_EA(int off) { - 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 (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); } - - 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; + } 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 SHL_B_IMM(int reg, int count) +static __inline void +SP_MODIFY(int off) { - 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)); + 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 (reg & 8) - addbyte(0x41); - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | (reg & 7) | 0x20); - addbyte(count); + } 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 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) +static __inline void +TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { - 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)); - } + 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 NEG_HOST_REG_W(int reg) +static __inline void +TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { - 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)); + 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 FP_ENTER(void) +static __inline void +TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { - 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(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 +*/ - 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)); + } 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)); - codegen_fpu_entered = 1; + 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 FP_FXCH(int reg) +static __inline void +BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); + 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(0x48); /*MOV RDX, ST[RBX*8]*/ - addbyte(0x8b); - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); 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)); + } else { + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + } - 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 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(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)); + addbyte(0x89); /*MOV [TOP], EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); } - - -static __inline void FP_FLD(int reg) +static __inline void +FP_FST(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(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)); - 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); + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); 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)); + 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_FST(int reg) +static __inline void +FP_POP(void) { - 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)); + 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_POP(void) +static __inline void +FP_LOAD_S(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)); + 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_POP2(void) +static __inline void +FP_LOAD_D(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)); + 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_S(void) +static __inline void +FP_LOAD_IW(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)); + 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_D(void) +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(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)); + 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_IW(void) +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(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)); + 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_LOAD_IMM_Q(uint64_t v) +static __inline void +FP_FCHS(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(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); + 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 void FP_FCHS(void) +static __inline int +FP_LOAD_REG(int reg) { - 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(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; + return REG_EBX; } -static __inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +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)); + 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; + *host_reg1 = REG_EBX; } -static __inline int64_t x87_fround16_64(double b) +static __inline int64_t +x87_fround16_64(double b) { - int16_t a, c; + 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); - } + 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; + return 0; } -static __inline int64_t x87_fround32_64(double b) +static __inline int64_t +x87_fround32_64(double b) { - int32_t a, c; + 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); - } + 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; + return 0; } -static __inline int64_t x87_fround(double b) +static __inline int64_t +x87_fround(double b) { - int64_t a, c; + 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; - } + 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; + return 0; } -static __inline int FP_LOAD_REG_INT_W(int reg) +static __inline int +FP_LOAD_REG_INT_W(int reg) { - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); + 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)); + 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); + CALL_FUNC((uintptr_t) x87_fround16_64); - addbyte(0x93); /*XCHG EBX, EAX*/ + addbyte(0x93); /*XCHG EBX, EAX*/ - return REG_EBX; + return REG_EBX; } -static __inline int FP_LOAD_REG_INT(int reg) +static __inline int +FP_LOAD_REG_INT(int reg) { - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); + 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)); + 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); + CALL_FUNC((uintptr_t) x87_fround32_64); - addbyte(0x93); /*XCHG EBX, EAX*/ + addbyte(0x93); /*XCHG EBX, EAX*/ - return REG_EBX; + return REG_EBX; } -static __inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) +static __inline void +FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) { - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); + 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(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(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((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 @@ -4526,1793 +4155,1695 @@ static __inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) #define FPU_SUB 2 #define FPU_SUBR 3 -static __inline void FP_OP_REG(int op, int dst, int src) +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(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)); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static __inline void FP_OP_MEM(int op) +static __inline void +FP_OP_S(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(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(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)); - } + 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_OP_S(int op) +static __inline void +FP_COMPARE_REG(int dst, int src) { - 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(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(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); -} + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } -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); - 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]*/ + if (src) { + addbyte(0xf3); /*MOVQ XMM0, ST[RBX*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(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x66); /*COMISD XMM0, ST[RAX*8]*/ 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(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xf3); /*MOVQ XMM0, ST[RAX*8]*/ addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc8); - addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ + addbyte(0x7e); + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x66); /*COMISD XMM0, ST[RBX*8]*/ 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(); + 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 UPDATE_NPXC(int reg) +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) +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); - } + 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); - } + } 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) +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); - } + 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); - } + } 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) +static __inline void +MMX_ENTER(void) { - if (codegen_mmx_entered) - return; + 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)); + 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])); - 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; + codegen_mmx_entered = 1; } extern int mmx_ebx_ecx_loaded; -static __inline int LOAD_MMX_D(int guest_reg) +static __inline int +LOAD_MMX_D(int guest_reg) { - int host_reg = REG_EBX; + 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])); + 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; + return host_reg; } -static __inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +static __inline void +LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) { - int host_reg = REG_EBX; + 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)); + 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; + *host_reg1 = host_reg; } -static __inline int LOAD_MMX_Q_MMX(int guest_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; + 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)); + 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; + return dst_reg; } -static __inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +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; + 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)); + 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; + return dst_reg; } -static __inline void STORE_MMX_LQ(int guest_reg, int host_reg1) +static __inline void +STORE_MMX_LQ(int guest_reg, int host_reg1) { - addbyte(0xC7); /*MOVL [reg],0*/ + 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(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])); + 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) +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])); + 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) +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)); + 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); \ -} +#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(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(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(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(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(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(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(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(PMULLW, 0xd5); +MMX_x86_OP(PMULHW, 0xe5); MMX_x86_OP(PMADDWD, 0xf5); -static __inline void MMX_PACKSSWB(int dst_reg, int src_reg) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + addbyte(0x66); /*PSLLQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } - -static __inline void SAVE_EA(void) +static __inline void +SAVE_EA(void) { - addbyte(0x89); /*MOV [ESP+0x24], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); + addbyte(0x89); /*MOV [ESP+0x24], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x24); } -static __inline void LOAD_EA(void) +static __inline void +LOAD_EA(void) { - addbyte(0x8b); /*MOV EAX, [ESP+0x24]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x24); + 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) +static __inline void +MEM_CHECK_WRITE(x86seg *seg) { - uint8_t *jump1, *jump2, *jump3 = NULL; + uint8_t *jump1, *jump2, *jump3 = NULL; - CHECK_SEG_WRITE(seg); + 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); - } - addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ - addbyte(0x8d); + 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(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(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(0xf8 | REG_ESI); + addbyte(0xfe); 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); - } - 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); + 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*/ - addbyte(4+2); - addbyte(0x66); /*MOV AX,[RDI+RSI]*/ + 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); + } + 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(0x04); + 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); + } + 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); + } + 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); + } + 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)); - 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); - } - 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); + } else { + addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); 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; + } + 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_B_NO_ABRT(x86seg *seg, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_W_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); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); + 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); + } + 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(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); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); + 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(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:*/ + 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) +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); - } - addbyte(0x67); /*LEA ESI, (EAX,EBX)*/ - addbyte(0x8d); + 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); + } + 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(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:*/ + 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) +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)); + 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/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index 28fa33bd7..80e081220 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -4,35 +4,35 @@ ESI, EDI - work registers EBP - points at emulated register array */ -#define HOST_REG_START 1 -#define HOST_REG_END 4 +#define HOST_REG_START 1 +#define HOST_REG_END 4 #define HOST_REG_XMM_START 0 -#define HOST_REG_XMM_END 7 -static __inline int find_host_reg(void) +#define HOST_REG_XMM_END 7 +static __inline int +find_host_reg(void) { - int c; - for (c = HOST_REG_START; c < HOST_REG_END; c++) - { - if (host_reg_mapping[c] == -1) - break; - } + int c; + for (c = HOST_REG_START; c < HOST_REG_END; c++) { + if (host_reg_mapping[c] == -1) + break; + } - if (c == NR_HOST_REGS) - fatal("Out of host regs!\n"); - return c; + if (c == NR_HOST_REGS) + fatal("Out of host regs!\n"); + return c; } -static __inline int find_host_xmm_reg(void) +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; - } + 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; + if (c == HOST_REG_XMM_END) + fatal("Out of host XMM regs!\n"); + return c; } #if 0 @@ -52,2637 +52,2572 @@ static __inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) addword(val); } #endif -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 - (uint32_t)&cpu_state - 128); - addlong(val); - } - else - { - addbyte(0xC7); /*MOVL [addr],val*/ - addbyte(0x05); - addlong(addr); - addlong(val); - } -} - -static __inline void STORE_IMM_REG_B(int reg, uint8_t val) -{ - addbyte(0xC6); /*MOVB [addr],val*/ - addbyte(0x45); - if (reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); - addbyte(val); -} -static __inline void STORE_IMM_REG_W(int reg, uint16_t val) -{ - addbyte(0x66); /*MOVW [addr],val*/ - addbyte(0xC7); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); - addword(val); -} -static __inline void STORE_IMM_REG_L(int reg, uint32_t val) +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((uint8_t)cpu_state_offset(regs[reg & 7].l)); + addbyte(addr - (uint32_t) &cpu_state - 128); addlong(val); + } else { + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x05); + addlong(addr); + addlong(val); + } } -static __inline int LOAD_REG_B(int reg) +static __inline void +STORE_IMM_REG_B(int reg, uint8_t val) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x0f); /*MOVZX B[reg],host_reg*/ - addbyte(0xb6); - addbyte(0x45 | (host_reg << 3)); - if (reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); - - return host_reg; + addbyte(0xC6); /*MOVB [addr],val*/ + addbyte(0x45); + if (reg & 4) + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.l)); + addbyte(val); } -static __inline int LOAD_REG_W(int reg) +static __inline void +STORE_IMM_REG_W(int reg, uint16_t val) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x0f); /*MOVZX W[reg],host_reg*/ - addbyte(0xb7); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); - - return host_reg; + addbyte(0x66); /*MOVW [addr],val*/ + addbyte(0xC7); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].w)); + addword(val); } -static __inline int LOAD_REG_L(int reg) +static __inline void +STORE_IMM_REG_L(int reg, uint32_t val) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = reg; - - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[reg & 7].l)); - - return host_reg; + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].l)); + addlong(val); } -static __inline int LOAD_VAR_W(uintptr_t addr) +static __inline int +LOAD_REG_B(int reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; - addbyte(0x66); /*MOVL host_reg,[reg]*/ - addbyte(0x8b); - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); + addbyte(0x0f); /*MOVZX B[reg],host_reg*/ + addbyte(0xb6); + addbyte(0x45 | (host_reg << 3)); + if (reg & 4) + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[reg & 3].b.l)); - return host_reg; + return host_reg; } -static __inline int LOAD_VAR_WL(uintptr_t addr) +static __inline int +LOAD_REG_W(int reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; - addbyte(0x0f); /*MOVZX host_reg, [addr]*/ - addbyte(0xb7); - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); + addbyte(0x0f); /*MOVZX W[reg],host_reg*/ + addbyte(0xb7); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].w)); - return host_reg; + return host_reg; } -static __inline int LOAD_VAR_L(uintptr_t addr) +static __inline int +LOAD_REG_L(int reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; - addbyte(0x8b); /*MOVL host_reg,[reg]*/ - addbyte(0x05 | (host_reg << 3)); - addlong((uint32_t)addr); + addbyte(0x8b); /*MOVL host_reg,[reg]*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[reg & 7].l)); - return host_reg; + return host_reg; } -static __inline int LOAD_REG_IMM(uint32_t imm) +static __inline int +LOAD_VAR_W(uintptr_t addr) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; - addbyte(0xc7); /*MOVL host_reg, imm*/ - addbyte(0xc0 | host_reg); - addlong(imm); + addbyte(0x66); /*MOVL host_reg,[reg]*/ + addbyte(0x8b); + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t) addr); - return host_reg; + return host_reg; +} +static __inline int +LOAD_VAR_WL(uintptr_t addr) +{ + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0x0f); /*MOVZX host_reg, [addr]*/ + addbyte(0xb7); + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t) addr); + + return host_reg; +} +static __inline int +LOAD_VAR_L(uintptr_t addr) +{ + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; + + addbyte(0x8b); /*MOVL host_reg,[reg]*/ + addbyte(0x05 | (host_reg << 3)); + addlong((uint32_t) addr); + + return host_reg; } -static __inline int LOAD_HOST_REG(int host_reg) +static __inline int +LOAD_REG_IMM(uint32_t imm) { - int new_host_reg = find_host_reg(); - host_reg_mapping[new_host_reg] = 0; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 0; - addbyte(0x89); /*MOV new_host_reg, host_reg*/ - addbyte(0xc0 | (host_reg << 3) | new_host_reg); + addbyte(0xc7); /*MOVL host_reg, imm*/ + addbyte(0xc0 | host_reg); + addlong(imm); - return new_host_reg; + return host_reg; } -static __inline void STORE_REG_B_RELEASE(int host_reg) +static __inline int +LOAD_HOST_REG(int host_reg) { - addbyte(0x88); /*MOVB [reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - if (host_reg_mapping[host_reg] & 4) - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.l)); - host_reg_mapping[host_reg] = -1; + int new_host_reg = find_host_reg(); + host_reg_mapping[new_host_reg] = 0; + + addbyte(0x89); /*MOV new_host_reg, host_reg*/ + addbyte(0xc0 | (host_reg << 3) | new_host_reg); + + return new_host_reg; } -static __inline void STORE_REG_W_RELEASE(int host_reg) + +static __inline void +STORE_REG_B_RELEASE(int host_reg) { - addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x88); /*MOVB [reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + if (host_reg_mapping[host_reg] & 4) + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.l)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_W_RELEASE(int host_reg) +{ + addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg]].w)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_L_RELEASE(int host_reg) +{ + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[host_reg_mapping[host_reg]].l)); + host_reg_mapping[host_reg] = -1; +} + +static __inline void +STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) +{ + addbyte(0x88); /*MOVB [guest_reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + if (guest_reg & 4) + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 3].b.h)); + else + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 3].b.l)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) +{ + addbyte(0x66); /*MOVW [guest_reg],host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 7].w)); + host_reg_mapping[host_reg] = -1; +} +static __inline void +STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) +{ + addbyte(0x89); /*MOVL [guest_reg],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(regs[guest_reg & 7].l)); + host_reg_mapping[host_reg] = -1; +} + +static __inline void +RELEASE_REG(int host_reg) +{ + host_reg_mapping[host_reg] = -1; +} + +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*/ addbyte(0x89); addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].w)); - host_reg_mapping[host_reg] = -1; + addbyte((uint32_t) addr - (uint32_t) &cpu_state - 128); + } else { + addbyte(0x66); /*MOVL [reg],host_reg*/ + addbyte(0x89); + addbyte(0x05 | (host_reg << 3)); + addlong(addr); + } } -static __inline void STORE_REG_L_RELEASE(int host_reg) +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) { + addbyte(0x89); /*MOVL [addr],host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t) addr - (uint32_t) &cpu_state - 128); + } else { addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].l)); - host_reg_mapping[host_reg] = -1; -} - -static __inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x88); /*MOVB [guest_reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - if (guest_reg & 4) - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.h)); - else - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.l)); - host_reg_mapping[host_reg] = -1; -} -static __inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x66); /*MOVW [guest_reg],host_reg*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].w)); - host_reg_mapping[host_reg] = -1; -} -static __inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) -{ - addbyte(0x89); /*MOVL [guest_reg],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].l)); - host_reg_mapping[host_reg] = -1; -} - -static __inline void RELEASE_REG(int host_reg) -{ - host_reg_mapping[host_reg] = -1; -} - -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*/ - addbyte(0x89); - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128); - } - else - { - addbyte(0x66); /*MOVL [reg],host_reg*/ - addbyte(0x89); - addbyte(0x05 | (host_reg << 3)); - addlong(addr); - } -} -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) - { - addbyte(0x89); /*MOVL [addr],host_reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint32_t)addr - (uint32_t)&cpu_state - 128); - } - else - { - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x05 | (host_reg << 3)); - addlong(addr); - } + addbyte(0x05 | (host_reg << 3)); + addlong(addr); + } } #define STORE_HOST_REG_ADDR_BL STORE_HOST_REG_ADDR #define STORE_HOST_REG_ADDR_WL STORE_HOST_REG_ADDR -static __inline void ADD_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_B(int dst_reg, int src_reg) { - addbyte(0x00); /*ADDB dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x00); /*ADDB dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void ADD_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_W(int dst_reg, int src_reg) { - addbyte(0x66); /*ADDW dst_reg, src_reg*/ - addbyte(0x01); - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void ADD_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +ADD_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x01); /*ADDL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x01); /*ADDL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline void +ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - addbyte(0x80); /*ADDB host_reg, imm*/ + addbyte(0x80); /*ADDB host_reg, imm*/ + addbyte(0xC0 | host_reg); + addbyte(imm); +} +static __inline void +ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + if (imm < 0x80 || imm >= 0xff80) { + addbyte(0x66); /*ADDW host_reg, imm*/ + addbyte(0x83); addbyte(0xC0 | host_reg); - addbyte(imm); + addbyte(imm & 0xff); + } else { + addbyte(0x66); /*ADDW host_reg, imm*/ + addbyte(0x81); + addbyte(0xC0 | host_reg); + addword(imm); + } } -static __inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static __inline void +ADD_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xff80) - { - addbyte(0x66); /*ADDW host_reg, imm*/ - addbyte(0x83); - addbyte(0xC0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x66); /*ADDW host_reg, imm*/ - addbyte(0x81); - addbyte(0xC0 | host_reg); - addword(imm); - } -} -static __inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ADDL host_reg, imm*/ - addbyte(0xC0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ADDL host_reg, imm*/ - addbyte(0xC0 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*ADDL host_reg, imm*/ + addbyte(0xC0 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*ADDL host_reg, imm*/ + addbyte(0xC0 | host_reg); + addlong(imm); + } } #define AND_HOST_REG_B AND_HOST_REG_L #define AND_HOST_REG_W AND_HOST_REG_L -static __inline void AND_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +AND_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x21); /*ANDL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x21); /*ANDL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +AND_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ANDL host_reg, imm*/ - addbyte(0xE0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ANDL host_reg, imm*/ - addbyte(0xE0 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*ANDL host_reg, imm*/ + addbyte(0xE0 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*ANDL host_reg, imm*/ + addbyte(0xE0 | host_reg); + addlong(imm); + } } -static __inline int TEST_HOST_REG_B(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_B(int dst_reg, int src_reg) { - AND_HOST_REG_B(dst_reg, src_reg); + AND_HOST_REG_B(dst_reg, src_reg); - return dst_reg; + return dst_reg; } -static __inline int TEST_HOST_REG_W(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_W(int dst_reg, int src_reg) { - AND_HOST_REG_W(dst_reg, src_reg); + AND_HOST_REG_W(dst_reg, src_reg); - return dst_reg; + return dst_reg; } -static __inline int TEST_HOST_REG_L(int dst_reg, int src_reg) +static __inline int +TEST_HOST_REG_L(int dst_reg, int src_reg) { - AND_HOST_REG_L(dst_reg, src_reg); + AND_HOST_REG_L(dst_reg, src_reg); - return dst_reg; + return dst_reg; } -static __inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline int +TEST_HOST_REG_IMM(int host_reg, uint32_t imm) { - AND_HOST_REG_IMM(host_reg, imm); + AND_HOST_REG_IMM(host_reg, imm); - return host_reg; + return host_reg; } #define OR_HOST_REG_B OR_HOST_REG_L #define OR_HOST_REG_W OR_HOST_REG_L -static __inline void OR_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +OR_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x09); /*ORL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x09); /*ORL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +OR_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*ORL host_reg, imm*/ - addbyte(0xC8 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*ORL host_reg, imm*/ - addbyte(0xC8 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*ORL host_reg, imm*/ + addbyte(0xC8 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*ORL host_reg, imm*/ + addbyte(0xC8 | host_reg); + addlong(imm); + } } -static __inline void NEG_HOST_REG_B(int reg) +static __inline void +NEG_HOST_REG_B(int reg) { - addbyte(0xf6); - addbyte(0xd8 | reg); + addbyte(0xf6); + addbyte(0xd8 | reg); } -static __inline void NEG_HOST_REG_W(int reg) +static __inline void +NEG_HOST_REG_W(int reg) { - addbyte(0x66); - addbyte(0xf7); - addbyte(0xd8 | reg); + addbyte(0x66); + addbyte(0xf7); + addbyte(0xd8 | reg); } -static __inline void NEG_HOST_REG_L(int reg) +static __inline void +NEG_HOST_REG_L(int reg) { - addbyte(0xf7); - addbyte(0xd8 | reg); + addbyte(0xf7); + addbyte(0xd8 | reg); } -static __inline void SUB_HOST_REG_B(int dst_reg, int src_reg) +static __inline void +SUB_HOST_REG_B(int dst_reg, int src_reg) { - addbyte(0x28); /*SUBB dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x28); /*SUBB dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void SUB_HOST_REG_W(int dst_reg, int src_reg) +static __inline void +SUB_HOST_REG_W(int dst_reg, int src_reg) { - addbyte(0x66); /*SUBW dst_reg, src_reg*/ - addbyte(0x29); - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void SUB_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +SUB_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x29); /*SUBL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x29); /*SUBL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline void +SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - addbyte(0x80); /*SUBB host_reg, imm*/ + addbyte(0x80); /*SUBB host_reg, imm*/ + addbyte(0xE8 | host_reg); + addbyte(imm); +} +static __inline void +SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + if (imm < 0x80 || imm >= 0xff80) { + addbyte(0x66); /*SUBW host_reg, imm*/ + addbyte(0x83); + addbyte(0xE8 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x66); /*SUBW host_reg, imm*/ + addbyte(0x81); + addbyte(0xE8 | host_reg); + addword(imm); + } +} +static __inline void +SUB_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*SUBL host_reg, imm*/ addbyte(0xE8 | host_reg); addbyte(imm); -} -static __inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) -{ - if (imm < 0x80 || imm >= 0xff80) - { - addbyte(0x66); /*SUBW host_reg, imm*/ - addbyte(0x83); - addbyte(0xE8 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x66); /*SUBW host_reg, imm*/ - addbyte(0x81); - addbyte(0xE8 | host_reg); - addword(imm); - } -} -static __inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) -{ - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*SUBL host_reg, imm*/ - addbyte(0xE8 | host_reg); - addbyte(imm); - } - else - { - addbyte(0x81); /*SUBL host_reg, imm*/ - addbyte(0xE8 | host_reg); - addlong(imm); - } + } else { + addbyte(0x81); /*SUBL host_reg, imm*/ + addbyte(0xE8 | host_reg); + addlong(imm); + } } -static __inline void INC_HOST_REG_W(int host_reg) +static __inline void +INC_HOST_REG_W(int host_reg) { - addbyte(0x66); /*INCW host_reg*/ - addbyte(0x40 | host_reg); + addbyte(0x66); /*INCW host_reg*/ + addbyte(0x40 | host_reg); } -static __inline void INC_HOST_REG(int host_reg) +static __inline void +INC_HOST_REG(int host_reg) { - addbyte(0x40 | host_reg); /*DECL host_reg*/ + addbyte(0x40 | host_reg); /*DECL host_reg*/ } -static __inline void DEC_HOST_REG_W(int host_reg) +static __inline void +DEC_HOST_REG_W(int host_reg) { - addbyte(0x66); /*DECW host_reg*/ - addbyte(0x48 | host_reg); + addbyte(0x66); /*DECW host_reg*/ + addbyte(0x48 | host_reg); } -static __inline void DEC_HOST_REG(int host_reg) +static __inline void +DEC_HOST_REG(int host_reg) { - addbyte(0x48 | host_reg); /*DECL host_reg*/ + addbyte(0x48 | host_reg); /*DECL host_reg*/ } -static __inline int CMP_HOST_REG_B(int dst_reg, int src_reg) +static __inline int +CMP_HOST_REG_B(int dst_reg, int src_reg) { - SUB_HOST_REG_B(dst_reg, src_reg); + SUB_HOST_REG_B(dst_reg, src_reg); - return dst_reg; + return dst_reg; } -static __inline int CMP_HOST_REG_W(int dst_reg, int src_reg) +static __inline int +CMP_HOST_REG_W(int dst_reg, int src_reg) { - SUB_HOST_REG_W(dst_reg, src_reg); + SUB_HOST_REG_W(dst_reg, src_reg); - return dst_reg; + return dst_reg; } -static __inline int CMP_HOST_REG_L(int dst_reg, int src_reg) +static __inline int +CMP_HOST_REG_L(int dst_reg, int src_reg) { - SUB_HOST_REG_L(dst_reg, src_reg); + SUB_HOST_REG_L(dst_reg, src_reg); - return dst_reg; + return dst_reg; } -static __inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static __inline int +CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) { - SUB_HOST_REG_IMM_B(host_reg, imm); + SUB_HOST_REG_IMM_B(host_reg, imm); - return host_reg; + return host_reg; } -static __inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static __inline int +CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) { - SUB_HOST_REG_IMM_W(host_reg, imm); + SUB_HOST_REG_IMM_W(host_reg, imm); - return host_reg; + return host_reg; } -static __inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +static __inline int +CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) { - SUB_HOST_REG_IMM(host_reg, imm); + SUB_HOST_REG_IMM(host_reg, imm); - return host_reg; + return host_reg; } #define XOR_HOST_REG_B XOR_HOST_REG_L #define XOR_HOST_REG_W XOR_HOST_REG_L -static __inline void XOR_HOST_REG_L(int dst_reg, int src_reg) +static __inline void +XOR_HOST_REG_L(int dst_reg, int src_reg) { - addbyte(0x31); /*XORL dst_reg, src_reg*/ - addbyte(0xc0 | dst_reg | (src_reg << 3)); + addbyte(0x31); /*XORL dst_reg, src_reg*/ + addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static __inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +static __inline void +XOR_HOST_REG_IMM(int host_reg, uint32_t imm) { - if (imm < 0x80 || imm >= 0xffffff80) - { - addbyte(0x83); /*XORL host_reg, imm*/ - addbyte(0xF0 | host_reg); - addbyte(imm & 0xff); - } - else - { - addbyte(0x81); /*XORL host_reg, imm*/ - addbyte(0xF0 | host_reg); - addlong(imm); - } + if (imm < 0x80 || imm >= 0xffffff80) { + addbyte(0x83); /*XORL host_reg, imm*/ + addbyte(0xF0 | host_reg); + addbyte(imm & 0xff); + } else { + addbyte(0x81); /*XORL host_reg, imm*/ + addbyte(0xF0 | host_reg); + addlong(imm); + } } -static __inline void CALL_FUNC(uintptr_t dest) +static __inline void +CALL_FUNC(uintptr_t dest) { - addbyte(0xE8); /*CALL*/ - addlong(((uintptr_t)dest - (uintptr_t)(&codeblock[block_current].data[block_pos + 4]))); + addbyte(0xE8); /*CALL*/ + addlong(((uintptr_t) dest - (uintptr_t) (&codeblock[block_current].data[block_pos + 4]))); } -static __inline void SHL_B_IMM(int reg, int count) +static __inline void +SHL_B_IMM(int reg, int count) { - addbyte(0xc0); /*SHL reg, count*/ - addbyte(0xc0 | reg | 0x20); - addbyte(count); + addbyte(0xc0); /*SHL reg, count*/ + addbyte(0xc0 | reg | 0x20); + addbyte(count); } -static __inline void SHL_W_IMM(int reg, int count) +static __inline void +SHL_W_IMM(int reg, int count) { - addbyte(0x66); /*SHL reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x20); - addbyte(count); + addbyte(0x66); /*SHL reg, count*/ + addbyte(0xc1); + addbyte(0xc0 | reg | 0x20); + addbyte(count); } -static __inline void SHL_L_IMM(int reg, int count) +static __inline void +SHL_L_IMM(int reg, int count) { - addbyte(0xc1); /*SHL reg, count*/ - addbyte(0xc0 | reg | 0x20); - addbyte(count); + addbyte(0xc1); /*SHL reg, count*/ + addbyte(0xc0 | reg | 0x20); + addbyte(count); } -static __inline void SHR_B_IMM(int reg, int count) +static __inline void +SHR_B_IMM(int reg, int count) { - addbyte(0xc0); /*SHR reg, count*/ - addbyte(0xc0 | reg | 0x28); - addbyte(count); + addbyte(0xc0); /*SHR reg, count*/ + addbyte(0xc0 | reg | 0x28); + addbyte(count); } -static __inline void SHR_W_IMM(int reg, int count) +static __inline void +SHR_W_IMM(int reg, int count) { - addbyte(0x66); /*SHR reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x28); - addbyte(count); + addbyte(0x66); /*SHR reg, count*/ + addbyte(0xc1); + addbyte(0xc0 | reg | 0x28); + addbyte(count); } -static __inline void SHR_L_IMM(int reg, int count) +static __inline void +SHR_L_IMM(int reg, int count) { - addbyte(0xc1); /*SHR reg, count*/ - addbyte(0xc0 | reg | 0x28); - addbyte(count); + addbyte(0xc1); /*SHR reg, count*/ + addbyte(0xc0 | reg | 0x28); + addbyte(count); } -static __inline void SAR_B_IMM(int reg, int count) +static __inline void +SAR_B_IMM(int reg, int count) { - addbyte(0xc0); /*SAR reg, count*/ - addbyte(0xc0 | reg | 0x38); - addbyte(count); + addbyte(0xc0); /*SAR reg, count*/ + addbyte(0xc0 | reg | 0x38); + addbyte(count); } -static __inline void SAR_W_IMM(int reg, int count) +static __inline void +SAR_W_IMM(int reg, int count) { - addbyte(0x66); /*SAR reg, count*/ - addbyte(0xc1); - addbyte(0xc0 | reg | 0x38); - addbyte(count); + addbyte(0x66); /*SAR reg, count*/ + addbyte(0xc1); + addbyte(0xc0 | reg | 0x38); + addbyte(count); } -static __inline void SAR_L_IMM(int reg, int count) +static __inline void +SAR_L_IMM(int reg, int count) { - addbyte(0xc1); /*SAR reg, count*/ - addbyte(0xc0 | reg | 0x38); - addbyte(count); + addbyte(0xc1); /*SAR reg, count*/ + addbyte(0xc0 | reg | 0x38); + addbyte(count); } - -static __inline void CHECK_SEG_READ(x86seg *seg) +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; + /*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; - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x05|0x38); - addlong((uint32_t)&seg->base); - addbyte(-1); - addbyte(0x0f); - addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x05 | 0x38); + addlong((uint32_t) &seg->base); + addbyte(-1); + addbyte(0x0f); + addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - seg->checked = 1; + seg->checked = 1; } -static __inline void CHECK_SEG_WRITE(x86seg *seg) +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; + /*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; - addbyte(0x83); /*CMP seg->base, -1*/ - addbyte(0x05|0x38); - addlong((uint32_t)&seg->base); - addbyte(-1); - addbyte(0x0f); - addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ - addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x05 | 0x38); + addlong((uint32_t) &seg->base); + addbyte(-1); + addbyte(0x0f); + addbyte(0x84); /*JE BLOCK_GPF_OFFSET*/ + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); - seg->checked = 1; + seg->checked = 1; } -static __inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +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 ((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; - addbyte(0x3b); /*CMP EAX, seg->limit_low*/ - addbyte(0x05); - addlong((uint32_t)&seg->limit_low); - 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(0x05); - addlong((uint32_t)&seg->limit_high); - 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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_b*/ - addlong(mem_load_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_b_no_abrt*/ - addlong(mem_load_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ - addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -static __inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int 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))) - { - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0x3b); /*CMP EAX, seg->limit_low*/ + addbyte(0x05); + addlong((uint32_t) &seg->limit_low); + 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(offset); - addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ - addlong(mem_load_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[0] = 8; -} -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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_w_no_abrt*/ - addlong(mem_load_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; -} -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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_l*/ - addlong(mem_load_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - - host_reg_mapping[0] = 8; -} -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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_l_no_abrt*/ - addlong(mem_load_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - - host_reg_mapping[REG_ECX] = 8; - - return REG_ECX; + addbyte(end_offset); + addbyte(0x3b); /*CMP EAX, seg->limit_high*/ + addbyte(0x05); + addlong((uint32_t) &seg->limit_high); + 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_Q(x86seg *seg) +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 EDX, EDX*/ - addbyte(0xd2); - } - else - { - addbyte(0x8b); /*MOVL EDX, seg->base*/ - addbyte(0x05 | (REG_EDX << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_load_addr_ea_q*/ - addlong(mem_load_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + 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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_b*/ + addlong(mem_load_addr_ea_b - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); - host_reg_mapping[0] = 8; + host_reg_mapping[0] = 8; +} +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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_b_no_abrt*/ + addlong(mem_load_addr_ea_b_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} +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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ + addlong(mem_load_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} +static __inline void +MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int 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))) { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0x83); /*ADD EAX, offset*/ + addbyte(0xc0); + addbyte(offset); + addbyte(0xe8); /*CALL mem_load_addr_ea_w*/ + addlong(mem_load_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} +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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_w_no_abrt*/ + addlong(mem_load_addr_ea_w_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; +} +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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_l*/ + addlong(mem_load_addr_ea_l - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; +} +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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_l_no_abrt*/ + addlong(mem_load_addr_ea_l_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[REG_ECX] = 8; + + return REG_ECX; } -static __inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +static __inline void +MEM_LOAD_ADDR_EA_Q(x86seg *seg) { - 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); + 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 EDX, EDX*/ + addbyte(0xd2); + } else { + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_load_addr_ea_q*/ + addlong(mem_load_addr_ea_q - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + + host_reg_mapping[0] = 8; } -static __inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +static __inline void +MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) { - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ - addlong(mem_store_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_B(seg); } -static __inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) +static __inline void +MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) { - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_b_no_abrt*/ - addlong(mem_store_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_W(seg); } -static __inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +static __inline void +MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) { - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_w*/ - addlong(mem_store_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -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 ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_w_no_abrt*/ - addlong(mem_store_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -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 ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_l*/ - addlong(mem_store_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -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 ESI, ESI*/ - addbyte(0xf6); - } - else - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - if (host_reg != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg*/ - addbyte(0xc0 | REG_ECX | (host_reg << 3)); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_l_no_abrt*/ - addlong(mem_store_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -} -static __inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) -{ - if (host_reg != REG_EBX) - { - addbyte(0x89); /*MOV EBX, host_reg*/ - addbyte(0xc0 | REG_EBX | (host_reg << 3)); - } - if (host_reg2 != REG_ECX) - { - addbyte(0x89); /*MOV ECX, host_reg2*/ - addbyte(0xc0 | REG_ECX | (host_reg2 << 3)); - } - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_store_addr_ea_q*/ - addlong(mem_store_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_L(seg); } -static __inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_B(seg, 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 ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ + addlong(mem_store_addr_ea_b - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); } -static __inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_L(seg, 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 ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_b_no_abrt*/ + addlong(mem_store_addr_ea_b_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); } -static __inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +static __inline void +MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) { - addbyte(0xb8); /*MOV EAX, addr*/ - addlong(addr); - MEM_STORE_ADDR_EA_W(seg, 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 ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_w*/ + addlong(mem_store_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +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 ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_w_no_abrt*/ + addlong(mem_store_addr_ea_w_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +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 ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_l*/ + addlong(mem_store_addr_ea_l - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +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 ESI, ESI*/ + addbyte(0xf6); + } else { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + if (host_reg != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg*/ + addbyte(0xc0 | REG_ECX | (host_reg << 3)); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_l_no_abrt*/ + addlong(mem_store_addr_ea_l_no_abrt - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +} +static __inline void +MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +{ + if (host_reg != REG_EBX) { + addbyte(0x89); /*MOV EBX, host_reg*/ + addbyte(0xc0 | REG_EBX | (host_reg << 3)); + } + if (host_reg2 != REG_ECX) { + addbyte(0x89); /*MOV ECX, host_reg2*/ + addbyte(0xc0 | REG_ECX | (host_reg2 << 3)); + } + 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 { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_store_addr_ea_q*/ + addlong(mem_store_addr_ea_q - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); } - -static __inline x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +static __inline void +MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) { - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; - if (!mod && rm == 6) - { + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_B(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 +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 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, imm16*/ + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + switch (mod) { + case 0: + addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ + addlong((uint32_t) mod1add[0][rm]); + if (mod1add[1][rm] != &zero) { + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][rm]); + } + break; + case 1: + addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ + addlong((uint32_t) mod1add[0][rm]); + addbyte(0x83); /*ADDL EAX, imm8*/ + addbyte(0xc0 | REG_EAX); + addbyte((int8_t) (rmdat >> 8)); + if (mod1add[1][rm] != &zero) { + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][rm]); + } + (*op_pc)++; + break; + case 2: addbyte(0xb8); /*MOVL EAX, imm16*/ addlong((fetchdat >> 8) & 0xffff); + addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[0][rm]); + if (mod1add[1][rm] != &zero) { + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][rm]); + } (*op_pc) += 2; + break; } - else - { - switch (mod) - { - case 0: - addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ - addlong((uint32_t)mod1add[0][rm]); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - break; - case 1: - addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ - addlong((uint32_t)mod1add[0][rm]); - addbyte(0x83); /*ADDL EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(rmdat >> 8)); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - (*op_pc)++; - break; - case 2: - addbyte(0xb8); /*MOVL EAX, imm16*/ - addlong((fetchdat >> 8) & 0xffff); - addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][rm]); - if (mod1add[1][rm] != &zero) - { - addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][rm]); - } - (*op_pc) += 2; - break; - } - addbyte(0x25); /*ANDL EAX, 0xffff*/ - addlong(0xffff); + addbyte(0x25); /*ANDL EAX, 0xffff*/ + addlong(0xffff); - if (mod1seg[rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; } -static __inline x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +static __inline x86seg * +FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { - uint32_t new_eaaddr; - int mod = (fetchdat >> 6) & 3; - int rm = fetchdat & 7; + uint32_t new_eaaddr; + int mod = (fetchdat >> 6) & 3; + int rm = fetchdat & 7; - if (rm == 4) - { - uint8_t sib = fetchdat >> 8; + if (rm == 4) { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (mod) { + case 0: + if ((sib & 7) == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } else { + addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + } + break; + case 1: + addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + addbyte(0x83); /*ADDL EAX, imm8*/ + addbyte(0xc0 | REG_EAX); + addbyte((int8_t) (rmdat >> 16)); (*op_pc)++; - - switch (mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - } - break; - case 1: - addbyte(0x8b); /*MOVL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - addbyte(0x83); /*ADDL EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(rmdat >> 16)); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc) += 4; - break; - } - if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ - { - if (stack_offset < 0x80 || stack_offset >= 0xffffff80) - { - addbyte(0x83); - addbyte(0xc0 | REG_EAX); - addbyte(stack_offset); - } - else - { - addbyte(0x05); /*ADDL EAX, stack_offset*/ - addlong(stack_offset); - } - } - if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); - break; - case 1: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - case 2: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ - addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(2); /*SHL EDI, 2*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - case 3: - addbyte(0x8B); addbyte(0x45 | (REG_EDI << 3)); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI reg*/ - addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(3); /*SHL EDI, 3*/ - addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ - break; - } - } - } - else - { - if (!mod && rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - addbyte(0x8b); /*MOVL EAX, regs[rm].l*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[rm].l)); - cpu_state.eaaddr = cpu_state.regs[rm].l; - if (mod) - { - if (rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (mod == 1) - { - addbyte(0x83); /*ADD EAX, imm8*/ - addbyte(0xc0 | REG_EAX); - addbyte((int8_t)(fetchdat >> 8)); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x05); /*ADD EAX, imm32*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - } - 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 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_EBP].w)); - 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*/ - addbyte(0x83); - addbyte(0xc0 | 0x38 | host_reg); - 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) -{ - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | host_reg); - 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*/ - addbyte(0x83); - addbyte(0xc0 | 0x38 | host_reg); - 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) -{ - addbyte(0x83); /*CMPW host_reg, 0*/ - addbyte(0xc0 | 0x38 | host_reg); - 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) -{ - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x76); /*JBE*/ - else - addbyte(0x77); /*JNBE*/ + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + (*op_pc) += 4; break; + } + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + if (stack_offset < 0x80 || stack_offset >= 0xffffff80) { + addbyte(0x83); + addbyte(0xc0 | REG_EAX); + addbyte(stack_offset); + } else { + addbyte(0x05); /*ADDL EAX, stack_offset*/ + addlong(stack_offset); + } + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (((sib >> 3) & 7) != 4) { + switch (sib >> 6) { + case 0: + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); + break; + case 1: + addbyte(0x8B); + addbyte(0x45 | (REG_EDI << 3)); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + case 2: + addbyte(0x8B); + addbyte(0x45 | (REG_EDI << 3)); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI, reg*/ + addbyte(0xC1); + addbyte(0xE0 | REG_EDI); + addbyte(2); /*SHL EDI, 2*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + case 3: + addbyte(0x8B); + addbyte(0x45 | (REG_EDI << 3)); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL EDI reg*/ + addbyte(0xC1); + addbyte(0xE0 | REG_EDI); + addbyte(3); /*SHL EDI, 3*/ + addbyte(0x01); + addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + } + } + } else { + if (!mod && rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0x8b); /*MOVL EAX, regs[rm].l*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[rm].l)); + cpu_state.eaaddr = cpu_state.regs[rm].l; + if (mod) { + if (rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (mod == 1) { + addbyte(0x83); /*ADD EAX, imm8*/ + addbyte(0xc0 | REG_EAX); + addbyte((int8_t) (fetchdat >> 8)); + (*op_pc)++; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); /*ADD EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + } + return op_ea_seg; +} - default: - 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 +*/ - } - if (not) - addbyte(5+2+2+7+5+(timing_bt ? 4 : 0)); - else - addbyte(5+2+2); - CALL_FUNC((uintptr_t)CF_SET); +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 +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_EBP].w)); + 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*/ + addbyte(0x83); + addbyte(0xc0 | 0x38 | host_reg); + 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) +{ + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | host_reg); + 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*/ + addbyte(0x83); + addbyte(0xc0 | 0x38 | host_reg); + 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) +{ + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | host_reg); + 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 ) +{ + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + addbyte(0x8a); /*MOV AL, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3a); /*CMP AL, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x76); /*JBE*/ + else + addbyte(0x77); /*JNBE*/ + break; + case FLAGS_SUB16: + addbyte(0x66); /*MOV AX, flags_op1*/ + addbyte(0x8b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x66); /*CMP AX, flags_op2*/ + addbyte(0x3b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x76); /*JBE*/ + else + addbyte(0x77); /*JNBE*/ + break; + case FLAGS_SUB32: + addbyte(0x8b); /*MOV EAX, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3b); /*CMP EAX, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x76); /*JBE*/ + else + addbyte(0x77); /*JNBE*/ + break; + + default: + 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); - if (not) - addbyte(0x75); /*JNZ +*/ - else - addbyte(0x74); /*JZ +*/ - break; - } - 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)); + addbyte(0x75); /*JNZ +*/ + } + if (not ) + addbyte(5 + 2 + 2 + 7 + 5 + (timing_bt ? 4 : 0)); + else + addbyte(5 + 2 + 2); + CALL_FUNC((uintptr_t) CF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + if (not ) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + break; + } + 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_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static __inline void +BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7c); /*JL*/ - else - addbyte(0x7d); /*JNL*/ - break; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + addbyte(0x8a); /*MOV AL, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3a); /*CMP AL, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7c); /*JL*/ + else + addbyte(0x7d); /*JNL*/ + break; + case FLAGS_SUB16: + addbyte(0x66); /*MOV AX, flags_op1*/ + addbyte(0x8b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x66); /*CMP AX, flags_op2*/ + addbyte(0x3b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7c); /*JL*/ + else + addbyte(0x7d); /*JNL*/ + break; + case FLAGS_SUB32: + addbyte(0x8b); /*MOV EAX, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3b); /*CMP EAX, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7c); /*JL*/ + else + addbyte(0x7d); /*JNL*/ + break; - default: - 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 +*/ - break; - } - 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)); + default: + 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 +*/ + break; + } + 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) +static __inline void +BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not ) { - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: - addbyte(0x8a); /*MOV AL, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3a); /*CMP AL, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - case FLAGS_SUB16: - addbyte(0x66); /*MOV AX, flags_op1*/ - addbyte(0x8b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x66); /*CMP AX, flags_op2*/ - addbyte(0x3b); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; - case FLAGS_SUB32: - addbyte(0x8b); /*MOV EAX, flags_op1*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op1)); - addbyte(0x3b); /*CMP EAX, flags_op2*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(flags_op2)); - if (not) - addbyte(0x7e); /*JLE*/ - else - addbyte(0x7f); /*JNLE*/ - break; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + addbyte(0x8a); /*MOV AL, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3a); /*CMP AL, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7e); /*JLE*/ + else + addbyte(0x7f); /*JNLE*/ + break; + case FLAGS_SUB16: + addbyte(0x66); /*MOV AX, flags_op1*/ + addbyte(0x8b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x66); /*CMP AX, flags_op2*/ + addbyte(0x3b); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7e); /*JLE*/ + else + addbyte(0x7f); /*JNLE*/ + break; + case FLAGS_SUB32: + addbyte(0x8b); /*MOV EAX, flags_op1*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op1)); + addbyte(0x3b); /*CMP EAX, flags_op2*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(flags_op2)); + if (not ) + addbyte(0x7e); /*JLE*/ + else + addbyte(0x7f); /*JNLE*/ + break; - default: - 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 +*/ - } - if (not) - addbyte(5+2+3+5+2+3+2+2+7+5+(timing_bt ? 4 : 0)); - else - addbyte(5+2+3+5+2+3+2+2); - - CALL_FUNC((uintptr_t)NF_SET); + default: + 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(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 +*/ - break; - } - 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)); + addbyte(0x75); /*JNZ +*/ + } + if (not ) + addbyte(5 + 2 + 3 + 5 + 2 + 3 + 2 + 2 + 7 + 5 + (timing_bt ? 4 : 0)); + else + addbyte(5 + 2 + 3 + 5 + 2 + 3 + 2 + 2); + + 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 +*/ + break; + } + 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 FP_ENTER(void) +static __inline void +FP_ENTER(void) { - if (codegen_fpu_entered) - return; + if (codegen_fpu_entered) + return; - addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x05); + addlong((uintptr_t) &cr0); + addbyte(0xc); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 7 + 5 + 5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(op_old_pc); + addbyte(0xc7); /*MOV [ESP], 7*/ + addbyte(0x04); + addbyte(0x24); + addlong(7); + addbyte(0xe8); /*CALL x86_int*/ + addlong((uint32_t) x86_int - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + codegen_fpu_entered = 1; +} + +static __inline void +FP_FLD(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x88); /*MOV tag[-1][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + } else { + 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(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(0x07); + addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ + addbyte(0x54); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ + addbyte(0x4c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x8a); /*MOV AL, [tag+EAX]*/ + addbyte(0x44); addbyte(0x05); - addlong((uintptr_t)&cr0); - addbyte(0xc); - addbyte(0x74); /*JZ +*/ - addbyte(7+7+5+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - addbyte(0xc7); /*MOV [ESP], 7*/ - addbyte(0x04); - addbyte(0x24); - addlong(7); - addbyte(0xe8); /*CALL x86_int*/ - addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); - - codegen_fpu_entered = 1; -} - -static __inline void FP_FLD(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x88); /*MOV tag[-1][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - } - else - { - 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(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(0x07); - addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ - addbyte(0x54); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ - addbyte(0x4c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -static __inline void FP_FST(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - 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[0])); - - if (reg) - { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - } - - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - 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[0])); - } -} - -static __inline void FP_FXCH(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[cpu_state.TOP].q)); - addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); - addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/ - addbyte(0x0f); - addbyte(0xd6); - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(MM[cpu_state.TOP].q)); - addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); - addbyte(0x88); /*MOV tag[0][EBP], AH*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - } - else - { - 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(0xdd); /*FLD [ST+EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(0xbe); /*MOVL ESI, ST_int64*/ - addlong((uintptr_t)cpu_state.MM); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ - addbyte(0x0c); - addbyte(0xc6); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ - addbyte(0x14); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ - addbyte(0x0c); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ - addbyte(0x14); - addbyte(0xc6); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ - addbyte(0x4c); - addbyte(0xc6); - addbyte(0x04); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ - addbyte(0x54); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ - addbyte(0x4c); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ - addbyte(0x54); - addbyte(0xc6); - addbyte(0x04); - } -} - - -static __inline void FP_LOAD_S(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - 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(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - 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[0])); - } -} -static __inline void FP_LOAD_D(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV ST[reg][EBP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/ - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0xdd); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - 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[0])); - } -} -static __inline void FP_LOAD_IW(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0x66); /*TEST AX, AX*/ - addbyte(0x85); - addbyte(0xc0); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - 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[0])); - } -} -static __inline void FP_LOAD_IL(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x85); /*TEST EAX, EAX*/ - addbyte(0xc0); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x0f); /*SETE tag[reg][EBP]*/ - addbyte(0x94); - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - 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[0])); - } -} -static __inline void FP_LOAD_IQ(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV MM[reg][EBP], EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/ - addbyte(0x55); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdf); /*FILDq MM[reg][EBP]*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0x88); /*MOV tag[reg][EBP], AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(0xdd); /*FSTP ST[reg][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ - addbyte(0x6c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - } -} - -static __inline void FP_LOAD_IMM_Q(uint64_t v) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc7); /*MOV ST[reg][EBP], v*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); - addlong(v & 0xffffffff); - addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); - addlong(v >> 32); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP - 1) & 7); - addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); - addbyte(v ? 0 : 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - 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(0xc6); /*MOVB tag[reg][EBP], 1:0*/ - addbyte(0x44); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(v ? 0 : 1); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} - -static __inline int FP_LOAD_REG(int reg) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - addbyte(0xd9); /*FSTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV EAX, [ESP]*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(0x24); - - return REG_EBX; -} - -static __inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[reg][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - addbyte(0xdd); /*FSTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(0x24); - addbyte(0x8b); /*MOV ECX, [ESP+4]*/ - addbyte(0x44 | (REG_ECX << 3)); - addbyte(0x24); - addbyte(0x04); - - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; -} - -static __inline int FP_LOAD_REG_INT_W(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdb); /*FISTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - - return REG_EBX; -} -static __inline int FP_LOAD_REG_INT(int reg) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - if (reg) - { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdb); /*FISTP [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - - return REG_EBX; -} -static __inline void FP_LOAD_REG_INT_Q(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(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - 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(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); - addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); - - return; - } - - addbyte(0xf6); /*TEST TAG[EBX], TAG_UINT64*/ + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ addbyte(0x44); addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_UINT64); - addbyte(0x74); /*JZ +*/ - addbyte(4+4+2); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x89); /*MOV [TOP], EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + } +} + +static __inline void +FP_FST(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + } else { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + 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[0])); + + if (reg) { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + + addbyte(0xdd); /*FSTP [ST+EAX*8]*/ + addbyte(0x5c); + 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[0])); + } +} + +static __inline void +FP_FXCH(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(MM[cpu_state.TOP].q)); + addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(MM[cpu_state.TOP].q)); + addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[0][EBP], AH*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + } else { + 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(0xdd); /*FLD [ST+EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP [ST+EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV CL, tag[EAX]*/ + addbyte(0x4c); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x8a); /*MOV DL, tag[EBX]*/ + addbyte(0x54); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x88); /*MOV tag[EBX], CL*/ + addbyte(0x4c); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0x88); /*MOV tag[EAX], DL*/ + addbyte(0x54); + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(0xbe); /*MOVL ESI, ST_int64*/ + addlong((uintptr_t) cpu_state.MM); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ + addbyte(0x0c); + addbyte(0xc6); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ + addbyte(0x14); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ + addbyte(0x0c); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ + addbyte(0x14); + addbyte(0xc6); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ + addbyte(0x4c); + addbyte(0xc6); + addbyte(0x04); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ + addbyte(0x54); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ + addbyte(0x4c); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ + addbyte(0x54); + addbyte(0xc6); + addbyte(0x04); + } +} + +static __inline void +FP_LOAD_S(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0xd9); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xd9); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + 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(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + 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[0])); + } +} +static __inline void +FP_LOAD_D(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV ST[reg][EBP], EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/ + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0xdd); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + 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[0])); + } +} +static __inline void +FP_LOAD_IW(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0x66); /*TEST AX, AX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0xdf); /*FILDw [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xdf); /*FILDw [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + 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[0])); + } +} +static __inline void +FP_LOAD_IL(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0xdb); /*FILDl [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xdb); /*FILDl [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + 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[0])); + } +} +static __inline void +FP_LOAD_IQ(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV MM[reg][EBP], EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/ + addbyte(0x55); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0xdf); /*FILDq MM[reg][EBP]*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ + addbyte(0x54); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ + addbyte(0x6c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + } +} + +static __inline void +FP_LOAD_IMM_Q(uint64_t v) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xc7); /*MOV ST[reg][EBP], v*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(v ? 0 : 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + 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(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(v ? 0 : 1); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + } +} + +static __inline int +FP_LOAD_REG(int reg) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[reg][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + addbyte(0xd9); /*FSTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0x8b); /*MOV EAX, [ESP]*/ + addbyte(0x04 | (REG_EBX << 3)); + addbyte(0x24); + + return REG_EBX; +} + +static __inline void +FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[reg][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + addbyte(0xdd); /*FSTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x04 | (REG_EBX << 3)); + addbyte(0x24); + addbyte(0x8b); /*MOV ECX, [ESP+4]*/ + addbyte(0x44 | (REG_ECX << 3)); + addbyte(0x24); + addbyte(0x04); + + *host_reg1 = REG_EBX; + *host_reg2 = REG_ECX; +} + +static __inline int +FP_LOAD_REG_INT_W(int reg) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addbyte(0xdb); /*FISTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + + return REG_EBX; +} +static __inline int +FP_LOAD_REG_INT(int reg) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + if (reg) { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addbyte(0xdb); /*FISTP [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + + return REG_EBX; +} +static __inline void +FP_LOAD_REG_INT_Q(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(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + 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(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ addbyte(0x4c); addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)+4); + addbyte((uint8_t) cpu_state_offset(MM) + 4); addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ addbyte(0x5c); addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(MM)); + addbyte((uint8_t) cpu_state_offset(MM)); - addbyte(0xeb); /*JMP done*/ - addbyte(4+3+3+3+3+4); + return; + } - addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0xf6); /*TEST TAG[EBX], TAG_UINT64*/ + addbyte(0x44); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_UINT64); + addbyte(0x74); /*JZ +*/ + addbyte(4 + 4 + 2); + + addbyte(0x8b); /*MOV ECX, [ST_i64+EBX*8]*/ + addbyte(0x4c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM) + 4); + addbyte(0x8b); /*MOV EBX, [ST_i64+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(MM)); + + addbyte(0xeb); /*JMP done*/ + addbyte(4 + 3 + 3 + 3 + 3 + 4); + + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addbyte(0xdf); /*FISTPQ [ESP]*/ + addbyte(0x3c); + addbyte(0x24); + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + addbyte(0x8b); /*MOV EBX, [ESP]*/ + addbyte(0x1c); + addbyte(0x24); + addbyte(0x8b); /*MOV ECX, 4[ESP]*/ + addbyte(0x4c); + addbyte(0x24); + addbyte(4); + + *host_reg1 = REG_EBX; + *host_reg2 = REG_ECX; +} + +static __inline void +FP_POP(void) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(3); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP + 1) & 7); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addbyte(0xdf); /*FISTPQ [ESP]*/ - addbyte(0x3c); - addbyte(0x24); - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - addbyte(0x8b); /*MOV EBX, [ESP]*/ - addbyte(0x1c); - addbyte(0x24); - addbyte(0x8b); /*MOV ECX, 4[ESP]*/ - addbyte(0x4c); - addbyte(0x24); - addbyte(4); - - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; + addbyte(0x05); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(3); + addbyte(0x04); /*ADD AL, 1*/ + addbyte(1); + addbyte(0x24); /*AND AL, 7*/ + addbyte(7); + addbyte(0x88); /*MOV TOP, AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + } } - -static __inline void FP_POP(void) +static __inline void +FP_POP2(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(3); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP + 1) & 7); - } - else - { - 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[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 1*/ - addbyte(1); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - } -} -static __inline void FP_POP2(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(3); - addbyte(0xc6); /*MOVB tag[1][EBP], 3*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP+1)&7])); - addbyte(3); - addbyte(0xc6); /*MOVB TOP[EBP], (TOP+2) & 7*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte((cpu_state.TOP + 2) & 7); - } - else - { - 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[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 2*/ - addbyte(2); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(3); + addbyte(0xc6); /*MOVB tag[1][EBP], 3*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + 1) & 7])); + addbyte(3); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP+2) & 7*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte((cpu_state.TOP + 2) & 7); + } else { + 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[0])); + addbyte(3); + addbyte(0x04); /*ADD AL, 2*/ + addbyte(2); + addbyte(0x24); /*AND AL, 7*/ + addbyte(7); + addbyte(0x88); /*MOV TOP, AL*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + } } #define FPU_ADD 0x00 @@ -2692,226 +2627,214 @@ static __inline void FP_POP2(void) #define FPU_SUB 0x20 #define FPU_SUBR 0x28 -static __inline void FP_OP_S(int op) +static __inline void +FP_OP_S(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xd8); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xd8); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static __inline void FP_OP_D(int op) +static __inline void +FP_OP_D(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - } - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - } - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) - { - addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ - addbyte(0x6d); - addbyte((uint8_t)cpu_state_offset(old_npxc)); - } + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); } + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + } + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) { + addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/ + addbyte(0x6d); + addbyte((uint8_t) cpu_state_offset(old_npxc)); + } + } } -static __inline void FP_OP_IW(int op) +static __inline void +FP_OP_IW(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xde); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xde); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static __inline void FP_OP_IL(int op) +static __inline void +FP_OP_IL(int op) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP ST[0][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xda); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xda); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } } #if 0 static __inline void FP_OP_IQ(int op) @@ -2971,1037 +2894,1032 @@ static __inline void FP_OP_IQ(int op) } #endif -static __inline void FP_COMPARE_S(void) +static __inline void +FP_COMPARE_S(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xd8); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xd8); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static __inline void FP_COMPARE_D(void) +static __inline void +FP_COMPARE_D(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xdc); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xdc); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static __inline void FP_COMPARE_IW(void) +static __inline void +FP_COMPARE_IW(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x66); /*MOV [ESP], AX*/ - addbyte(0x89); - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xde); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xde); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static __inline void FP_COMPARE_IL(void) +static __inline void +FP_COMPARE_IL(void) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } - else - { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - } + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xda); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } else { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xda); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0 | C2 | C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + } } -static __inline void FP_OP_REG(int op, int dst, int src) +static __inline void +FP_OP_REG(int op, int dst, int src) { - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - addbyte(0xdc); /*FADD ST[src][EBP]*/ - addbyte(0x45 | op); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - } - else - { - 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); - } - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte((uint8_t)cpu_state_offset(tag[0])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdc); /*FADD ST[EAX*8]*/ - addbyte(0x44 | op); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - 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(0xdc); /*FADD ST[EBX*8]*/ - addbyte(0x44 | op); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - } -} - -static __inline void FP_COMPARE_REG(int dst, int src) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte((uint8_t)cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0xdd); /*FLD ST[dst][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP ST[src][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - 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); - } - else - { - 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(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EAX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } - else - { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EBX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xdd); - addbyte((uint8_t)cpu_state_offset(ST)); - } - - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - 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_FCHS(void) -{ - if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) - { - addbyte(0xdd); /*FLD ST[0][EBP]*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - addbyte(0xd9); /*FCHS*/ - addbyte(0xe0); - addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ - addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); - addbyte(TAG_NOT_UINT64); - addbyte(0xdd); /*FSTP ST[dst][EBP]*/ - addbyte(0x5d); - addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); - } - else - { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(TOP)); - - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - 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(0xd9); /*FCHS*/ - addbyte(0xe0); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte((uint8_t)cpu_state_offset(ST)); - } -} - -static __inline void UPDATE_NPXC(int reg) -{ - addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ - addbyte(0x81); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + addbyte(0xdc); /*FADD ST[src][EBP]*/ + addbyte(0x45 | op); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ addbyte(0x65); - addbyte((uint8_t)cpu_state_offset(new_npxc)); - addword(~0xc00); - if (reg) - { - addbyte(0x66); /*AND reg, 0xc00*/ - addbyte(0x81); - addbyte(0xe0 | reg); - addword(0xc00); + addbyte((uint8_t) cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + } else { + 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); } - else - { - addbyte(0x66); /*AND AX, 0xc00*/ - addbyte(0x25); - addword(0xc00); + + if (src) { + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte((uint8_t) cpu_state_offset(tag[0])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdc); /*FADD ST[EAX*8]*/ + addbyte(0x44 | op); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP ST[EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + 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(0xdc); /*FADD ST[EBX*8]*/ + addbyte(0x44 | op); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); } - addbyte(0x66); /*OR cpu_state.new_npxc, reg*/ - addbyte(0x09); - addbyte(0x45 | (reg << 3)); - addbyte((uint8_t)cpu_state_offset(new_npxc)); + } } -static __inline int ZERO_EXTEND_W_B(int reg) +static __inline void +FP_COMPARE_REG(int dst, int src) { - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static __inline int ZERO_EXTEND_L_B(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regb*/ - addbyte(0xb6); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static __inline int ZERO_EXTEND_L_W(int reg) -{ - addbyte(0x0f); /*MOVZX regl, regw*/ - addbyte(0xb7); - addbyte(0xc0 | reg | (reg << 3)); - return reg; + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte((uint8_t) cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0 | C2 | C3)) >> 8); + addbyte(0xdc); /*FCOMP ST[src][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + 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); + } else { + 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(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0 | C2 | C3)) >> 8); + + if (src) { + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdc); /*FCOMP ST[EAX*8]*/ + addbyte(0x44 | 0x18); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } else { + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0xdc); /*FCOMP ST[EBX*8]*/ + addbyte(0x44 | 0x18); + addbyte(0xdd); + addbyte((uint8_t) cpu_state_offset(ST)); + } + + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + 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 int SIGN_EXTEND_W_B(int reg) +static __inline void +FP_FCHS(void) { - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static __inline int SIGN_EXTEND_L_B(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regb*/ - addbyte(0xbe); - addbyte(0xc0 | reg | (reg << 3)); - return reg; -} -static __inline int SIGN_EXTEND_L_W(int reg) -{ - addbyte(0x0f); /*MOVSX regl, regw*/ - addbyte(0xbf); - addbyte(0xc0 | reg | (reg << 3)); - return reg; + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(tag[cpu_state.TOP])); + addbyte(TAG_NOT_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte((uint8_t) cpu_state_offset(ST[cpu_state.TOP])); + } else { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(TOP)); + + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + 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(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte((uint8_t) cpu_state_offset(ST)); + } } -static __inline int COPY_REG(int src_reg) +static __inline void +UPDATE_NPXC(int reg) { - return src_reg; + addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ + addbyte(0x81); + addbyte(0x65); + addbyte((uint8_t) cpu_state_offset(new_npxc)); + addword(~0xc00); + if (reg) { + addbyte(0x66); /*AND reg, 0xc00*/ + addbyte(0x81); + addbyte(0xe0 | reg); + addword(0xc00); + } else { + addbyte(0x66); /*AND AX, 0xc00*/ + addbyte(0x25); + addword(0xc00); + } + addbyte(0x66); /*OR cpu_state.new_npxc, reg*/ + addbyte(0x09); + addbyte(0x45 | (reg << 3)); + addbyte((uint8_t) cpu_state_offset(new_npxc)); } -static __inline void SET_BITS(uintptr_t addr, uint32_t val) +static __inline int +ZERO_EXTEND_W_B(int reg) { - if (val & ~0xff) - { - addbyte(0x81); - addbyte(0x0d); - addlong(addr); - addlong(val); - } - else - { - addbyte(0x80); - addbyte(0x0d); - addlong(addr); - addbyte(val); - } + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static __inline void CLEAR_BITS(uintptr_t addr, uint32_t val) +static __inline int +ZERO_EXTEND_L_B(int reg) { - if (val & ~0xff) - { - addbyte(0x81); - addbyte(0x25); - addlong(addr); - addlong(~val); - } - else - { - addbyte(0x80); - addbyte(0x25); - addlong(addr); - addbyte(~val); - } + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} +static __inline int +ZERO_EXTEND_L_W(int reg) +{ + addbyte(0x0f); /*MOVZX regl, regw*/ + addbyte(0xb7); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} + +static __inline int +SIGN_EXTEND_W_B(int reg) +{ + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} +static __inline int +SIGN_EXTEND_L_B(int reg) +{ + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} +static __inline int +SIGN_EXTEND_L_W(int reg) +{ + addbyte(0x0f); /*MOVSX regl, regw*/ + addbyte(0xbf); + addbyte(0xc0 | reg | (reg << 3)); + return reg; +} + +static __inline int +COPY_REG(int src_reg) +{ + return src_reg; +} + +static __inline void +SET_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) { + addbyte(0x81); + addbyte(0x0d); + addlong(addr); + addlong(val); + } else { + addbyte(0x80); + addbyte(0x0d); + addlong(addr); + addbyte(val); + } +} +static __inline void +CLEAR_BITS(uintptr_t addr, uint32_t val) +{ + if (val & ~0xff) { + addbyte(0x81); + addbyte(0x25); + addlong(addr); + addlong(~val); + } else { + addbyte(0x80); + addbyte(0x25); + addlong(addr); + addbyte(~val); + } } #define LOAD_Q_REG_1 REG_EAX #define LOAD_Q_REG_2 REG_EDX -static __inline void MMX_ENTER(void) +static __inline void +MMX_ENTER(void) { - if (codegen_mmx_entered) - return; + if (codegen_mmx_entered) + return; - addbyte(0xf6); /*TEST cr0, 0xc*/ - addbyte(0x05); - addlong((uintptr_t)&cr0); - addbyte(0xc); - addbyte(0x74); /*JZ +*/ - addbyte(7+7+5+5); - addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(op_old_pc); - addbyte(0xc7); /*MOV [ESP], 7*/ - addbyte(0x04); - addbyte(0x24); - addlong(7); - addbyte(0xe8); /*CALL x86_int*/ - addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0xe9); /*JMP end*/ - addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x05); + addlong((uintptr_t) &cr0); + addbyte(0xc); + addbyte(0x74); /*JZ +*/ + addbyte(7 + 7 + 5 + 5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(op_old_pc); + addbyte(0xc7); /*MOV [ESP], 7*/ + addbyte(0x04); + addbyte(0x24); + addlong(7); + addbyte(0xe8); /*CALL x86_int*/ + addlong((uint32_t) x86_int - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + 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])); + 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; + codegen_mmx_entered = 1; } extern int mmx_ebx_ecx_loaded; -static __inline int LOAD_MMX_D(int guest_reg) +static __inline int +LOAD_MMX_D(int guest_reg) { - int host_reg = find_host_reg(); - host_reg_mapping[host_reg] = 100; + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = 100; - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0x8b); /*MOV EBX, reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); - return host_reg; + return host_reg; } -static __inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +static __inline void +LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) { - if (!mmx_ebx_ecx_loaded) - { - *host_reg1 = REG_EBX; - *host_reg2 = REG_ECX; - mmx_ebx_ecx_loaded = 1; - } - else - { - *host_reg1 = REG_EAX; - *host_reg2 = REG_EDX; - } + if (!mmx_ebx_ecx_loaded) { + *host_reg1 = REG_EBX; + *host_reg2 = REG_ECX; + mmx_ebx_ecx_loaded = 1; + } else { + *host_reg1 = REG_EAX; + *host_reg2 = REG_EDX; + } - addbyte(0x8b); /*MOV EBX, reg*/ - addbyte(0x45 | ((*host_reg1) << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - addbyte(0x8b); /*MOV ECX, reg+4*/ - addbyte(0x45 | ((*host_reg2) << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); + addbyte(0x8b); /*MOV EBX, reg*/ + addbyte(0x45 | ((*host_reg1) << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0x8b); /*MOV ECX, reg+4*/ + addbyte(0x45 | ((*host_reg2) << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); } -static __inline int LOAD_MMX_Q_MMX(int guest_reg) +static __inline int +LOAD_MMX_Q_MMX(int guest_reg) { - int dst_reg = find_host_xmm_reg(); - host_reg_xmm_mapping[dst_reg] = guest_reg; + int dst_reg = find_host_xmm_reg(); + host_reg_xmm_mapping[dst_reg] = guest_reg; - addbyte(0xf3); /*MOVQ dst_reg,[reg]*/ - addbyte(0x0f); - addbyte(0x7e); - addbyte(0x45 | (dst_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); + addbyte(0xf3); /*MOVQ dst_reg,[reg]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45 | (dst_reg << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].q)); - return dst_reg; + return dst_reg; } -static __inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +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; + int dst_reg = find_host_xmm_reg(); + host_reg_xmm_mapping[dst_reg] = 100; - addbyte(0x66); /*MOVD dst_reg, src_reg1*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (dst_reg << 3) | src_reg1); - addbyte(0x66); /*MOVD XMM7, src_reg2*/ - addbyte(0x0f); - addbyte(0x6e); - addbyte(0xc0 | (7 << 3) | src_reg2); - addbyte(0x66); /*PUNPCKLDQ dst_reg, XMM7*/ - addbyte(0x0f); - addbyte(0x62); - addbyte(0xc0 | 7 | (dst_reg << 3)); + addbyte(0x66); /*MOVD dst_reg, src_reg1*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0 | (dst_reg << 3) | src_reg1); + addbyte(0x66); /*MOVD XMM7, src_reg2*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0 | (7 << 3) | src_reg2); + addbyte(0x66); /*PUNPCKLDQ dst_reg, XMM7*/ + addbyte(0x0f); + addbyte(0x62); + addbyte(0xc0 | 7 | (dst_reg << 3)); - return dst_reg; + return dst_reg; } -static __inline void STORE_MMX_LQ(int guest_reg, int host_reg1) +static __inline void +STORE_MMX_LQ(int guest_reg, int host_reg1) { - addbyte(0xC7); /*MOVL [reg],0*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); - addlong(0); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg1 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0xC7); /*MOVL [reg],0*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); + addlong(0); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg1 << 3)); + 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) +static __inline void +STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) { - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg1 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); - addbyte(0x89); /*MOVL [reg],host_reg*/ - addbyte(0x45 | (host_reg2 << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg1 << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[0])); + addbyte(0x89); /*MOVL [reg],host_reg*/ + addbyte(0x45 | (host_reg2 << 3)); + addbyte((uint8_t) cpu_state_offset(MM[guest_reg].l[1])); } -static __inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) +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(0x45 | (host_reg << 3)); - addbyte((uint8_t)cpu_state_offset(MM[guest_reg].q)); + addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45 | (host_reg << 3)); + 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); \ -} +#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(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(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(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(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(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(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(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(PMULLW, 0xd5); +MMX_x86_OP(PMULHW, 0xe5); MMX_x86_OP(PMADDWD, 0xf5); -static __inline void MMX_PACKSSWB(int dst_reg, int src_reg) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + 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) +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); + addbyte(0x66); /*PSLLQ dst_reg, amount*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xc0 | dst_reg | 0x30); + addbyte(amount); } - -static __inline void SAVE_EA(void) +static __inline void +SAVE_EA(void) { - addbyte(0x89); /*MOV [ESP+12], EAX*/ - addbyte(0x44); - addbyte(0x24); - addbyte(12); + addbyte(0x89); /*MOV [ESP+12], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(12); } -static __inline void LOAD_EA(void) +static __inline void +LOAD_EA(void) { - addbyte(0x8b); /*MOV EAX, [ESP+12]*/ - addbyte(0x44); - addbyte(0x24); - addbyte(12); + addbyte(0x8b); /*MOV EAX, [ESP+12]*/ + addbyte(0x44); + addbyte(0x24); + addbyte(12); } #define MEM_CHECK_WRITE_B MEM_CHECK_WRITE -static __inline void MEM_CHECK_WRITE(x86seg *seg) +static __inline void +MEM_CHECK_WRITE(x86seg *seg) { - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write*/ - addlong(mem_check_write - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); + 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 { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_check_write*/ + addlong(mem_check_write - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + LOAD_EA(); } -static __inline void MEM_CHECK_WRITE_W(x86seg *seg) +static __inline void +MEM_CHECK_WRITE_W(x86seg *seg) { - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write_w*/ - addlong(mem_check_write_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); + 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 { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_check_write_w*/ + addlong(mem_check_write_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + LOAD_EA(); } -static __inline void MEM_CHECK_WRITE_L(x86seg *seg) +static __inline void +MEM_CHECK_WRITE_L(x86seg *seg) { - 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 - { - addbyte(0x8b); /*MOVL ESI, seg->base*/ - addbyte(0x05 | (REG_ESI << 3)); - addlong((uint32_t)&seg->base); - } - addbyte(0xe8); /*CALL mem_check_write_l*/ - addlong(mem_check_write_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - LOAD_EA(); + 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 { + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t) &seg->base); + } + addbyte(0xe8); /*CALL mem_check_write_l*/ + addlong(mem_check_write_l - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + LOAD_EA(); } -static __inline void LOAD_SEG(int host_reg, void *seg) +static __inline void +LOAD_SEG(int host_reg, void *seg) { - addbyte(0xc7); /*MOV [ESP+4], seg*/ - addbyte(0x44); - addbyte(0x24); - addbyte(4); - addlong((uint32_t)seg); - addbyte(0x89); /*MOV [ESP], host_reg*/ - addbyte(0x04 | (host_reg << 3)); - addbyte(0x24); - 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)); + addbyte(0xc7); /*MOV [ESP+4], seg*/ + addbyte(0x44); + addbyte(0x24); + addbyte(4); + addlong((uint32_t) seg); + addbyte(0x89); /*MOV [ESP], host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(0x24); + 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/codegen/codegen_ops_xchg.h b/src/codegen/codegen_ops_xchg.h index a51f42eda..071acc3d8 100644 --- a/src/codegen/codegen_ops_xchg.h +++ b/src/codegen/codegen_ops_xchg.h @@ -1,16 +1,16 @@ -#define OP_XCHG_AX_(reg) \ - static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int ax_reg, host_reg, temp_reg; \ - \ - ax_reg = LOAD_REG_W(REG_AX); \ - host_reg = LOAD_REG_W(REG_ ## reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \ - STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ - \ - return op_pc; \ - } +#define OP_XCHG_AX_(reg) \ + static uint32_t ropXCHG_AX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int ax_reg, host_reg, temp_reg; \ + \ + ax_reg = LOAD_REG_W(REG_AX); \ + host_reg = LOAD_REG_W(REG_##reg); \ + temp_reg = COPY_REG(host_reg); \ + STORE_REG_TARGET_W_RELEASE(ax_reg, REG_##reg); \ + STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ + \ + return op_pc; \ + } OP_XCHG_AX_(BX) OP_XCHG_AX_(CX) @@ -20,19 +20,19 @@ OP_XCHG_AX_(DI) OP_XCHG_AX_(SP) OP_XCHG_AX_(BP) -#define OP_XCHG_EAX_(reg) \ - static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ - { \ - int eax_reg, host_reg, temp_reg; \ - \ - eax_reg = LOAD_REG_L(REG_EAX); \ - host_reg = LOAD_REG_L(REG_ ## reg); \ - temp_reg = COPY_REG(host_reg); \ - STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \ - STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ - \ - return op_pc; \ - } +#define OP_XCHG_EAX_(reg) \ + static uint32_t ropXCHG_EAX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + int eax_reg, host_reg, temp_reg; \ + \ + eax_reg = LOAD_REG_L(REG_EAX); \ + host_reg = LOAD_REG_L(REG_##reg); \ + temp_reg = COPY_REG(host_reg); \ + STORE_REG_TARGET_L_RELEASE(eax_reg, REG_##reg); \ + STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ + \ + return op_pc; \ + } OP_XCHG_EAX_(EBX) OP_XCHG_EAX_(ECX) @@ -42,48 +42,51 @@ OP_XCHG_EAX_(EDI) OP_XCHG_EAX_(ESP) OP_XCHG_EAX_(EBP) -static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg, temp_reg; + int src_reg, dst_reg, temp_reg; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) != 0xc0) + return 0; - dst_reg = LOAD_REG_B(fetchdat & 7); - src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7); + dst_reg = LOAD_REG_B(fetchdat & 7); + src_reg = LOAD_REG_B((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); + STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7); + STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg, temp_reg; + int src_reg, dst_reg, temp_reg; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) != 0xc0) + return 0; - dst_reg = LOAD_REG_W(fetchdat & 7); - src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7); + dst_reg = LOAD_REG_W(fetchdat & 7); + src_reg = LOAD_REG_W((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); + STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7); + STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7); - return op_pc + 1; + return op_pc + 1; } -static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +static uint32_t +ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg, temp_reg; + int src_reg, dst_reg, temp_reg; - if ((fetchdat & 0xc0) != 0xc0) - return 0; + if ((fetchdat & 0xc0) != 0xc0) + return 0; - dst_reg = LOAD_REG_L(fetchdat & 7); - src_reg = LOAD_REG_L((fetchdat >> 3) & 7); - temp_reg = COPY_REG(src_reg); - STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7); + dst_reg = LOAD_REG_L(fetchdat & 7); + src_reg = LOAD_REG_L((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); + STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7); + STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7); - return op_pc + 1; + return op_pc + 1; } diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index 6ee277f72..6939819d4 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -1,1188 +1,1116 @@ #if defined __amd64__ || defined _M_X64 -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include "x86.h" -#include "x86_flags.h" -#include "x86_ops.h" -#include "x87.h" -#include <86box/mem.h> +# include +# include +# include +# include +# include +# define HAVE_STDARG_H +# include <86box/86box.h> +# include "cpu.h" +# include "x86.h" +# include "x86_flags.h" +# include "x86_ops.h" +# include "x87.h" +# include <86box/mem.h> -#include "386_common.h" +# include "386_common.h" -#include "codegen.h" -#include "codegen_accumulate.h" -#include "codegen_ops.h" -#include "codegen_ops_x86-64.h" +# include "codegen.h" +# include "codegen_accumulate.h" +# include "codegen_ops.h" +# include "codegen_ops_x86-64.h" -#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) -#include -#include -#endif -#if _WIN64 -#include -#endif +# if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) +# include +# include +# endif +# if _WIN64 +# include +# endif -int codegen_flat_ds, codegen_flat_ss; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_fpu_loaded_iq[8]; -int codegen_reg_loaded[8]; -x86seg *op_ea_seg; -int op_ssegs; +int codegen_flat_ds, codegen_flat_ss; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_fpu_loaded_iq[8]; +int codegen_reg_loaded[8]; +x86seg *op_ea_seg; +int op_ssegs; uint32_t op_old_pc; uint32_t recomp_page = -1; -int host_reg_mapping[NR_HOST_REGS]; -int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; -codeblock_t *codeblock; +int host_reg_mapping[NR_HOST_REGS]; +int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; +codeblock_t *codeblock; codeblock_t **codeblock_hash; -int codegen_mmx_entered = 0; +int codegen_mmx_entered = 0; -int block_current = 0; +int block_current = 0; static int block_num; -int block_pos; +int block_pos; uint32_t codegen_endpc; -int codegen_block_cycles; +int codegen_block_cycles; static int codegen_block_ins; static int codegen_block_full_ins; static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; +static x86seg *last_ea_seg; +static int last_ssegs; -void codegen_init(void) +void +codegen_init(void) { - int c; + int c; -#if _WIN64 - codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#elif defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) - codeblock = mmap(NULL, BLOCK_SIZE * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); -#else - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); -#endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); +# if _WIN64 + codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +# elif defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) + codeblock = mmap(NULL, BLOCK_SIZE * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); +# else + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); +# endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].valid = 0; + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].valid = 0; } -void codegen_reset(void) +void +codegen_reset(void) { - int c; + int c; - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - mem_reset_page_blocks(); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + mem_reset_page_blocks(); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].valid = 0; + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].valid = 0; } -void dump_block(void) +void +dump_block(void) { } -static void add_to_block_list(codeblock_t *block) +static void +add_to_block_list(codeblock_t *block) { - codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; - if (!block->page_mask) - fatal("add_to_block_list - mask = 0\n"); + if (!block->page_mask) + fatal("add_to_block_list - mask = 0\n"); - if (block_prev) - { - block->next = block_prev; - block_prev->prev = block; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - else - { - block->next = NULL; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - - if (block->next) - { - if (block->next->valid == 0) - fatal("block->next->valid=0 %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); - } - - if (block->page_mask2) - { - block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; - - if (block_prev) - { - block->next_2 = block_prev; - block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - else - { - block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } + if (block_prev) { + block->next = block_prev; + block_prev->prev = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } else { + block->next = NULL; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } + + if (block->next) { + if (block->next->valid == 0) + fatal("block->next->valid=0 %p %p %x %x\n", (void *) block->next, (void *) codeblock, block_current, block_pos); + } + + if (block->page_mask2) { + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + + if (block_prev) { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + } else { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } + } } -static void remove_from_block_list(codeblock_t *block, uint32_t pc) -{ - if (!block->page_mask) - return; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; - if (block->next) - block->next->prev = NULL; - else - mem_flush_write_page(block->phys, 0); - } - if (!block->page_mask2) - { - if (block->prev_2 || block->next_2) - fatal("Invalid block_2\n"); - return; - } - - if (block->prev_2) - { - block->prev_2->next_2 = block->next_2; - if (block->next_2) - block->next_2->prev_2 = block->prev_2; - } - else - { - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; - if (block->next_2) - block->next_2->prev_2 = NULL; - else - mem_flush_write_page(block->phys_2, 0); - } -} - -static void delete_block(codeblock_t *block) -{ - uint32_t old_pc = block->pc; - - if (block == codeblock_hash[HASH(block->phys)]) - codeblock_hash[HASH(block->phys)] = NULL; - - if (block->valid == 0) - fatal("Deleting deleted block\n"); - block->valid = 0; - - codeblock_tree_delete(block); - remove_from_block_list(block, old_pc); -} - -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) -{ - struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask) - { - delete_block(block); - } - if (block == block->next) - fatal("Broken 1\n"); - block = block->next; - } - - block = page->block_2[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask2) - { - delete_block(block); - } - if (block == block->next_2) - fatal("Broken 2\n"); - block = block->next_2; - } -} - -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block[(phys_addr >> 10) & 3]) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - - block_current = (block_current + 1) & BLOCK_MASK; - block = &codeblock[block_current]; - - if (block->valid != 0) - { - delete_block(block); - } - block_num = HASH(phys_addr); - codeblock_hash[block_num] = &codeblock[block_current]; - - block->valid = 1; - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->pnt = block_current; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - block->dirty_mask2 = NULL; - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - block->page_mask = 0; - block->flags = 0; - block->status = cpu_cur_status; - - block->was_recompiled = 0; - - recomp_page = block->phys & ~0xfff; - - codeblock_tree_add(block); -} - -void codegen_block_start_recompile(codeblock_t *block) -{ - page_t *page = &pages[block->phys >> 12]; - uintptr_t rip_rel; - - if (!page->block[(block->phys >> 10) & 3]) - mem_flush_write_page(block->phys, cs+cpu_state.pc); - - block_num = HASH(block->phys); - block_current = block->pnt; - - if (block->pc != cs + cpu_state.pc || block->was_recompiled) - fatal("Recompile to used block!\n"); - - block->status = cpu_cur_status; - - block_pos = BLOCK_GPF_OFFSET; -#ifdef OLD_GPF -#if _WIN64 - addbyte(0x48); /*XOR RCX, RCX*/ - addbyte(0x31); - addbyte(0xc9); - addbyte(0x31); /*XOR EDX, EDX*/ - addbyte(0xd2); -#else - addbyte(0x48); /*XOR RDI, RDI*/ - addbyte(0x31); - addbyte(0xff); - addbyte(0x31); /*XOR ESI, ESI*/ - addbyte(0xf6); -#endif - call(block, (uintptr_t)x86gpf); - while (block_pos < BLOCK_EXIT_OFFSET) - addbyte(0x90); /*NOP*/ -#else - addbyte(0xC6); /*MOVB ABRT_GPF,(abrt)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(ABRT_GPF); - addbyte(0x31); /* xor eax,eax */ - addbyte(0xc0); - addbyte(0x89); /*MOVB eax,(abrt_error)*/ - addbyte(0x85); - rip_rel = ((uintptr_t)&cpu_state) + 128; - rip_rel = ((uintptr_t) &(abrt_error)) - rip_rel; - addlong((uint32_t) rip_rel); -#endif - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x28); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ - cpu_block_end = 0; - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH RBX*/ - addbyte(0x55); /*PUSH RBP*/ - addbyte(0x56); /*PUSH RSI*/ - addbyte(0x57); /*PUSH RDI*/ - addbyte(0x41); /*PUSH R12*/ - addbyte(0x54); - addbyte(0x41); /*PUSH R13*/ - addbyte(0x55); - addbyte(0x41); /*PUSH R14*/ - addbyte(0x56); - addbyte(0x41); /*PUSH R15*/ - addbyte(0x57); - addbyte(0x48); /*SUBL $40,%rsp*/ - addbyte(0x83); - addbyte(0xEC); - addbyte(0x28); - addbyte(0x48); /*MOVL RBP, &cpu_state*/ - addbyte(0xBD); - addquad(((uintptr_t)&cpu_state) + 128); - - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; - - codegen_block_cycles = 0; - codegen_timing_block_start(); - - codegen_block_ins = 0; - codegen_block_full_ins = 0; - - recomp_page = block->phys & ~0xfff; - - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; - - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; - - codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = - codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; - - block->was_recompiled = 1; - - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); -} - -void codegen_block_remove(void) -{ - codeblock_t *block = &codeblock[block_current]; - - delete_block(block); - - recomp_page = -1; -} - -void codegen_block_generate_end_mask(void) -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; - - block->endpc = codegen_endpc; - - block->page_mask = 0; - start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ block->endpc) & ~0x3ff) - end_pc = 0x3ff & ~15; - else - end_pc = (block->endpc & 0x3ff) & ~15; - if (end_pc < start_pc) - end_pc = 0x3ff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; - - for (; start_pc <= end_pc; start_pc++) - block->page_mask |= ((uint64_t)1 << start_pc); - - pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; - - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0x3ff) - { - block->phys_2 = get_phys_noabrt(block->endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - start_pc = 0; - end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); - page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - - if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) - mem_flush_write_page(block->phys_2, block->endpc); - - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (block->next_2->valid == 0) - fatal("block->next_2->valid=0 %p\n", (void *)block->next_2); - } - - block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - } - } - - recomp_page = -1; -} - -void codegen_block_end(void) -{ - codeblock_t *block = &codeblock[block_current]; - - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - - codegen_accumulate_flush(); - - addbyte(0x48); /*ADDL $40,%rsp*/ - addbyte(0x83); - addbyte(0xC4); - addbyte(0x28); - addbyte(0x41); /*POP R15*/ - addbyte(0x5f); - addbyte(0x41); /*POP R14*/ - addbyte(0x5e); - addbyte(0x41); /*POP R13*/ - addbyte(0x5d); - addbyte(0x41); /*POP R12*/ - addbyte(0x5c); - addbyte(0x5f); /*POP RDI*/ - addbyte(0x5e); /*POP RSI*/ - addbyte(0x5d); /*POP RBP*/ - addbyte(0x5b); /*POP RDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - remove_from_block_list(block, block->pc); - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_flush(void) +static void +remove_from_block_list(codeblock_t *block, uint32_t pc) { + if (!block->page_mask) return; -} -static int opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ -}; -int opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ -}; - -void codegen_debug(void) -{ -} - -static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - if (!cpu_mod && cpu_rm == 6) - { - addbyte(0xC7); /*MOVL $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } + if (block->prev) { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } else { + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; + if (block->next) + block->next->prev = NULL; else - { - int base_reg = 0, index_reg = 0; + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } - switch (cpu_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 (!(cpu_rm & 4)) - { - if (cpu_rm & 1) - index_reg = LOAD_REG_W(REG_DI); - else - index_reg = LOAD_REG_W(REG_SI); - } - base_reg &= 7; - index_reg &= 7; - - switch (cpu_mod) - { - case 0: - if (cpu_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 (cpu_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 (cpu_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 (cpu_mod || !(cpu_rm & 4)) - { - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - } - addbyte(0x89); /*MOV eaaddr, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; + if (block->prev_2) { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } else { + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } } -//#if 0 -static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) + +static void +delete_block(codeblock_t *block) { - uint32_t new_eaaddr; + uint32_t old_pc = block->pc; - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; - int base_reg = -1, index_reg = -1; + if (block == codeblock_hash[HASH(block->phys)]) + codeblock_hash[HASH(block->phys)] = NULL; + if (block->valid == 0) + fatal("Deleting deleted block\n"); + block->valid = 0; + + codeblock_tree_delete(block); + remove_from_block_list(block, old_pc); +} + +void +codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask) { + delete_block(block); + } + if (block == block->next) + fatal("Broken 1\n"); + block = block->next; + } + + block = page->block_2[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask2) { + delete_block(block); + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; + } +} + +void +codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; + + if (!page->block[(phys_addr >> 10) & 3]) + mem_flush_write_page(phys_addr, cs + cpu_state.pc); + + block_current = (block_current + 1) & BLOCK_MASK; + block = &codeblock[block_current]; + + if (block->valid != 0) { + delete_block(block); + } + block_num = HASH(phys_addr); + codeblock_hash[block_num] = &codeblock[block_current]; + + block->valid = 1; + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->pnt = block_current; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + block->page_mask = 0; + block->flags = 0; + block->status = cpu_cur_status; + + block->was_recompiled = 0; + + recomp_page = block->phys & ~0xfff; + + codeblock_tree_add(block); +} + +void +codegen_block_start_recompile(codeblock_t *block) +{ + page_t *page = &pages[block->phys >> 12]; + uintptr_t rip_rel; + + if (!page->block[(block->phys >> 10) & 3]) + mem_flush_write_page(block->phys, cs + cpu_state.pc); + + block_num = HASH(block->phys); + block_current = block->pnt; + + if (block->pc != cs + cpu_state.pc || block->was_recompiled) + fatal("Recompile to used block!\n"); + + block->status = cpu_cur_status; + + block_pos = BLOCK_GPF_OFFSET; +# ifdef OLD_GPF +# if _WIN64 + addbyte(0x48); /*XOR RCX, RCX*/ + addbyte(0x31); + addbyte(0xc9); + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); +# else + addbyte(0x48); /*XOR RDI, RDI*/ + addbyte(0x31); + addbyte(0xff); + addbyte(0x31); /*XOR ESI, ESI*/ + addbyte(0xf6); +# endif + call(block, (uintptr_t) x86gpf); + while (block_pos < BLOCK_EXIT_OFFSET) + addbyte(0x90); /*NOP*/ +# else + addbyte(0xC6); /*MOVB ABRT_GPF,(abrt)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(ABRT_GPF); + addbyte(0x31); /* xor eax,eax */ + addbyte(0xc0); + addbyte(0x89); /*MOVB eax,(abrt_error)*/ + addbyte(0x85); + rip_rel = ((uintptr_t) &cpu_state) + 128; + rip_rel = ((uintptr_t) & (abrt_error)) - rip_rel; + addlong((uint32_t) rip_rel); +# endif + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x48); /*ADDL $40,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x28); + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5d); /*POP RBP*/ + addbyte(0x5b); /*POP RDX*/ + addbyte(0xC3); /*RET*/ + cpu_block_end = 0; + block_pos = 0; /*Entry code*/ + addbyte(0x53); /*PUSH RBX*/ + addbyte(0x55); /*PUSH RBP*/ + addbyte(0x56); /*PUSH RSI*/ + addbyte(0x57); /*PUSH RDI*/ + addbyte(0x41); /*PUSH R12*/ + addbyte(0x54); + addbyte(0x41); /*PUSH R13*/ + addbyte(0x55); + addbyte(0x41); /*PUSH R14*/ + addbyte(0x56); + addbyte(0x41); /*PUSH R15*/ + addbyte(0x57); + addbyte(0x48); /*SUBL $40,%rsp*/ + addbyte(0x83); + addbyte(0xEC); + addbyte(0x28); + addbyte(0x48); /*MOVL RBP, &cpu_state*/ + addbyte(0xBD); + addquad(((uintptr_t) &cpu_state) + 128); + + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; + + codegen_block_cycles = 0; + codegen_timing_block_start(); + + codegen_block_ins = 0; + codegen_block_full_ins = 0; + + recomp_page = block->phys & ~0xfff; + + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; + + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + + codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; + + block->was_recompiled = 1; + + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); +} + +void +codegen_block_remove(void) +{ + codeblock_t *block = &codeblock[block_current]; + + delete_block(block); + + recomp_page = -1; +} + +void +codegen_block_generate_end_mask(void) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + + block->endpc = codegen_endpc; + + block->page_mask = 0; + start_pc = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; + + for (; start_pc <= end_pc; start_pc++) + block->page_mask |= ((uint64_t) 1 << start_pc); + + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0x3ff) { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; + + start_pc = 0; + end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t) 1 << start_pc); + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; + + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) + mem_flush_write_page(block->phys_2, block->endpc); + + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (block->next_2->valid == 0) + fatal("block->next_2->valid=0 %p\n", (void *) block->next_2); + } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + } + } + + recomp_page = -1; +} + +void +codegen_block_end(void) +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void +codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + + codegen_accumulate_flush(); + + addbyte(0x48); /*ADDL $40,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x28); + addbyte(0x41); /*POP R15*/ + addbyte(0x5f); + addbyte(0x41); /*POP R14*/ + addbyte(0x5e); + addbyte(0x41); /*POP R13*/ + addbyte(0x5d); + addbyte(0x41); /*POP R12*/ + addbyte(0x5c); + addbyte(0x5f); /*POP RDI*/ + addbyte(0x5e); /*POP RSI*/ + addbyte(0x5d); /*POP RBP*/ + addbyte(0x5b); /*POP RDX*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); + + remove_from_block_list(block, block->pc); + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void +codegen_flush(void) +{ + return; +} + +static int opcode_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; +int opcode_0f_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; + +void +codegen_debug(void) +{ +} + +static x86seg * +codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + if (!cpu_mod && cpu_rm == 6) { + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + int base_reg = 0, index_reg = 0; + + switch (cpu_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 (!(cpu_rm & 4)) { + if (cpu_rm & 1) + index_reg = LOAD_REG_W(REG_DI); + else + index_reg = LOAD_REG_W(REG_SI); + } + base_reg &= 7; + index_reg &= 7; + + switch (cpu_mod) { + case 0: + if (cpu_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 (cpu_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)++; - - if (cpu_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 (cpu_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; - } + break; + case 2: + if (cpu_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); } - else - { - switch (cpu_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 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - - addbyte(0x89); /*MOV eaaddr, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); + (*op_pc) += 2; + break; } - else - { - int base_reg; + if (cpu_mod || !(cpu_rm & 4)) { + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + } + addbyte(0x89); /*MOV eaaddr, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); - if (!cpu_mod && cpu_rm == 5) - { + if (mod1seg[cpu_rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; +} +// #if 0 +static x86seg * +codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + uint32_t new_eaaddr; + + if (cpu_rm == 4) { + uint8_t sib = fetchdat >> 8; + int base_reg = -1, index_reg = -1; + + (*op_pc)++; + + if (cpu_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 (cpu_mod) { + case 0: + if ((sib & 7) == 5) { new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); + addbyte(0xb8); /*MOV EAX, imm32*/ addlong(new_eaaddr); (*op_pc) += 4; - return op_ea_seg; - } - base_reg = LOAD_REG_L(cpu_rm) & 7; - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_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; - } - addbyte(0x89); /*MOV eaaddr, EAX*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - } - else - { - addbyte(0x44); /*MOV eaaddr, base_reg*/ + } else { + addbyte(0x44); /*MOV EAX, base_reg*/ addbyte(0x89); - addbyte(0x45 | (base_reg << 3)); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - } + 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 (cpu_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; + } } - return op_ea_seg; -} -//#endif -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t op_32 = use32; - uint32_t op_pc = new_pc; - const OpFn *op_table = (OpFn *) x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - int over = 0; - int pc_off = 0; - int test_modrm = 1; - int c; - - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 0; - op_old_pc = old_pc; - - for (c = 0; c < NR_HOST_REGS; c++) - host_reg_mapping[c] = -1; - for (c = 0; c < NR_HOST_XMM_REGS; c++) - host_reg_xmm_mapping[c] = -1; - - codegen_timing_start(); - - while (!over) + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ { - switch (opcode) - { - case 0x0f: - op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; - - case 0x26: /*ES:*/ - op_ea_seg = &cpu_state.seg_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &cpu_state.seg_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &cpu_state.seg_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &cpu_state.seg_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &cpu_state.seg_gs; - op_ssegs = 1; - break; - - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; - - case 0xd8: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - - case 0xf0: /*LOCK*/ - break; - - case 0xf2: /*REPNE*/ - op_table = x86_dynarec_opcodes_REPNE; - recomp_op_table = recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ - op_table = x86_dynarec_opcodes_REPE; - recomp_op_table = recomp_opcodes_REPE; - break; - - default: - goto generate_call; - } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - op_pc++; + addbyte(0x05); + addlong(stack_offset); } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + + addbyte(0x89); /*MOV eaaddr, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + } else { + int base_reg; + + if (!cpu_mod && cpu_rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + base_reg = LOAD_REG_L(cpu_rm) & 7; + if (cpu_mod) { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_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; + } + addbyte(0x89); /*MOV eaaddr, EAX*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + } else { + addbyte(0x44); /*MOV eaaddr, base_reg*/ + addbyte(0x89); + addbyte(0x45 | (base_reg << 3)); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + } + } + return op_ea_seg; +} +// #endif +void +codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t op_32 = use32; + uint32_t op_pc = new_pc; + const OpFn *op_table = (OpFn *) x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + int over = 0; + int pc_off = 0; + int test_modrm = 1; + int c; + + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; + op_old_pc = old_pc; + + for (c = 0; c < NR_HOST_REGS; c++) + host_reg_mapping[c] = -1; + for (c = 0; c < NR_HOST_XMM_REGS; c++) + host_reg_xmm_mapping[c] = -1; + + codegen_timing_start(); + + while (!over) { + switch (opcode) { + case 0x0f: + op_table = x86_dynarec_opcodes_0f; + recomp_op_table = recomp_opcodes_0f; + over = 1; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.seg_gs; + op_ssegs = 1; + break; + + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; + + case 0xd8: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + + case 0xf0: /*LOCK*/ + break; + + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = recomp_opcodes_REPE; + break; + + default: + goto generate_call; + } + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + op_pc++; + } generate_call: - codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - codegen_block_cycles = 0; + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with - subsequent instructions, so no cycles may have been deducted for it yet. - To prevent having zero cycle blocks (eg with a jump instruction pointing - to itself), apply the cycles that would be taken if this jump is taken, - then reverse it for subsequent instructions if the jump is not taken*/ - int jump_cycles = 0; + if ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = 0; - if (codegen_timing_jump_cycles != NULL) - jump_cycles = codegen_timing_jump_cycles(); - - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, -jump_cycles); - codegen_accumulate_flush(); - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, jump_cycles); - } - - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; - } - - if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); - if (new_pc) - { - if (new_pc != -1) - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, new_pc); - - codegen_block_ins++; - block->ins++; - codegen_block_full_ins++; - codegen_endpc = (cs + cpu_state.pc) + 8; - -#ifdef CHECK_INT - /* Check for interrupts. */ - addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &pic_pending); - addbyte(0x01); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4])); -#endif - - return; - } - } - - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - if (op_ssegs != last_ssegs) - { - last_ssegs = op_ssegs; - addbyte(0xC6); /*MOVB $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ssegs)); - addbyte(op_ssegs); - } - if ((!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]))/* && !(op_32 & 0x200)*/) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(rm_data.rm_mod_reg_data)); - addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); - if (cpu_mod != 3 && (op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - op_pc -= pc_off; - } - if (op_ea_seg != last_ea_seg) - { - addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ea_seg)); - addlong((uint32_t)(uintptr_t)op_ea_seg); - } + if (codegen_timing_jump_cycles != NULL) + jump_cycles = codegen_timing_jump_cycles(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, -jump_cycles); codegen_accumulate_flush(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, jump_cycles); + } - addbyte(0xC7); /*MOVL [pc],new_pc*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); - addlong(op_pc + pc_off); - addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(old_pc); - if (op_32 != last_op32) - { - last_op32 = op_32; - addbyte(0xC7); /*MOVL $use32,(op32)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(op32)); - addlong(op_32); + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); + if (new_pc) { + if (new_pc != -1) + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, new_pc); + + codegen_block_ins++; + block->ins++; + codegen_block_full_ins++; + codegen_endpc = (cs + cpu_state.pc) + 8; + +# ifdef CHECK_INT + /* Check for interrupts. */ + addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &pic_pending); + addbyte(0x01); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) (uintptr_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (uintptr_t) (&block->data[block_pos + 4])); +# endif + + return; } + } - load_param_1_32(block, fetchdat); - call(block, (uintptr_t)op); + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (op_ssegs != last_ssegs) { + last_ssegs = op_ssegs; + addbyte(0xC6); /*MOVB $0,(ssegs)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ssegs)); + addbyte(op_ssegs); + } + if ((!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) /* && !(op_32 & 0x200)*/) { + int stack_offset = 0; - codegen_block_ins++; + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; - block->ins++; + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; -#ifdef CHECK_INT - /* Check for interrupts. */ - addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t) (uintptr_t) &pic_pending); -#endif + addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(rm_data.rm_mod_reg_data)); + addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - addbyte(0x85); /*OR %eax, %eax*/ - addbyte(0xc0); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4])); + op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); + if (cpu_mod != 3 && (op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); + op_pc -= pc_off; + } + if (op_ea_seg != last_ea_seg) { + addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ea_seg)); + addlong((uint32_t) (uintptr_t) op_ea_seg); + } - codegen_endpc = (cs + cpu_state.pc) + 8; + codegen_accumulate_flush(); + + addbyte(0xC7); /*MOVL [pc],new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); + addlong(op_pc + pc_off); + addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(old_pc); + if (op_32 != last_op32) { + last_op32 = op_32; + addbyte(0xC7); /*MOVL $use32,(op32)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(op32)); + addlong(op_32); + } + + load_param_1_32(block, fetchdat); + call(block, (uintptr_t) op); + + codegen_block_ins++; + + block->ins++; + +# ifdef CHECK_INT + /* Check for interrupts. */ + addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t) (uintptr_t) &pic_pending); +# endif + + addbyte(0x85); /*OR %eax, %eax*/ + addbyte(0xc0); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) (uintptr_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (uintptr_t) (&block->data[block_pos + 4])); + + codegen_endpc = (cs + cpu_state.pc) + 8; } #endif diff --git a/src/codegen/codegen_x86-64.h b/src/codegen/codegen_x86-64.h index 1ef81ff89..91c10a9ee 100644 --- a/src/codegen/codegen_x86-64.h +++ b/src/codegen/codegen_x86-64.h @@ -1,24 +1,23 @@ -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) #define BLOCK_EXIT_OFFSET 0x7e0 #ifdef OLD_GPF -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) #else -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12) #endif #define BLOCK_MAX 1620 -enum -{ - OP_RET = 0xc3 +enum { + OP_RET = 0xc3 }; #define NR_HOST_REGS 4 diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index fe4703ea7..61b473fe7 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -38,2139 +38,2127 @@ */ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> -#include "x86.h" -#include "x86_flags.h" -#include "x86_ops.h" -#include "x87.h" +# include +# include +# include +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> +# include "x86.h" +# include "x86_flags.h" +# include "x86_ops.h" +# include "x87.h" /*ex*/ -#include <86box/nmi.h> -#include <86box/pic.h> +# include <86box/nmi.h> +# include <86box/pic.h> -#include "386_common.h" +# include "386_common.h" -#include "codegen.h" -#include "codegen_accumulate.h" -#include "codegen_ops.h" -#include "codegen_ops_x86.h" +# include "codegen.h" +# include "codegen_accumulate.h" +# include "codegen_ops.h" +# include "codegen_ops_x86.h" -#ifdef __unix__ -#include -#include -#endif -#if defined _WIN32 -#include -#endif +# ifdef __unix__ +# include +# include +# endif +# if defined _WIN32 +# include +# endif -int codegen_flat_ds, codegen_flat_ss; -int mmx_ebx_ecx_loaded; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_mmx_entered = 0; -int codegen_fpu_loaded_iq[8]; -x86seg *op_ea_seg; -int op_ssegs; +int codegen_flat_ds, codegen_flat_ss; +int mmx_ebx_ecx_loaded; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_mmx_entered = 0; +int codegen_fpu_loaded_iq[8]; +x86seg *op_ea_seg; +int op_ssegs; uint32_t op_old_pc; uint32_t recomp_page = -1; -int host_reg_mapping[NR_HOST_REGS]; -int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; -codeblock_t *codeblock; +int host_reg_mapping[NR_HOST_REGS]; +int host_reg_xmm_mapping[NR_HOST_XMM_REGS]; +codeblock_t *codeblock; codeblock_t **codeblock_hash; - -int block_current = 0; +int block_current = 0; static int block_num; -int block_pos; +int block_pos; uint32_t codegen_endpc; -int codegen_block_cycles; +int codegen_block_cycles; static int codegen_block_ins; static int codegen_block_full_ins; static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; +static x86seg *last_ea_seg; +static int last_ssegs; static uint32_t mem_abrt_rout; -uint32_t mem_load_addr_ea_b; -uint32_t mem_load_addr_ea_w; -uint32_t mem_load_addr_ea_l; -uint32_t mem_load_addr_ea_q; -uint32_t mem_store_addr_ea_b; -uint32_t mem_store_addr_ea_w; -uint32_t mem_store_addr_ea_l; -uint32_t mem_store_addr_ea_q; -uint32_t mem_load_addr_ea_b_no_abrt; -uint32_t mem_store_addr_ea_b_no_abrt; -uint32_t mem_load_addr_ea_w_no_abrt; -uint32_t mem_store_addr_ea_w_no_abrt; -uint32_t mem_load_addr_ea_l_no_abrt; -uint32_t mem_store_addr_ea_l_no_abrt; -uint32_t mem_check_write; -uint32_t mem_check_write_w; -uint32_t mem_check_write_l; +uint32_t mem_load_addr_ea_b; +uint32_t mem_load_addr_ea_w; +uint32_t mem_load_addr_ea_l; +uint32_t mem_load_addr_ea_q; +uint32_t mem_store_addr_ea_b; +uint32_t mem_store_addr_ea_w; +uint32_t mem_store_addr_ea_l; +uint32_t mem_store_addr_ea_q; +uint32_t mem_load_addr_ea_b_no_abrt; +uint32_t mem_store_addr_ea_b_no_abrt; +uint32_t mem_load_addr_ea_w_no_abrt; +uint32_t mem_store_addr_ea_w_no_abrt; +uint32_t mem_load_addr_ea_l_no_abrt; +uint32_t mem_store_addr_ea_l_no_abrt; +uint32_t mem_check_write; +uint32_t mem_check_write_w; +uint32_t mem_check_write_l; -static uint32_t gen_MEM_LOAD_ADDR_EA_B(void) +static uint32_t +gen_MEM_LOAD_ADDR_EA_B(void) { - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX EAX, B[EDX+EDI]*/ - addbyte(0xb6); - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmembl*/ - addlong((uint32_t)readmembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*MOVZX EAX, AL*/ - addbyte(0xb6); - addbyte(0xc0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_LOAD_ADDR_EA_W(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/ - addbyte(0xb7); - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemwl*/ - addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x0f); /*MOVZX EAX, AX*/ - addbyte(0xb7); - addbyte(0xc0); - addbyte(0x0f); /*JNE mem_abrt_rout*/ - addbyte(0x85); - addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_LOAD_ADDR_EA_L(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ - addbyte(0x04); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemll*/ - addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_LOAD_ADDR_EA_Q(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 7*/ - addbyte(0xc7); - addlong(7); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+4+1); - addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ - addbyte(0x04); - addbyte(0x3a); - addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/ - addbyte(0x54); - addbyte(0x3a); - addbyte(4); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemql*/ - addlong((uint32_t)readmemql - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_B(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x88); /*MOV [EDI+ESI],CL*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writemembl*/ - addlong((uint32_t)writemembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_W(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - 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); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x66); /*MOV [EDI+ESI],CX*/ - addbyte(0x89); - addbyte(0x04 | (REG_CX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememwl*/ - addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_L(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - 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); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x89); /*MOV [EDI+ESI],ECX*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememll*/ - addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_STORE_ADDR_EA_Q(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = EBX/ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EDX, ESI*/ - addbyte(0xf2); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - 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); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+4+1); - addbyte(0x89); /*MOV [EDI+ESI],EBX*/ - addbyte(0x04 | (REG_EBX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/ - addbyte(0x44 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(4); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x01); /*ADD EDX,EAX*/ - addbyte(0xC2); - addbyte(0x52); /*PUSH EDX*/ - addbyte(0xe8); /*CALL writememql*/ - addlong((uint32_t)writememql - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 12*/ - addbyte(0xc4); - addbyte(12); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_B_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX ECX, B[EDX+EDI]*/ - addbyte(0xb6); - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmembl*/ - addlong((uint32_t)readmembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); -#endif - addbyte(0x0f); /*MOVZX ECX, AL*/ - addbyte(0xb6); - addbyte(0xc8); -#ifndef RELEASE_BUILD - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_W_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 1*/ - addbyte(0xc7); - addlong(1); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/ - addbyte(0xb7); - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemwl*/ - addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); -#endif - addbyte(0x0f); /*MOVZX ECX, AX*/ - addbyte(0xb7); - addbyte(0xc8); -#ifndef RELEASE_BUILD - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_L_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - addbyte(0x89); /*MOV ESI, EDX*/ - addbyte(0xd6); - addbyte(0x01); /*ADDL EDX, EAX*/ - addbyte(0xc2); - addbyte(0x89); /*MOV EDI, EDX*/ - addbyte(0xd7); - addbyte(0xc1); /*SHR EDX, 12*/ - addbyte(0xea); - addbyte(12); - addbyte(0xf7); /*TEST EDI, 3*/ - addbyte(0xc7); - addlong(3); - addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ - addbyte(0x14); - addbyte(0x95); - addlong((uint32_t)readlookup2); - addbyte(0x75); /*JE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP EDX, -1*/ - addbyte(0xfa); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/ - addbyte(0x0c); - addbyte(0x3a); - addbyte(0xc3); /*RET*/ - - addbyte(0x01); /*slowpath: ADD ESI,EAX*/ - addbyte(0xc6); - addbyte(0x56); /*PUSH ESI*/ - addbyte(0xe8); /*CALL readmemll*/ - addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x89); /*MOV ECX, EAX*/ - addbyte(0xc1); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0x83); /*SUBL 4,%esp*/ - addbyte(0xEC); - addbyte(4); - addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_B_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - addbyte(0x89); /*MOV EDI, ESI*/ - addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xe8 | REG_ESI); - addbyte(12); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x88); /*MOV [EDI+ESI],CL*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xc3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writemembl*/ - addlong((uint32_t)writemembl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_W_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - 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); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+4+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(4+1); - addbyte(0x66); /*MOV [EDI+ESI],CX*/ - addbyte(0x89); - addbyte(0x04 | (REG_CX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememwl*/ - addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -#ifndef RELEASE_BUILD -static char gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_L_NO_ABRT aborted\n"; -#endif -static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*dat = ECX, seg = ESI, addr = EAX*/ - addbyte(0x89); /*MOV EBX, ESI*/ - addbyte(0xf3); - addbyte(0x01); /*ADDL ESI, EAX*/ - addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); - 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); - addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ - addbyte(0x04 | (REG_ESI << 3)); - addbyte(0x85 | (REG_ESI << 3)); - addlong((uint32_t)writelookup2); - addbyte(0x75); /*JNE slowpath*/ - addbyte(3+2+3+1); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xf8 | REG_ESI); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(3+1); - addbyte(0x89); /*MOV [EDI+ESI],ECX*/ - addbyte(0x04 | (REG_ECX << 3)); - addbyte(REG_EDI | (REG_ESI << 3)); - addbyte(0xc3); /*RET*/ - - addbyte(0x51); /*slowpath: PUSH ECX*/ - addbyte(0x01); /*ADD EBX,EAX*/ - addbyte(0xC3); - addbyte(0x53); /*PUSH EBX*/ - addbyte(0xe8); /*CALL writememll*/ - addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); -#ifndef RELEASE_BUILD - addbyte(0x80); /*CMP abrt, 0*/ - addbyte(0x7d); - addbyte((uint8_t)cpu_state_offset(abrt)); - addbyte(0); - addbyte(0x75); /*JNE mem_abrt_rout*/ - addbyte(1); -#endif - addbyte(0xc3); /*RET*/ -#ifndef RELEASE_BUILD - addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err*/ - addbyte(0x04); - addbyte(0x24); - addlong((uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err); - addbyte(0xe8); /*CALL fatal*/ - addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - /*Should not return!*/ -#endif - return addr; -} - -static uint32_t gen_MEM_CHECK_WRITE(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal32*/ - addlong((uint32_t)mmutranslatereal32 - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x83); /*ADD ESP, 8*/ - addbyte(0xc4); - addbyte(8); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_CHECK_WRITE_W(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x8d); /*LEA ESI, 1[EDI]*/ - addbyte(0x77); - addbyte(0x01); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x89); /*MOV EAX, EDI*/ - addbyte(0xf8); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ - addbyte(0x3c); - addbyte(0xb5); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc7); - /*slowpath_lp:*/ - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal32*/ - addlong((uint32_t)mmutranslatereal32 - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x83); /*ADD EDI, 1*/ - addbyte(0xc7); - 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(mem_abrt_rout - ((uint32_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, EDI*/ - addbyte(0xc7); - addlong(0xfff); - addbyte(0x74); /*JE slowpath_lp*/ - addbyte(-33); - addbyte(0xc3); /*RET*/ - - return addr; -} - -static uint32_t gen_MEM_CHECK_WRITE_L(void) -{ - uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; - - /*seg = ESI, addr = EAX*/ - - addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ - addbyte(0x3c); - addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3d); - addlong((uint32_t)&cr0); - addbyte(0); - addbyte(0x78); /*JS +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - addbyte(0x83); /*CMP ESI, -1*/ - addbyte(0xfe); - addbyte(-1); - addbyte(0x8d); /*LEA ESI, 3[EDI]*/ - addbyte(0x77); - addbyte(0x03); - addbyte(0x74); /*JE slowpath*/ - addbyte(11); - addbyte(0x89); /*MOV EAX, EDI*/ - addbyte(0xf8); - addbyte(0xc1); /*SHR EDI, 12*/ - addbyte(0xef); - addbyte(12); - addbyte(0xc1); /*SHR ESI, 12*/ - addbyte(0xee); - addbyte(12); - addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ - addbyte(0x3c); - addbyte(0xbd); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(11); - addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ - addbyte(0x3c); - addbyte(0xb5); - addlong((uint32_t)writelookup2); - addbyte(-1); - addbyte(0x74); /*JE +*/ - addbyte(1); - addbyte(0xc3); /*RET*/ - - /*slowpath:*/ - addbyte(0x89); /*MOV EDI, EAX*/ - addbyte(0xc7); - /*slowpath_lp:*/ - addbyte(0x6a); /*PUSH 1*/ - addbyte(1); - addbyte(0x57); /*PUSH EDI*/ - addbyte(0xe8); /*CALL mmutranslatereal32*/ - addlong((uint32_t)mmutranslatereal32 - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x83); /*ADD ESP, 4*/ - addbyte(0xc4); - addbyte(4); - addbyte(0x83); /*ADD EDI, 3*/ - addbyte(0xc7); - 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(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4)); - /*If bits 2-11 of the address are now 0 then this crosses a page, so loop back*/ - addbyte(0xf7); /*TEST EDI, FFC*/ - addbyte(0xc7); - addlong(0xffc); - addbyte(0x74); /*JE slowpath_lp*/ - addbyte(-33); - addbyte(0xc3); /*RET*/ - - return addr; -} - -void codegen_init(void) -{ -#ifdef _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#elif defined __unix__ - codeblock = mmap(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, 0, 0); -#else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); -#endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - - memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - - block_current = BLOCK_SIZE; - block_pos = 0; - mem_abrt_rout = (uint32_t)&codeblock[block_current].data[block_pos]; - addbyte(0x83); /*ADDL $16+4,%esp*/ - addbyte(0xC4); - addbyte(0x10+4); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_l = (uint32_t)gen_MEM_LOAD_ADDR_EA_L(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_w = (uint32_t)gen_MEM_LOAD_ADDR_EA_W(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_b = (uint32_t)gen_MEM_LOAD_ADDR_EA_B(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_q = (uint32_t)gen_MEM_LOAD_ADDR_EA_Q(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_l = (uint32_t)gen_MEM_STORE_ADDR_EA_L(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_w = (uint32_t)gen_MEM_STORE_ADDR_EA_W(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_b = (uint32_t)gen_MEM_STORE_ADDR_EA_B(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_q = (uint32_t)gen_MEM_STORE_ADDR_EA_Q(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_b_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_b_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_w_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_w_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_load_addr_ea_l_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_store_addr_ea_l_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT(); - block_pos = (block_pos + 15) & ~15; - mem_check_write = (uint32_t)gen_MEM_CHECK_WRITE(); - block_pos = (block_pos + 15) & ~15; - mem_check_write_w = (uint32_t)gen_MEM_CHECK_WRITE_W(); - block_pos = (block_pos + 15) & ~15; - mem_check_write_l = (uint32_t)gen_MEM_CHECK_WRITE_L(); - -#ifndef _MSC_VER - asm( - "fstcw %0\n" - : "=m" (cpu_state.old_npxc) - ); -#else - __asm - { - fstcw cpu_state.old_npxc - } -#endif -} - -void codegen_reset(void) -{ - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - mem_reset_page_blocks(); -} - -void dump_block(void) -{ -} - -static void add_to_block_list(codeblock_t *block) -{ - codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; - - if (!block->page_mask) - fatal("add_to_block_list - mask = 0\n"); - - if (block_prev) - { - block->next = block_prev; - block_prev->prev = block; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - else - { - block->next = NULL; - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; - } - - if (block->next) - { - if (!block->next->valid) - fatal("block->next->valid=0 %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); - } - - if (block->page_mask2) - { - block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; - - if (block_prev) - { - block->next_2 = block_prev; - block_prev->prev_2 = block; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - else - { - block->next_2 = NULL; - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; - } - } -} - -static void remove_from_block_list(codeblock_t *block, uint32_t pc) -{ - if (!block->page_mask) - return; - - if (block->prev) - { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - else - { - pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; - if (block->next) - block->next->prev = NULL; - else - mem_flush_write_page(block->phys, 0); - } - if (!block->page_mask2) - { - if (block->prev_2 || block->next_2) - fatal("Invalid block_2\n"); - return; - } - - if (block->prev_2) - { - block->prev_2->next_2 = block->next_2; - if (block->next_2) - block->next_2->prev_2 = block->prev_2; - } - else - { - pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; - if (block->next_2) - block->next_2->prev_2 = NULL; - else - mem_flush_write_page(block->phys_2, 0); - } -} - -static void delete_block(codeblock_t *block) -{ - uint32_t old_pc = block->pc; - - if (block == codeblock_hash[HASH(block->phys)]) - codeblock_hash[HASH(block->phys)] = NULL; - - if (!block->valid) - fatal("Deleting deleted block\n"); - block->valid = 0; - - codeblock_tree_delete(block); - remove_from_block_list(block, old_pc); -} - -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) -{ - struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask) - { - delete_block(block); - } - if (block == block->next) - fatal("Broken 1\n"); - block = block->next; - } - - block = page->block_2[(phys_addr >> 10) & 3]; - - while (block) - { - if (mask & block->page_mask2) - { - delete_block(block); - } - if (block == block->next_2) - fatal("Broken 2\n"); - block = block->next_2; - } -} - -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block[(phys_addr >> 10) & 3]) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - - block_current = (block_current + 1) & BLOCK_MASK; - block = &codeblock[block_current]; - - if (block->valid != 0) - { - delete_block(block); - } - block_num = HASH(phys_addr); - codeblock_hash[block_num] = &codeblock[block_current]; - - block->valid = 1; - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->pnt = block_current; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - block->dirty_mask2 = NULL; - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - block->page_mask = 0; - block->flags = CODEBLOCK_STATIC_TOP; - block->status = cpu_cur_status; - - block->was_recompiled = 0; - - recomp_page = block->phys & ~0xfff; - - codeblock_tree_add(block); -} - -void codegen_block_start_recompile(codeblock_t *block) -{ - page_t *page = &pages[block->phys >> 12]; - - if (!page->block[(block->phys >> 10) & 3]) - mem_flush_write_page(block->phys, cs+cpu_state.pc); - - block_num = HASH(block->phys); - block_current = block->pnt; - - if (block->pc != cs + cpu_state.pc || block->was_recompiled) - fatal("Recompile to used block!\n"); - - block->status = cpu_cur_status; - - block_pos = BLOCK_GPF_OFFSET; -#ifdef OLD_GPF - addbyte(0xc7); /*MOV [ESP],0*/ - addbyte(0x04); - addbyte(0x24); - addlong(0); - addbyte(0xc7); /*MOV [ESP+4],0*/ - addbyte(0x44); - addbyte(0x24); - addbyte(0x04); - addlong(0); - addbyte(0xe8); /*CALL x86gpf*/ - addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); -#else - addbyte(0xc6); /* mov byte ptr[&(cpu_state.abrt)],ABRT_GPF */ - addbyte(0x05); - addlong((uint32_t) (uintptr_t) &(cpu_state.abrt)); - addbyte(ABRT_GPF); - addbyte(0x31); /* xor eax,eax */ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX EAX, B[EDX+EDI]*/ + addbyte(0xb6); + addbyte(0x04); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ + + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmembl*/ + addlong((uint32_t) readmembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*MOVZX EAX, AL*/ + addbyte(0xb6); addbyte(0xc0); - addbyte(0xa3); /* mov [&(abrt_error)],eax */ - addlong((uint32_t) (uintptr_t) &(abrt_error)); -#endif - block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $16,%esp*/ - addbyte(0xC4); - addbyte(0x10); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - cpu_block_end = 0; - block_pos = 0; /*Entry code*/ - addbyte(0x53); /*PUSH EBX*/ - addbyte(0x55); /*PUSH EBP*/ - addbyte(0x56); /*PUSH ESI*/ - addbyte(0x57); /*PUSH EDI*/ - addbyte(0x83); /*SUBL $16,%esp*/ - addbyte(0xEC); - addbyte(0x10); - addbyte(0xBD); /*MOVL EBP, &cpu_state*/ - addlong(((uintptr_t)&cpu_state) + 128); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; - - codegen_block_cycles = 0; - codegen_timing_block_start(); - - codegen_block_ins = 0; - codegen_block_full_ins = 0; - - recomp_page = block->phys & ~0xfff; - - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; - - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; - - block->TOP = cpu_state.TOP & 7; - block->was_recompiled = 1; - - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); - - codegen_accumulate_reset(); + return addr; } -void codegen_block_remove(void) +static uint32_t +gen_MEM_LOAD_ADDR_EA_W(void) { - codeblock_t *block = &codeblock[block_current]; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - delete_block(block); + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/ + addbyte(0xb7); + addbyte(0x04); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - recomp_page = -1; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemwl*/ + addlong((uint32_t) readmemwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x0f); /*MOVZX EAX, AX*/ + addbyte(0xb7); + addbyte(0xc0); + addbyte(0x0f); /*JNE mem_abrt_rout*/ + addbyte(0x85); + addlong(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; } -void codegen_block_generate_end_mask(void) +static uint32_t +gen_MEM_LOAD_ADDR_EA_L(void) { - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; - block->endpc = codegen_endpc; + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ + addbyte(0x04); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ - block->page_mask = 0; - start_pc = (block->pc & 0x3ff) & ~15; - if ((block->pc ^ block->endpc) & ~0x3ff) - end_pc = 0x3ff & ~15; - else - end_pc = (block->endpc & 0x3ff) & ~15; - if (end_pc < start_pc) - end_pc = 0x3ff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemll*/ + addlong((uint32_t) readmemll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ - for (; start_pc <= end_pc; start_pc++) - { - block->page_mask |= ((uint64_t)1 << start_pc); + return addr; +} + +static uint32_t +gen_MEM_LOAD_ADDR_EA_Q(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 7*/ + addbyte(0xc7); + addlong(7); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 4 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 4 + 1); + addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ + addbyte(0x04); + addbyte(0x3a); + addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/ + addbyte(0x54); + addbyte(0x3a); + addbyte(4); + addbyte(0xc3); /*RET*/ + + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemql*/ + addlong((uint32_t) readmemql - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; +} + +static uint32_t +gen_MEM_STORE_ADDR_EA_B(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x88); /*MOV [EDI+ESI],CL*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writemembl*/ + addlong((uint32_t) writemembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; +} + +static uint32_t +gen_MEM_STORE_ADDR_EA_W(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + 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); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x66); /*MOV [EDI+ESI],CX*/ + addbyte(0x89); + addbyte(0x04 | (REG_CX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememwl*/ + addlong((uint32_t) writememwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; +} + +static uint32_t +gen_MEM_STORE_ADDR_EA_L(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + 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); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x89); /*MOV [EDI+ESI],ECX*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememll*/ + addlong((uint32_t) writememll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; +} + +static uint32_t +gen_MEM_STORE_ADDR_EA_Q(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = EBX/ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EDX, ESI*/ + addbyte(0xf2); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + 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); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 4 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 4 + 1); + addbyte(0x89); /*MOV [EDI+ESI],EBX*/ + addbyte(0x04 | (REG_EBX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/ + addbyte(0x44 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(4); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x53); /*PUSH EBX*/ + addbyte(0x01); /*ADD EDX,EAX*/ + addbyte(0xC2); + addbyte(0x52); /*PUSH EDX*/ + addbyte(0xe8); /*CALL writememql*/ + addlong((uint32_t) writememql - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 12*/ + addbyte(0xc4); + addbyte(12); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; +} + +# ifndef RELEASE_BUILD +static char gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_B_NO_ABRT aborted\n"; +# endif +static uint32_t +gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX ECX, B[EDX+EDI]*/ + addbyte(0xb6); + addbyte(0x0c); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ + + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmembl*/ + addlong((uint32_t) readmembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); +# endif + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); +# ifndef RELEASE_BUILD + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; +} + +# ifndef RELEASE_BUILD +static char gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_W_NO_ABRT aborted\n"; +# endif +static uint32_t +gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 1*/ + addbyte(0xc7); + addlong(1); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/ + addbyte(0xb7); + addbyte(0x0c); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ + + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemwl*/ + addlong((uint32_t) readmemwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); +# endif + addbyte(0x0f); /*MOVZX ECX, AX*/ + addbyte(0xb7); + addbyte(0xc8); +# ifndef RELEASE_BUILD + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; +} + +# ifndef RELEASE_BUILD +static char gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_L_NO_ABRT aborted\n"; +# endif +static uint32_t +gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 3*/ + addbyte(0xc7); + addlong(3); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t) readlookup2); + addbyte(0x75); /*JE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/ + addbyte(0x0c); + addbyte(0x3a); + addbyte(0xc3); /*RET*/ + + addbyte(0x01); /*slowpath: ADD ESI,EAX*/ + addbyte(0xc6); + addbyte(0x56); /*PUSH ESI*/ + addbyte(0xe8); /*CALL readmemll*/ + addlong((uint32_t) readmemll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc1); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0x83); /*SUBL 4,%esp*/ + addbyte(0xEC); + addbyte(4); + addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; +} + +# ifndef RELEASE_BUILD +static char gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_B_NO_ABRT aborted\n"; +# endif +static uint32_t +gen_MEM_STORE_ADDR_EA_B_NO_ABRT(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x88); /*MOV [EDI+ESI],CL*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xc3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writemembl*/ + addlong((uint32_t) writemembl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; +} + +# ifndef RELEASE_BUILD +static char gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_W_NO_ABRT aborted\n"; +# endif +static uint32_t +gen_MEM_STORE_ADDR_EA_W_NO_ABRT(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + 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); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 4 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4 + 1); + addbyte(0x66); /*MOV [EDI+ESI],CX*/ + addbyte(0x89); + addbyte(0x04 | (REG_CX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememwl*/ + addlong((uint32_t) writememwl - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; +} + +# ifndef RELEASE_BUILD +static char gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_L_NO_ABRT aborted\n"; +# endif +static uint32_t +gen_MEM_STORE_ADDR_EA_L_NO_ABRT(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*dat = ECX, seg = ESI, addr = EAX*/ + addbyte(0x89); /*MOV EBX, ESI*/ + addbyte(0xf3); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + 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); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t) writelookup2); + addbyte(0x75); /*JNE slowpath*/ + addbyte(3 + 2 + 3 + 1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3 + 1); + addbyte(0x89); /*MOV [EDI+ESI],ECX*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xc3); /*RET*/ + + addbyte(0x51); /*slowpath: PUSH ECX*/ + addbyte(0x01); /*ADD EBX,EAX*/ + addbyte(0xC3); + addbyte(0x53); /*PUSH EBX*/ + addbyte(0xe8); /*CALL writememll*/ + addlong((uint32_t) writememll - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); +# ifndef RELEASE_BUILD + addbyte(0x80); /*CMP abrt, 0*/ + addbyte(0x7d); + addbyte((uint8_t) cpu_state_offset(abrt)); + addbyte(0); + addbyte(0x75); /*JNE mem_abrt_rout*/ + addbyte(1); +# endif + addbyte(0xc3); /*RET*/ +# ifndef RELEASE_BUILD + addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err*/ + addbyte(0x04); + addbyte(0x24); + addlong((uint32_t) gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err); + addbyte(0xe8); /*CALL fatal*/ + addlong((uint32_t) fatal - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + /*Should not return!*/ +# endif + return addr; +} + +static uint32_t +gen_MEM_CHECK_WRITE(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*seg = ESI, addr = EAX*/ + + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3d); + addlong((uint32_t) &cr0); + addbyte(0); + addbyte(0x78); /*JS +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(11); + addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ + addbyte(0x3c); + addbyte(0xbd); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + + /*slowpath:*/ + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x6a); /*PUSH 1*/ + addbyte(1); + addbyte(0x57); /*PUSH EDI*/ + addbyte(0xe8); /*CALL mmutranslatereal32*/ + addlong((uint32_t) mmutranslatereal32 - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*ADD ESP, 8*/ + addbyte(0xc4); + addbyte(8); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + addbyte(0xc3); /*RET*/ + + return addr; +} + +static uint32_t +gen_MEM_CHECK_WRITE_W(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*seg = ESI, addr = EAX*/ + + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3d); + addlong((uint32_t) &cr0); + addbyte(0); + addbyte(0x78); /*JS +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + addbyte(0x8d); /*LEA ESI, 1[EDI]*/ + addbyte(0x77); + addbyte(0x01); + addbyte(0x74); /*JE slowpath*/ + addbyte(11); + addbyte(0x89); /*MOV EAX, EDI*/ + addbyte(0xf8); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xee); + addbyte(12); + addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ + addbyte(0x3c); + addbyte(0xbd); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(11); + addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ + addbyte(0x3c); + addbyte(0xb5); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + + /*slowpath:*/ + addbyte(0x89); /*MOV EDI, EAX*/ + addbyte(0xc7); + /*slowpath_lp:*/ + addbyte(0x6a); /*PUSH 1*/ + addbyte(1); + addbyte(0x57); /*PUSH EDI*/ + addbyte(0xe8); /*CALL mmutranslatereal32*/ + addlong((uint32_t) mmutranslatereal32 - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x83); /*ADD EDI, 1*/ + addbyte(0xc7); + 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(mem_abrt_rout - ((uint32_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, EDI*/ + addbyte(0xc7); + addlong(0xfff); + addbyte(0x74); /*JE slowpath_lp*/ + addbyte(-33); + addbyte(0xc3); /*RET*/ + + return addr; +} + +static uint32_t +gen_MEM_CHECK_WRITE_L(void) +{ + uint32_t addr = (uint32_t) &codeblock[block_current].data[block_pos]; + + /*seg = ESI, addr = EAX*/ + + addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/ + addbyte(0x3c); + addbyte(0x30); + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3d); + addlong((uint32_t) &cr0); + addbyte(0); + addbyte(0x78); /*JS +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xfe); + addbyte(-1); + addbyte(0x8d); /*LEA ESI, 3[EDI]*/ + addbyte(0x77); + addbyte(0x03); + addbyte(0x74); /*JE slowpath*/ + addbyte(11); + addbyte(0x89); /*MOV EAX, EDI*/ + addbyte(0xf8); + addbyte(0xc1); /*SHR EDI, 12*/ + addbyte(0xef); + addbyte(12); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xee); + addbyte(12); + addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/ + addbyte(0x3c); + addbyte(0xbd); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(11); + addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/ + addbyte(0x3c); + addbyte(0xb5); + addlong((uint32_t) writelookup2); + addbyte(-1); + addbyte(0x74); /*JE +*/ + addbyte(1); + addbyte(0xc3); /*RET*/ + + /*slowpath:*/ + addbyte(0x89); /*MOV EDI, EAX*/ + addbyte(0xc7); + /*slowpath_lp:*/ + addbyte(0x6a); /*PUSH 1*/ + addbyte(1); + addbyte(0x57); /*PUSH EDI*/ + addbyte(0xe8); /*CALL mmutranslatereal32*/ + addlong((uint32_t) mmutranslatereal32 - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x83); /*ADD ESP, 4*/ + addbyte(0xc4); + addbyte(4); + addbyte(0x83); /*ADD EDI, 3*/ + addbyte(0xc7); + 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(mem_abrt_rout - ((uint32_t) (&codeblock[block_current].data[block_pos]) + 4)); + /*If bits 2-11 of the address are now 0 then this crosses a page, so loop back*/ + addbyte(0xf7); /*TEST EDI, FFC*/ + addbyte(0xc7); + addlong(0xffc); + addbyte(0x74); /*JE slowpath_lp*/ + addbyte(-33); + addbyte(0xc3); /*RET*/ + + return addr; +} + +void +codegen_init(void) +{ +# ifdef _WIN32 + codeblock = VirtualAlloc(NULL, (BLOCK_SIZE + 1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +# elif defined __unix__ + codeblock = mmap(NULL, (BLOCK_SIZE + 1) * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, 0, 0); +# else + codeblock = malloc((BLOCK_SIZE + 1) * sizeof(codeblock_t)); +# endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + + memset(codeblock, 0, (BLOCK_SIZE + 1) * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + + block_current = BLOCK_SIZE; + block_pos = 0; + mem_abrt_rout = (uint32_t) &codeblock[block_current].data[block_pos]; + addbyte(0x83); /*ADDL $16+4,%esp*/ + addbyte(0xC4); + addbyte(0x10 + 4); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_l = (uint32_t) gen_MEM_LOAD_ADDR_EA_L(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_w = (uint32_t) gen_MEM_LOAD_ADDR_EA_W(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_b = (uint32_t) gen_MEM_LOAD_ADDR_EA_B(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_q = (uint32_t) gen_MEM_LOAD_ADDR_EA_Q(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_l = (uint32_t) gen_MEM_STORE_ADDR_EA_L(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_w = (uint32_t) gen_MEM_STORE_ADDR_EA_W(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_b = (uint32_t) gen_MEM_STORE_ADDR_EA_B(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_q = (uint32_t) gen_MEM_STORE_ADDR_EA_Q(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_b_no_abrt = (uint32_t) gen_MEM_LOAD_ADDR_EA_B_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_b_no_abrt = (uint32_t) gen_MEM_STORE_ADDR_EA_B_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_w_no_abrt = (uint32_t) gen_MEM_LOAD_ADDR_EA_W_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_w_no_abrt = (uint32_t) gen_MEM_STORE_ADDR_EA_W_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_load_addr_ea_l_no_abrt = (uint32_t) gen_MEM_LOAD_ADDR_EA_L_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_store_addr_ea_l_no_abrt = (uint32_t) gen_MEM_STORE_ADDR_EA_L_NO_ABRT(); + block_pos = (block_pos + 15) & ~15; + mem_check_write = (uint32_t) gen_MEM_CHECK_WRITE(); + block_pos = (block_pos + 15) & ~15; + mem_check_write_w = (uint32_t) gen_MEM_CHECK_WRITE_W(); + block_pos = (block_pos + 15) & ~15; + mem_check_write_l = (uint32_t) gen_MEM_CHECK_WRITE_L(); + +# ifndef _MSC_VER + asm( + "fstcw %0\n" + : "=m"(cpu_state.old_npxc)); +# else + __asm + { + fstcw cpu_state.old_npxc + } +# endif +} + +void +codegen_reset(void) +{ + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + mem_reset_page_blocks(); +} + +void +dump_block(void) +{ +} + +static void +add_to_block_list(codeblock_t *block) +{ + codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3]; + + if (!block->page_mask) + fatal("add_to_block_list - mask = 0\n"); + + if (block_prev) { + block->next = block_prev; + block_prev->prev = block; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } else { + block->next = NULL; + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block; + } + + if (block->next) { + if (!block->next->valid) + fatal("block->next->valid=0 %p %p %x %x\n", (void *) block->next, (void *) codeblock, block_current, block_pos); + } + + if (block->page_mask2) { + block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]; + + if (block_prev) { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; + } else { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block; } - - pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; - - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = NULL; - if ((block->pc ^ block->endpc) & ~0x3ff) - { - block->phys_2 = get_phys_noabrt(block->endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - start_pc = 0; - end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); - page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; - - if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) - mem_flush_write_page(block->phys_2, block->endpc); - - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (!block->next_2->valid) - fatal("block->next_2->valid=0 %p\n", (void *)block->next_2); - } - - block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; - } - } - - recomp_page = -1; + } } -void codegen_block_end(void) -{ - codeblock_t *block = &codeblock[block_current]; - - codegen_block_generate_end_mask(); - add_to_block_list(block); -} - -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - - codegen_accumulate_flush(); - - addbyte(0x83); /*ADDL $16,%esp*/ - addbyte(0xC4); - addbyte(0x10); - addbyte(0x5f); /*POP EDI*/ - addbyte(0x5e); /*POP ESI*/ - addbyte(0x5d); /*POP EBP*/ - addbyte(0x5b); /*POP EDX*/ - addbyte(0xC3); /*RET*/ - - if (block_pos > BLOCK_GPF_OFFSET) - fatal("Over limit!\n"); - - remove_from_block_list(block, block->pc); - block->next = block->prev = NULL; - block->next_2 = block->prev_2 = NULL; - codegen_block_generate_end_mask(); - add_to_block_list(block); - - if (!(block->flags & CODEBLOCK_HAS_FPU)) - block->flags &= ~CODEBLOCK_STATIC_TOP; -} - -void codegen_flush(void) +static void +remove_from_block_list(codeblock_t *block, uint32_t pc) { + if (!block->page_mask) return; -} -static int opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ -}; -int opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ -}; - -void codegen_debug(void) -{ -} - -static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) -{ - if (!cpu_mod && cpu_rm == 6) - { - addbyte(0xC7); /*MOVL $0,(ssegs)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong((fetchdat >> 8) & 0xffff); - (*op_pc) += 2; - } + if (block->prev) { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } else { + pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next; + if (block->next) + block->next->prev = NULL; else - { - switch (cpu_mod) - { - case 0: - addbyte(0xa1); /*MOVL *mod1add[0][cpu_rm], %eax*/ - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - break; - case 1: - addbyte(0xb8); /*MOVL ,%eax*/ - addlong((uint32_t)(int8_t)(rmdat >> 8)); - addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - (*op_pc)++; - break; - case 2: - addbyte(0xb8); /*MOVL ,%eax*/ - addlong((fetchdat >> 8) & 0xffff); - addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[0][cpu_rm]); - addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ - addbyte(0x05); - addlong((uint32_t)mod1add[1][cpu_rm]); - (*op_pc) += 2; - break; - } - addbyte(0x25); /*ANDL $0xffff, %eax*/ - addlong(0xffff); - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - } - return op_ea_seg; + if (block->prev_2) { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } else { + pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } } -static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +static void +delete_block(codeblock_t *block) { - uint32_t new_eaaddr; + uint32_t old_pc = block->pc; - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; + if (block == codeblock_hash[HASH(block->phys)]) + codeblock_hash[HASH(block->phys)] = NULL; + + if (!block->valid) + fatal("Deleting deleted block\n"); + block->valid = 0; + + codeblock_tree_delete(block); + remove_from_block_list(block, old_pc); +} + +void +codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask) { + delete_block(block); + } + if (block == block->next) + fatal("Broken 1\n"); + block = block->next; + } + + block = page->block_2[(phys_addr >> 10) & 3]; + + while (block) { + if (mask & block->page_mask2) { + delete_block(block); + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; + } +} + +void +codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; + + if (!page->block[(phys_addr >> 10) & 3]) + mem_flush_write_page(phys_addr, cs + cpu_state.pc); + + block_current = (block_current + 1) & BLOCK_MASK; + block = &codeblock[block_current]; + + if (block->valid != 0) { + delete_block(block); + } + block_num = HASH(phys_addr); + codeblock_hash[block_num] = &codeblock[block_current]; + + block->valid = 1; + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->pnt = block_current; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + block->dirty_mask2 = NULL; + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + block->page_mask = 0; + block->flags = CODEBLOCK_STATIC_TOP; + block->status = cpu_cur_status; + + block->was_recompiled = 0; + + recomp_page = block->phys & ~0xfff; + + codeblock_tree_add(block); +} + +void +codegen_block_start_recompile(codeblock_t *block) +{ + page_t *page = &pages[block->phys >> 12]; + + if (!page->block[(block->phys >> 10) & 3]) + mem_flush_write_page(block->phys, cs + cpu_state.pc); + + block_num = HASH(block->phys); + block_current = block->pnt; + + if (block->pc != cs + cpu_state.pc || block->was_recompiled) + fatal("Recompile to used block!\n"); + + block->status = cpu_cur_status; + + block_pos = BLOCK_GPF_OFFSET; +# ifdef OLD_GPF + addbyte(0xc7); /*MOV [ESP],0*/ + addbyte(0x04); + addbyte(0x24); + addlong(0); + addbyte(0xc7); /*MOV [ESP+4],0*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addlong(0); + addbyte(0xe8); /*CALL x86gpf*/ + addlong((uint32_t) x86gpf - (uint32_t) (&codeblock[block_current].data[block_pos + 4])); +# else + addbyte(0xc6); /* mov byte ptr[&(cpu_state.abrt)],ABRT_GPF */ + addbyte(0x05); + addlong((uint32_t) (uintptr_t) & (cpu_state.abrt)); + addbyte(ABRT_GPF); + addbyte(0x31); /* xor eax,eax */ + addbyte(0xc0); + addbyte(0xa3); /* mov [&(abrt_error)],eax */ + addlong((uint32_t) (uintptr_t) & (abrt_error)); +# endif + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0xC4); + addbyte(0x10); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + cpu_block_end = 0; + block_pos = 0; /*Entry code*/ + addbyte(0x53); /*PUSH EBX*/ + addbyte(0x55); /*PUSH EBP*/ + addbyte(0x56); /*PUSH ESI*/ + addbyte(0x57); /*PUSH EDI*/ + addbyte(0x83); /*SUBL $16,%esp*/ + addbyte(0xEC); + addbyte(0x10); + addbyte(0xBD); /*MOVL EBP, &cpu_state*/ + addlong(((uintptr_t) &cpu_state) + 128); + + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; + + codegen_block_cycles = 0; + codegen_timing_block_start(); + + codegen_block_ins = 0; + codegen_block_full_ins = 0; + + recomp_page = block->phys & ~0xfff; + + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; + + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + + block->TOP = cpu_state.TOP & 7; + block->was_recompiled = 1; + + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); + + codegen_accumulate_reset(); +} + +void +codegen_block_remove(void) +{ + codeblock_t *block = &codeblock[block_current]; + + delete_block(block); + + recomp_page = -1; +} + +void +codegen_block_generate_end_mask(void) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + + block->endpc = codegen_endpc; + + block->page_mask = 0; + start_pc = (block->pc & 0x3ff) & ~15; + if ((block->pc ^ block->endpc) & ~0x3ff) + end_pc = 0x3ff & ~15; + else + end_pc = (block->endpc & 0x3ff) & ~15; + if (end_pc < start_pc) + end_pc = 0x3ff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; + + for (; start_pc <= end_pc; start_pc++) { + block->page_mask |= ((uint64_t) 1 << start_pc); + } + + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0x3ff) { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; + + start_pc = 0; + end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t) 1 << start_pc); + page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2; + + if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3]) + mem_flush_write_page(block->phys_2, block->endpc); + + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (!block->next_2->valid) + fatal("block->next_2->valid=0 %p\n", (void *) block->next_2); + } + + block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK]; + } + } + + recomp_page = -1; +} + +void +codegen_block_end(void) +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask(); + add_to_block_list(block); +} + +void +codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + + codegen_accumulate_flush(); + + addbyte(0x83); /*ADDL $16,%esp*/ + addbyte(0xC4); + addbyte(0x10); + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5d); /*POP EBP*/ + addbyte(0x5b); /*POP EDX*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); + + remove_from_block_list(block, block->pc); + block->next = block->prev = NULL; + block->next_2 = block->prev_2 = NULL; + codegen_block_generate_end_mask(); + add_to_block_list(block); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; +} + +void +codegen_flush(void) +{ + return; +} + +static int opcode_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; +int opcode_0f_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; + +void +codegen_debug(void) +{ +} + +static x86seg * +codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + if (!cpu_mod && cpu_rm == 6) { + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } else { + switch (cpu_mod) { + case 0: + addbyte(0xa1); /*MOVL *mod1add[0][cpu_rm], %eax*/ + addlong((uint32_t) mod1add[0][cpu_rm]); + addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][cpu_rm]); + break; + case 1: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((uint32_t) (int8_t) (rmdat >> 8)); + addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[0][cpu_rm]); + addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][cpu_rm]); (*op_pc)++; + break; + case 2: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((fetchdat >> 8) & 0xffff); + addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[0][cpu_rm]); + addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/ + addbyte(0x05); + addlong((uint32_t) mod1add[1][cpu_rm]); + (*op_pc) += 2; + break; + } + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + addbyte(0xa3); + addlong((uint32_t) &cpu_state.eaaddr); - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL ,%eax*/ - addlong(new_eaaddr); - (*op_pc) += 4; - } - else - { - addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - } - break; - case 1: - new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); - addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc)++; - break; - case 2: - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ - addlong(new_eaaddr); - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l)); - (*op_pc) += 4; - break; - } - if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - addbyte(0x05); - addlong(stack_offset); - } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); - break; - case 1: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - case 2: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0xC1); addbyte(0xE3); addbyte(2); /*SHL $2,%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - case 3: - addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ - addbyte(0xC1); addbyte(0xE3); addbyte(3); /*SHL $2,%ebx*/ - addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ - break; - } - } - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); - } - else - { - if (!cpu_mod && cpu_rm == 5) - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(eaaddr)); - addlong(new_eaaddr); - (*op_pc) += 4; - return op_ea_seg; - } - addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(regs[cpu_rm].l)); - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_mod == 1) - { - addbyte(0x05); - addlong((uint32_t)(int8_t)(fetchdat >> 8)); - (*op_pc)++; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - addbyte(0x05); - addlong(new_eaaddr); - (*op_pc) += 4; - } - } - addbyte(0xa3); - addlong((uint32_t)&cpu_state.eaaddr); - } - return op_ea_seg; + if (mod1seg[cpu_rm] == &ss && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + } + return op_ea_seg; } -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +static x86seg * +codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { - codeblock_t *block = &codeblock[block_current]; - uint32_t op_32 = use32; - uint32_t op_pc = new_pc; - const OpFn *op_table = x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - int over = 0; - int pc_off = 0; - int test_modrm = 1; - int c; + uint32_t new_eaaddr; - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 0; - op_old_pc = old_pc; + if (cpu_rm == 4) { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; - for (c = 0; c < NR_HOST_REGS; c++) - host_reg_mapping[c] = -1; - mmx_ebx_ecx_loaded = 0; - for (c = 0; c < NR_HOST_XMM_REGS; c++) - host_reg_xmm_mapping[c] = -1; - - codegen_timing_start(); - - while (!over) - { - switch (opcode) - { - case 0x0f: - op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; - - case 0x26: /*ES:*/ - op_ea_seg = &cpu_state.seg_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &cpu_state.seg_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &cpu_state.seg_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &cpu_state.seg_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &cpu_state.seg_gs; - op_ssegs = 1; - break; - - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; - - case 0xd8: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: - op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - - case 0xf0: /*LOCK*/ - break; - - case 0xf2: /*REPNE*/ - op_table = x86_dynarec_opcodes_REPNE; - recomp_op_table = recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ - op_table = x86_dynarec_opcodes_REPE; - recomp_op_table = recomp_opcodes_REPE; - break; - - default: - goto generate_call; + switch (cpu_mod) { + case 0: + if ((sib & 7) == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL ,%eax*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } else { + addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - - op_pc++; + break; + case 1: + new_eaaddr = (uint32_t) (int8_t) ((fetchdat >> 16) & 0xff); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[sib & 7].l)); + (*op_pc) += 4; + break; } + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (((sib >> 3) & 7) != 4) { + switch (sib >> 6) { + case 0: + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); + break; + case 1: + addbyte(0x8B); + addbyte(0x5D); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 2: + addbyte(0x8B); + addbyte(0x5D); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); + addbyte(0xE3); + addbyte(2); /*SHL $2,%ebx*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 3: + addbyte(0x8B); + addbyte(0x5D); + addbyte((uint8_t) cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); + addbyte(0xE3); + addbyte(3); /*SHL $2,%ebx*/ + addbyte(0x01); + addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + } + } + addbyte(0xa3); + addlong((uint32_t) &cpu_state.eaaddr); + } else { + if (!cpu_mod && cpu_rm == 5) { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(eaaddr)); + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(regs[cpu_rm].l)); + cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; + if (cpu_mod) { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_mod == 1) { + addbyte(0x05); + addlong((uint32_t) (int8_t) (fetchdat >> 8)); + (*op_pc)++; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + addbyte(0xa3); + addlong((uint32_t) &cpu_state.eaaddr); + } + return op_ea_seg; +} + +void +codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t op_32 = use32; + uint32_t op_pc = new_pc; + const OpFn *op_table = x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + int over = 0; + int pc_off = 0; + int test_modrm = 1; + int c; + + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; + op_old_pc = old_pc; + + for (c = 0; c < NR_HOST_REGS; c++) + host_reg_mapping[c] = -1; + mmx_ebx_ecx_loaded = 0; + for (c = 0; c < NR_HOST_XMM_REGS; c++) + host_reg_xmm_mapping[c] = -1; + + codegen_timing_start(); + + while (!over) { + switch (opcode) { + case 0x0f: + op_table = x86_dynarec_opcodes_0f; + recomp_op_table = recomp_opcodes_0f; + over = 1; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.seg_gs; + op_ssegs = 1; + break; + + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; + + case 0xd8: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + + case 0xf0: /*LOCK*/ + break; + + case 0xf2: /*REPNE*/ + op_table = x86_dynarec_opcodes_REPNE; + recomp_op_table = recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ + op_table = x86_dynarec_opcodes_REPE; + recomp_op_table = recomp_opcodes_REPE; + break; + + default: + goto generate_call; + } + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + + op_pc++; + } generate_call: - codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); - codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); - codegen_block_cycles = 0; + codegen_accumulate(ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with - subsequent instructions, so no cycles may have been deducted for it yet. - To prevent having zero cycle blocks (eg with a jump instruction pointing - to itself), apply the cycles that would be taken if this jump is taken, - then reverse it for subsequent instructions if the jump is not taken*/ - int jump_cycles = 0; + if ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = 0; if (codegen_timing_jump_cycles != NULL) jump_cycles = codegen_timing_jump_cycles(); - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, -jump_cycles); - codegen_accumulate_flush(); - if (jump_cycles) - codegen_accumulate(ACCREG_cycles, jump_cycles); - } + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, -jump_cycles); + codegen_accumulate_flush(); + if (jump_cycles) + codegen_accumulate(ACCREG_cycles, jump_cycles); + } - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; - } + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { + op_table = x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } - if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); - if (new_pc) - { - if (new_pc != -1) - STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, new_pc); + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); + if (new_pc) { + if (new_pc != -1) + STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, new_pc); - codegen_block_ins++; - block->ins++; - codegen_block_full_ins++; - codegen_endpc = (cs + cpu_state.pc) + 8; + codegen_block_ins++; + block->ins++; + codegen_block_full_ins++; + codegen_endpc = (cs + cpu_state.pc) + 8; -#ifdef CHECK_INT +# ifdef CHECK_INT /* Check for interrupts. */ - addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ + addbyte(0xf6); /* test byte ptr[&pic_pending],1 */ addbyte(0x05); addlong((uint32_t) (uintptr_t) &pic_pending); addbyte(0x01); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); -#endif + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (&block->data[block_pos + 4])); +# endif - return; - } + return; } + } - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - if (op_ssegs != last_ssegs) - { - last_ssegs = op_ssegs; + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + if (op_ssegs != last_ssegs) { + last_ssegs = op_ssegs; - addbyte(0xC6); /*MOVB [ssegs],op_ssegs*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ssegs)); - addbyte(op_pc + pc_off); - } - - if (!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(rm_data.rm_mod_reg_data)); - addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); - if (cpu_mod != 3 && (op_32 & 0x200)) - op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - op_pc -= pc_off; - } - - if (op_ea_seg != last_ea_seg) - { - last_ea_seg = op_ea_seg; - addbyte(0xC7); /*MOVL $&cpu_state.seg_ds,(ea_seg)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(ea_seg)); - addlong((uint32_t)op_ea_seg); - } - - codegen_accumulate_flush(); - - addbyte(0xC7); /*MOVL pc,new_pc*/ + addbyte(0xC6); /*MOVB [ssegs],op_ssegs*/ addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(pc)); + addbyte((uint8_t) cpu_state_offset(ssegs)); + addbyte(op_pc + pc_off); + } + + if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) { + int stack_offset = 0; + + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; + + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; + + addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(rm_data.rm_mod_reg_data)); + addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); + + op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); + if (cpu_mod != 3 && (op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); + op_pc -= pc_off; + } + + if (op_ea_seg != last_ea_seg) { + last_ea_seg = op_ea_seg; + addbyte(0xC7); /*MOVL $&cpu_state.seg_ds,(ea_seg)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(ea_seg)); + addlong((uint32_t) op_ea_seg); + } + + codegen_accumulate_flush(); + + addbyte(0xC7); /*MOVL pc,new_pc*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(pc)); addlong(op_pc + pc_off); - addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ + addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ + addbyte(0x45); + addbyte((uint8_t) cpu_state_offset(oldpc)); + addlong(old_pc); + + if (op_32 != last_op32) { + last_op32 = op_32; + addbyte(0xC7); /*MOVL $use32,(op32)*/ addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(oldpc)); - addlong(old_pc); + addbyte((uint8_t) cpu_state_offset(op32)); + addlong(op_32); + } - if (op_32 != last_op32) - { - last_op32 = op_32; - addbyte(0xC7); /*MOVL $use32,(op32)*/ - addbyte(0x45); - addbyte((uint8_t)cpu_state_offset(op32)); - addlong(op_32); - } + addbyte(0xC7); /*MOVL $fetchdat,(%esp)*/ + addbyte(0x04); + addbyte(0x24); + addlong(fetchdat); - addbyte(0xC7); /*MOVL $fetchdat,(%esp)*/ - addbyte(0x04); - addbyte(0x24); - addlong(fetchdat); + addbyte(0xE8); /*CALL*/ + addlong(((uint8_t *) op - (uint8_t *) (&block->data[block_pos + 4]))); - addbyte(0xE8); /*CALL*/ - addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4]))); + codegen_block_ins++; - codegen_block_ins++; + block->ins++; - block->ins++; - -#ifdef CHECK_INT +# ifdef CHECK_INT /* Check for interrupts. */ - addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ + addbyte(0x0a); /* or al,byte ptr[&pic_pending] */ addbyte(0x05); addlong((uint32_t) (uintptr_t) &pic_pending); -#endif +# endif - addbyte(0x09); /*OR %eax, %eax*/ - addbyte(0xc0); - addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ - addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); + addbyte(0x09); /*OR %eax, %eax*/ + addbyte(0xc0); + addbyte(0x0F); + addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t) &block->data[BLOCK_EXIT_OFFSET] - (uint32_t) (&block->data[block_pos + 4])); - codegen_endpc = (cs + cpu_state.pc) + 8; + codegen_endpc = (cs + cpu_state.pc) + 8; } #endif diff --git a/src/codegen/codegen_x86.h b/src/codegen/codegen_x86.h index 369614329..d6842eec1 100644 --- a/src/codegen/codegen_x86.h +++ b/src/codegen/codegen_x86.h @@ -1,24 +1,23 @@ -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff -#define BLOCK_START 0 +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) #define BLOCK_EXIT_OFFSET 0x7f0 #ifdef OLD_GPF -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) #else -#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14) +# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14) #endif #define BLOCK_MAX 1720 -enum -{ - OP_RET = 0xc3 +enum { + OP_RET = 0xc3 }; #define NR_HOST_REGS 4 diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index eb3c7f5eb..2f178bc74 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -20,43 +20,43 @@ static struct { - uint32_t pc; - int op_ssegs; - x86seg *op_ea_seg; - uint32_t op_32; - int first_uop; - int TOP; + uint32_t pc; + int op_ssegs; + x86seg *op_ea_seg; + uint32_t op_32; + int first_uop; + int TOP; } codegen_instructions[MAX_INSTRUCTION_COUNT]; -int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP) +int +codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP) { - int c; + int c; - for (c = 0; c <= block->ins; c++) - { - if (codegen_instructions[c].pc == pc) - { - *first_instruction = c; - *TOP = codegen_instructions[c].TOP; - return codegen_instructions[c].first_uop; - } + for (c = 0; c <= block->ins; c++) { + if (codegen_instructions[c].pc == pc) { + *first_instruction = c; + *TOP = codegen_instructions[c].TOP; + return codegen_instructions[c].first_uop; } + } - *first_instruction = block->ins; - return -1; + *first_instruction = block->ins; + return -1; } -void codegen_set_loop_start(ir_data_t *ir, int first_instruction) +void +codegen_set_loop_start(ir_data_t *ir, int first_instruction) { - uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32); - uop_MOV_PTR(ir, IREG_ea_seg, (void *)codegen_instructions[first_instruction].op_ea_seg); - uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs); + uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32); + uop_MOV_PTR(ir, IREG_ea_seg, (void *) codegen_instructions[first_instruction].op_ea_seg); + uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs); } int has_ea; codeblock_t *codeblock; -uint16_t *codeblock_hash; +uint16_t *codeblock_hash; void (*codegen_timing_start)(void); void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat); @@ -65,714 +65,665 @@ void (*codegen_timing_block_start)(void); void (*codegen_timing_block_end)(void); int (*codegen_timing_jump_cycles)(void); -void codegen_timing_set(codegen_timing_t *timing) +void +codegen_timing_set(codegen_timing_t *timing) { - codegen_timing_start = timing->start; - codegen_timing_prefix = timing->prefix; - codegen_timing_opcode = timing->opcode; - codegen_timing_block_start = timing->block_start; - codegen_timing_block_end = timing->block_end; - codegen_timing_jump_cycles = timing->jump_cycles; + codegen_timing_start = timing->start; + codegen_timing_prefix = timing->prefix; + codegen_timing_opcode = timing->opcode; + codegen_timing_block_start = timing->block_start; + codegen_timing_block_end = timing->block_end; + codegen_timing_jump_cycles = timing->jump_cycles; } int codegen_in_recompile; -static int last_op_ssegs; -static x86seg *last_op_ea_seg; +static int last_op_ssegs; +static x86seg *last_op_ea_seg; static uint32_t last_op_32; -void codegen_generate_reset(void) +void +codegen_generate_reset(void) { - last_op_ssegs = -1; - last_op_ea_seg = NULL; - last_op_32 = -1; - has_ea = 0; + last_op_ssegs = -1; + last_op_ea_seg = NULL; + last_op_32 = -1; + has_ea = 0; } -void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg) +void +codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, 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; + /*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; - uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout); + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t) -1, codegen_gpf_rout); - seg->checked = 1; + seg->checked = 1; } -void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg) +void +codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, 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; + /*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; - uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout); + uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t) -1, codegen_gpf_rout); - seg->checked = 1; + seg->checked = 1; } -static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +static x86seg * +codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { - uint32_t old_pc = (*op_pc) + 1; - if (!cpu_mod && cpu_rm == 6) - { - uint16_t addr = (fetchdat >> 8) & 0xffff; - uop_MOV_IMM(ir, IREG_eaaddr, addr); - (*op_pc) += 2; + uint32_t old_pc = (*op_pc) + 1; + if (!cpu_mod && cpu_rm == 6) { + uint16_t addr = (fetchdat >> 8) & 0xffff; + uop_MOV_IMM(ir, IREG_eaaddr, addr); + (*op_pc) += 2; + } else { + int base_reg, index_reg, offset; + + switch (cpu_rm & 7) { + case 0: + case 1: + case 7: + default: + base_reg = IREG_EBX; + break; + case 2: + case 3: + case 6: + base_reg = IREG_EBP; + break; + case 4: + base_reg = IREG_ESI; + break; + case 5: + base_reg = IREG_EDI; + break; } - else - { - int base_reg, index_reg, offset; + uop_MOV(ir, IREG_eaaddr, base_reg); - switch (cpu_rm & 7) - { - case 0: case 1: case 7: default: - base_reg = IREG_EBX; - break; - case 2: case 3: case 6: - base_reg = IREG_EBP; - break; - case 4: - base_reg = IREG_ESI; - break; - case 5: - base_reg = IREG_EDI; - break; - } - uop_MOV(ir, IREG_eaaddr, base_reg); + if (!(cpu_rm & 4)) { + if (!(cpu_rm & 1)) + index_reg = IREG_ESI; + else + index_reg = IREG_EDI; - if (!(cpu_rm & 4)) - { - if (!(cpu_rm & 1)) - index_reg = IREG_ESI; - else - index_reg = IREG_EDI; - - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg); - } - - switch (cpu_mod) - { - case 1: - offset = (int)(int8_t)((fetchdat >> 8) & 0xff); - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); - (*op_pc)++; - break; - case 2: - offset = (fetchdat >> 8) & 0xffff; - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); - (*op_pc) += 2; - break; - } - - uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); - - if (mod1seg[cpu_rm] == &ss && !op_ssegs) - { - op_ea_seg = &cpu_state.seg_ss; - } + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg); } - codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-old_pc); - return op_ea_seg; -} - -static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) -{ - codeblock_t *block = ir->block; - uint32_t old_pc = (*op_pc) + 1; - uint32_t new_eaaddr; - int extra_bytes = 0; - - if (cpu_rm == 4) - { - uint8_t sib = fetchdat >> 8; + switch (cpu_mod) { + case 1: + offset = (int) (int8_t) ((fetchdat >> 8) & 0xff); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); (*op_pc)++; + break; + case 2: + offset = (fetchdat >> 8) & 0xffff; + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset); + (*op_pc) += 2; + break; + } - switch (cpu_mod) - { - case 0: - if ((sib & 7) == 5) - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); - extra_bytes = 1; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - extra_bytes = 5; - } - (*op_pc) += 4; - } - else - { - uop_MOV(ir, IREG_eaaddr, sib & 7); - extra_bytes = 1; - } - break; - case 1: - new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); + uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + + if (mod1seg[cpu_rm] == &ss && !op_ssegs) { + op_ea_seg = &cpu_state.seg_ss; + } + } + + codegen_mark_code_present(ir->block, cs + old_pc, ((*op_pc) + 1) - old_pc); + return op_ea_seg; +} + +static x86seg * +codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + codeblock_t *block = ir->block; + uint32_t old_pc = (*op_pc) + 1; + uint32_t new_eaaddr; + int extra_bytes = 0; + + if (cpu_rm == 4) { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (cpu_mod) { + case 0: + if ((sib & 7) == 5) { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + extra_bytes = 1; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); - (*op_pc)++; - extra_bytes = 2; - break; - case 2: - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); - extra_bytes = 1; - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - extra_bytes = 5; - } - (*op_pc) += 4; - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); - break; + extra_bytes = 5; + } + (*op_pc) += 4; + } else { + uop_MOV(ir, IREG_eaaddr, sib & 7); + extra_bytes = 1; } - if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ - { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset); -// addbyte(0x05); -// addlong(stack_offset); - } - if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (((sib >> 3) & 7) != 4) - { - switch (sib >> 6) - { - case 0: - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7); - break; - case 1: - uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1); - break; - case 2: - uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2); - break; - case 3: - uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3); - break; - } + break; + case 1: + new_eaaddr = (uint32_t) (int8_t) ((fetchdat >> 16) & 0xff); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + (*op_pc)++; + extra_bytes = 2; + break; + case 2: + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + extra_bytes = 1; + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 5; } + (*op_pc) += 4; + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7); + break; } - else + if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/ { - if (!cpu_mod && cpu_rm == 5) - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); - extra_bytes = 4; - } - - (*op_pc) += 4; - } - else - { - uop_MOV(ir, IREG_eaaddr, cpu_rm); - if (cpu_mod) - { - if (cpu_rm == 5 && !op_ssegs) - op_ea_seg = &cpu_state.seg_ss; - if (cpu_mod == 1) - { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8)); - (*op_pc)++; - extra_bytes = 1; - } - else - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0); - } - else - { - new_eaaddr = fastreadl(cs + (*op_pc) + 1); - uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); - extra_bytes = 4; - } - (*op_pc) += 4; - } - } - } + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset); + // addbyte(0x05); + // addlong(stack_offset); } + if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (((sib >> 3) & 7) != 4) { + switch (sib >> 6) { + case 0: + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7); + break; + case 1: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1); + break; + case 2: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2); + break; + case 3: + uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3); + break; + } + } + } else { + if (!cpu_mod && cpu_rm == 5) { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1); + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr); + extra_bytes = 4; + } - if (extra_bytes) - codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes); + (*op_pc) += 4; + } else { + uop_MOV(ir, IREG_eaaddr, cpu_rm); + if (cpu_mod) { + if (cpu_rm == 5 && !op_ssegs) + op_ea_seg = &cpu_state.seg_ss; + if (cpu_mod == 1) { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t) (int8_t) (fetchdat >> 8)); + (*op_pc)++; + extra_bytes = 1; + } else { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0); + } else { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr); + extra_bytes = 4; + } + (*op_pc) += 4; + } + } + } + } - return op_ea_seg; + if (extra_bytes) + codegen_mark_code_present(ir->block, cs + old_pc, extra_bytes); + + return op_ea_seg; } -x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset) +x86seg * +codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset) { - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; - if ((fetchdat & 0xc0) == 0xc0) - return NULL; - if (op_32 & 0x200) - return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset); + if ((fetchdat & 0xc0) == 0xc0) + return NULL; + if (op_32 & 0x200) + return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset); - return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc); + return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc); } -static uint8_t opcode_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ +static uint8_t opcode_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ - 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ }; -static uint8_t opcode_0f_modrm[256] = -{ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ +static uint8_t opcode_0f_modrm[256] = { + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ - 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ - 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ - 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ }; -void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +void +codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { - codeblock_t *block = &codeblock[block_current]; - ir_data_t *ir = codegen_get_ir_data(); - uint32_t op_pc = new_pc; - OpFn *op_table = (OpFn *) x86_dynarec_opcodes; - RecompOpFn *recomp_op_table = recomp_opcodes; - int opcode_shift = 0; - int opcode_mask = 0x3ff; - uint32_t recomp_opcode_mask = 0x1ff; - uint32_t op_32 = use32; - int over = 0; - int test_modrm = 1; - int pc_off = 0; - uint32_t next_pc = 0; + codeblock_t *block = &codeblock[block_current]; + ir_data_t *ir = codegen_get_ir_data(); + uint32_t op_pc = new_pc; + OpFn *op_table = (OpFn *) x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + uint32_t recomp_opcode_mask = 0x1ff; + uint32_t op_32 = use32; + int over = 0; + int test_modrm = 1; + int pc_off = 0; + uint32_t next_pc = 0; #ifdef DEBUG_EXTRA - uint8_t last_prefix = 0; + uint8_t last_prefix = 0; #endif - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 0; + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 0; - codegen_timing_start(); + codegen_timing_start(); - while (!over) - { - switch (opcode) - { - case 0x0f: + while (!over) { + switch (opcode) { + case 0x0f: #ifdef DEBUG_EXTRA - last_prefix = 0x0f; + last_prefix = 0x0f; #endif - op_table = (OpFn *) x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; - over = 1; - break; + op_table = (OpFn *) x86_dynarec_opcodes_0f; + recomp_op_table = recomp_opcodes_0f; + over = 1; + break; - case 0x26: /*ES:*/ - op_ea_seg = &cpu_state.seg_es; - op_ssegs = 1; - break; - case 0x2e: /*CS:*/ - op_ea_seg = &cpu_state.seg_cs; - op_ssegs = 1; - break; - case 0x36: /*SS:*/ - op_ea_seg = &cpu_state.seg_ss; - op_ssegs = 1; - break; - case 0x3e: /*DS:*/ - op_ea_seg = &cpu_state.seg_ds; - op_ssegs = 1; - break; - case 0x64: /*FS:*/ - op_ea_seg = &cpu_state.seg_fs; - op_ssegs = 1; - break; - case 0x65: /*GS:*/ - op_ea_seg = &cpu_state.seg_gs; - op_ssegs = 1; - break; + case 0x26: /*ES:*/ + op_ea_seg = &cpu_state.seg_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &cpu_state.seg_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &cpu_state.seg_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &cpu_state.seg_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &cpu_state.seg_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &cpu_state.seg_gs; + op_ssegs = 1; + break; - case 0x66: /*Data size select*/ - op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); - break; - case 0x67: /*Address size select*/ - op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); - break; + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; - case 0xd8: + case 0xd8: #ifdef DEBUG_EXTRA - last_prefix = 0xd8; + last_prefix = 0xd8; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d8_a32 : (OpFn *) x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xd9: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d8_a32 : (OpFn *) x86_dynarec_opcodes_d8_a16; + recomp_op_table = recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xd9: #ifdef DEBUG_EXTRA - last_prefix = 0xd9; + last_prefix = 0xd9; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d9_a32 : (OpFn *) x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xda: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d9_a32 : (OpFn *) x86_dynarec_opcodes_d9_a16; + recomp_op_table = recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xda: #ifdef DEBUG_EXTRA - last_prefix = 0xda; + last_prefix = 0xda; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_da_a32 : (OpFn *) x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdb: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_da_a32 : (OpFn *) x86_dynarec_opcodes_da_a16; + recomp_op_table = recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdb: #ifdef DEBUG_EXTRA - last_prefix = 0xdb; + last_prefix = 0xdb; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_db_a32 : (OpFn *) x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdc: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_db_a32 : (OpFn *) x86_dynarec_opcodes_db_a16; + recomp_op_table = recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdc: #ifdef DEBUG_EXTRA - last_prefix = 0xdc; + last_prefix = 0xdc; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dc_a32 : (OpFn *) x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; - opcode_shift = 3; - opcode_mask = 0x1f; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdd: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dc_a32 : (OpFn *) x86_dynarec_opcodes_dc_a16; + recomp_op_table = recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdd: #ifdef DEBUG_EXTRA - last_prefix = 0xdd; + last_prefix = 0xdd; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dd_a32 : (OpFn *) x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xde: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dd_a32 : (OpFn *) x86_dynarec_opcodes_dd_a16; + recomp_op_table = recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xde: #ifdef DEBUG_EXTRA - last_prefix = 0xde; + last_prefix = 0xde; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_de_a32 : (OpFn *) x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; - case 0xdf: + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_de_a32 : (OpFn *) x86_dynarec_opcodes_de_a16; + recomp_op_table = recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; + case 0xdf: #ifdef DEBUG_EXTRA - last_prefix = 0xdf; + last_prefix = 0xdf; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_df_a32 : (OpFn *) x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; - opcode_mask = 0xff; - over = 1; - pc_off = -1; - test_modrm = 0; - block->flags |= CODEBLOCK_HAS_FPU; - break; + op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_df_a32 : (OpFn *) x86_dynarec_opcodes_df_a16; + recomp_op_table = recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; + break; - case 0xf0: /*LOCK*/ - break; + case 0xf0: /*LOCK*/ + break; - case 0xf2: /*REPNE*/ + case 0xf2: /*REPNE*/ #ifdef DEBUG_EXTRA - last_prefix = 0xf2; + last_prefix = 0xf2; #endif - op_table = (OpFn *) x86_dynarec_opcodes_REPNE; - recomp_op_table = NULL;//recomp_opcodes_REPNE; - break; - case 0xf3: /*REPE*/ + op_table = (OpFn *) x86_dynarec_opcodes_REPNE; + recomp_op_table = NULL; // recomp_opcodes_REPNE; + break; + case 0xf3: /*REPE*/ #ifdef DEBUG_EXTRA - last_prefix = 0xf3; + last_prefix = 0xf3; #endif - op_table = (OpFn *) x86_dynarec_opcodes_REPE; - recomp_op_table = NULL;//recomp_opcodes_REPE; - break; + op_table = (OpFn *) x86_dynarec_opcodes_REPE; + recomp_op_table = NULL; // recomp_opcodes_REPE; + break; - default: - goto generate_call; - } - fetchdat = fastreadl(cs + op_pc); - codegen_timing_prefix(opcode, fetchdat); - if (cpu_state.abrt) - return; - opcode = fetchdat & 0xff; - if (!pc_off) - fetchdat >>= 8; - - op_pc++; + default: + goto generate_call; } + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (cpu_state.abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + + op_pc++; + } generate_call: - codegen_instructions[block->ins].pc = cpu_state.oldpc; - codegen_instructions[block->ins].op_ssegs = last_op_ssegs; - codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg; - codegen_instructions[block->ins].op_32 = last_op_32; - codegen_instructions[block->ins].TOP = cpu_state.TOP; - codegen_instructions[block->ins].first_uop = ir->wr_pos; + codegen_instructions[block->ins].pc = cpu_state.oldpc; + codegen_instructions[block->ins].op_ssegs = last_op_ssegs; + codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg; + codegen_instructions[block->ins].op_32 = last_op_32; + codegen_instructions[block->ins].TOP = cpu_state.TOP; + codegen_instructions[block->ins].first_uop = ir->wr_pos; - codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); - codegen_accumulate(ir, ACCREG_cycles, -codegen_block_cycles); - codegen_block_cycles = 0; + codegen_accumulate(ir, ACCREG_cycles, -codegen_block_cycles); + codegen_block_cycles = 0; - if ((op_table == x86_dynarec_opcodes && - ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || - (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || - (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || - (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) - { - /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with - subsequent instructions, so no cycles may have been deducted for it yet. - To prevent having zero cycle blocks (eg with a jump instruction pointing - to itself), apply the cycles that would be taken if this jump is taken, - then reverse it for subsequent instructions if the jump is not taken*/ - int jump_cycles = 0; + if ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 || (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 || (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80))) { + /*On some CPUs (eg K6), a jump/branch instruction may be able to pair with + subsequent instructions, so no cycles may have been deducted for it yet. + To prevent having zero cycle blocks (eg with a jump instruction pointing + to itself), apply the cycles that would be taken if this jump is taken, + then reverse it for subsequent instructions if the jump is not taken*/ + int jump_cycles = 0; - if (codegen_timing_jump_cycles) - codegen_timing_jump_cycles(); + if (codegen_timing_jump_cycles) + codegen_timing_jump_cycles(); - if (jump_cycles) - codegen_accumulate(ir, ACCREG_cycles, -jump_cycles); - codegen_accumulate_flush(ir); - if (jump_cycles) - codegen_accumulate(ir, ACCREG_cycles, jump_cycles); + if (jump_cycles) + codegen_accumulate(ir, ACCREG_cycles, -jump_cycles); + codegen_accumulate_flush(ir); + if (jump_cycles) + codegen_accumulate(ir, ACCREG_cycles, jump_cycles); + } + + if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f) { + /*3DNow opcodes are stored after ModR/M, SIB and any offset*/ + uint8_t modrm = fetchdat & 0xff; + uint8_t sib = (fetchdat >> 8) & 0xff; + uint32_t opcode_pc = op_pc + 1; + uint8_t opcode_3dnow; + + if ((modrm & 0xc0) != 0xc0) { + if (op_32 & 0x200) { + if ((modrm & 7) == 4) { + /* Has SIB*/ + opcode_pc++; + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((sib & 0x07) == 0x05) + opcode_pc += 4; + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((modrm & 0xc7) == 0x05) + opcode_pc += 4; + } + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 2; + else if ((modrm & 0xc7) == 0x06) + opcode_pc += 2; + } } - if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f) - { - /*3DNow opcodes are stored after ModR/M, SIB and any offset*/ - uint8_t modrm = fetchdat & 0xff; - uint8_t sib = (fetchdat >> 8) & 0xff; - uint32_t opcode_pc = op_pc + 1; - uint8_t opcode_3dnow; + opcode_3dnow = fastreadb(cs + opcode_pc); + if (recomp_opcodes_3DNOW[opcode_3dnow]) { + next_pc = opcode_pc + 1; - if ((modrm & 0xc0) != 0xc0) - { - if (op_32 & 0x200) - { - if ((modrm & 7) == 4) - { - /* Has SIB*/ - opcode_pc++; - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 4; - else if ((sib & 0x07) == 0x05) - opcode_pc += 4; - } - else - { - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 4; - else if ((modrm & 0xc7) == 0x05) - opcode_pc += 4; - } - } - else - { - if ((modrm & 0xc0) == 0x40) - opcode_pc++; - else if ((modrm & 0xc0) == 0x80) - opcode_pc += 2; - else if ((modrm & 0xc7) == 0x06) - opcode_pc += 2; - } - } - - opcode_3dnow = fastreadb(cs + opcode_pc); - if (recomp_opcodes_3DNOW[opcode_3dnow]) - { - next_pc = opcode_pc + 1; - - op_table = (OpFn *) x86_dynarec_opcodes_3DNOW; - recomp_op_table = recomp_opcodes_3DNOW; - opcode = opcode_3dnow; - recomp_opcode_mask = 0xff; - opcode_mask = 0xff; - } + op_table = (OpFn *) x86_dynarec_opcodes_3DNOW; + recomp_op_table = recomp_opcodes_3DNOW; + opcode = opcode_3dnow; + recomp_opcode_mask = 0xff; + opcode_mask = 0xff; } - codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off); - /* It is apparently a prefixed instruction. */ - // if ((recomp_op_table == recomp_opcodes) && (opcode == 0x48)) - // goto codegen_skip; + } + codegen_mark_code_present(block, cs + old_pc, (op_pc - old_pc) - pc_off); + /* It is apparently a prefixed instruction. */ + // if ((recomp_op_table == recomp_opcodes) && (opcode == 0x48)) + // goto codegen_skip; - if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) - { - uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc); - if (new_pc) - { - if (new_pc != -1) - uop_MOV_IMM(ir, IREG_pc, new_pc); + if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc); + if (new_pc) { + if (new_pc != -1) + uop_MOV_IMM(ir, IREG_pc, new_pc); - codegen_endpc = (cs + cpu_state.pc) + 8; + codegen_endpc = (cs + cpu_state.pc) + 8; - block->ins++; + block->ins++; - if (block->ins >= MAX_INSTRUCTION_COUNT) - CPU_BLOCK_END(); + if (block->ins >= MAX_INSTRUCTION_COUNT) + CPU_BLOCK_END(); - return; - } + return; } + } -// codegen_skip: - if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) - { - op_table = (OpFn *) x86_dynarec_opcodes; - recomp_op_table = recomp_opcodes; + // codegen_skip: + if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) { + op_table = (OpFn *) x86_dynarec_opcodes; + recomp_op_table = recomp_opcodes; + } + + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; + + if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || (op_table == x86_dynarec_opcodes_3DNOW)) { + int stack_offset = 0; + + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; + + cpu_mod = (fetchdat >> 6) & 3; + cpu_reg = (fetchdat >> 3) & 7; + cpu_rm = fetchdat & 7; + + uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); + + op_pc += pc_off; + if (cpu_mod != 3 && !(op_32 & 0x200)) { + op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); } - - op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; - - if (!test_modrm || - (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || - (op_table == x86_dynarec_opcodes_3DNOW)) - { - int stack_offset = 0; - - if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ - stack_offset = (op_32 & 0x100) ? 4 : 2; - - cpu_mod = (fetchdat >> 6) & 3; - cpu_reg = (fetchdat >> 3) & 7; - cpu_rm = fetchdat & 7; - - uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16)); - - op_pc += pc_off; - if (cpu_mod != 3 && !(op_32 & 0x200)) - { - op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc); - } - if (cpu_mod != 3 && (op_32 & 0x200)) - { - op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); - } - op_pc -= pc_off; + if (cpu_mod != 3 && (op_32 & 0x200)) { + op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); } + op_pc -= pc_off; + } #ifdef DEBUG_EXTRA - uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); + uop_LOG_INSTR(ir, opcode | (last_prefix << 8)); #endif - codegen_accumulate_flush(ir); - if (op_table == x86_dynarec_opcodes_3DNOW) - uop_MOV_IMM(ir, IREG_pc, next_pc); - else - uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off); - uop_MOV_IMM(ir, IREG_oldpc, old_pc); - if (op_32 != last_op_32) - uop_MOV_IMM(ir, IREG_op32, op_32); - if (op_ea_seg != last_op_ea_seg) - uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg); - if (op_ssegs != last_op_ssegs) - uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); - uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); - uop_CALL_INSTRUCTION_FUNC(ir, op); - codegen_mark_code_present(block, cs+cpu_state.pc, 8); + codegen_accumulate_flush(ir); + if (op_table == x86_dynarec_opcodes_3DNOW) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, op_pc + pc_off); + uop_MOV_IMM(ir, IREG_oldpc, old_pc); + if (op_32 != last_op_32) + uop_MOV_IMM(ir, IREG_op32, op_32); + if (op_ea_seg != last_op_ea_seg) + uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); + if (op_ssegs != last_op_ssegs) + uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); + uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); + uop_CALL_INSTRUCTION_FUNC(ir, op); + codegen_mark_code_present(block, cs + cpu_state.pc, 8); - last_op_32 = op_32; - last_op_ea_seg = op_ea_seg; - last_op_ssegs = op_ssegs; - //codegen_block_ins++; + last_op_32 = op_32; + last_op_ea_seg = op_ea_seg; + last_op_ssegs = op_ssegs; + // codegen_block_ins++; - block->ins++; + block->ins++; - if (block->ins >= MAX_INSTRUCTION_COUNT) - CPU_BLOCK_END(); + if (block->ins >= MAX_INSTRUCTION_COUNT) + CPU_BLOCK_END(); - codegen_endpc = (cs + cpu_state.pc) + 8; + codegen_endpc = (cs + cpu_state.pc) + 8; -// if (has_ea) -// fatal("Has EA\n"); + // if (has_ea) + // fatal("Has EA\n"); } diff --git a/src/codegen_new/codegen.h b/src/codegen_new/codegen.h index c6fbac2a9..cc7e3f083 100644 --- a/src/codegen_new/codegen.h +++ b/src/codegen_new/codegen.h @@ -30,34 +30,33 @@ same page). */ -typedef struct codeblock_t -{ - uint32_t pc; - uint32_t _cs; - uint32_t phys, phys_2; - uint16_t status; - uint16_t flags; - uint8_t ins; - uint8_t TOP; +typedef struct codeblock_t { + uint32_t pc; + uint32_t _cs; + uint32_t phys, phys_2; + uint16_t status; + uint16_t flags; + uint8_t ins; + uint8_t TOP; - /*Pointers for codeblock tree, used to search for blocks when hash lookup - fails.*/ - uint16_t parent, left, right; + /*Pointers for codeblock tree, used to search for blocks when hash lookup + fails.*/ + uint16_t parent, left, right; - uint8_t *data; + uint8_t *data; - uint64_t page_mask, page_mask2; - uint64_t *dirty_mask, *dirty_mask2; + uint64_t page_mask, page_mask2; + uint64_t *dirty_mask, *dirty_mask2; - /*Previous and next pointers, for the codeblock list associated with - each physical page. Two sets of pointers, as a codeblock can be - present in two pages.*/ - uint16_t prev, next; - uint16_t prev_2, next_2; + /*Previous and next pointers, for the codeblock list associated with + each physical page. Two sets of pointers, as a codeblock can be + present in two pages.*/ + uint16_t prev, next; + uint16_t prev_2, next_2; - /*First mem_block_t used by this block. Any subsequent mem_block_ts - will be in the list starting at head_mem_block->next.*/ - struct mem_block_t *head_mem_block; + /*First mem_block_t used by this block. Any subsequent mem_block_ts + will be in the list starting at head_mem_block->next.*/ + struct mem_block_t *head_mem_block; } codeblock_t; extern codeblock_t *codeblock; @@ -83,235 +82,206 @@ extern uint8_t *block_write_data; /*Code block is not inlining immediate parameters, parameters must be fetched from memory*/ #define CODEBLOCK_NO_IMMEDIATES 0x80 -#define BLOCK_PC_INVALID 0xffffffff +#define BLOCK_PC_INVALID 0xffffffff -#define BLOCK_INVALID 0 +#define BLOCK_INVALID 0 -static inline int get_block_nr(codeblock_t *block) +static inline int +get_block_nr(codeblock_t *block) { - return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t); + return ((uintptr_t) block - (uintptr_t) codeblock) / sizeof(codeblock_t); } -static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs) +static inline codeblock_t * +codeblock_tree_find(uint32_t phys, uint32_t _cs) { - codeblock_t *block; - uint64_t a = _cs | ((uint64_t)phys << 32); + codeblock_t *block; + uint64_t a = _cs | ((uint64_t) phys << 32); - if (!pages[phys >> 12].head) - return NULL; + if (!pages[phys >> 12].head) + return NULL; - block = &codeblock[pages[phys >> 12].head]; - while (block) - { - uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32); - if (a == block_cmp) - { - if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) - break; - } - if (a < block_cmp) - block = block->left ? &codeblock[block->left] : NULL; - else - block = block->right ? &codeblock[block->right] : NULL; - } - - return block; -} - -static inline void codeblock_tree_add(codeblock_t *new_block) -{ - codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head]; - uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); - - if (!pages[new_block->phys >> 12].head) - { - pages[new_block->phys >> 12].head = get_block_nr(new_block); - new_block->parent = new_block->left = new_block->right = BLOCK_INVALID; + block = &codeblock[pages[phys >> 12].head]; + while (block) { + uint64_t block_cmp = block->_cs | ((uint64_t) block->phys << 32); + if (a == block_cmp) { + if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK))) + break; } + if (a < block_cmp) + block = block->left ? &codeblock[block->left] : NULL; else - { - codeblock_t *old_block = NULL; - uint64_t old_block_cmp = 0; + block = block->right ? &codeblock[block->right] : NULL; + } - while (block) - { - old_block = block; - old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32); - - if (a < old_block_cmp) - block = block->left ? &codeblock[block->left] : NULL; - else - block = block->right ? &codeblock[block->right] : NULL; - } - - if (a < old_block_cmp) - old_block->left = get_block_nr(new_block); - else - old_block->right = get_block_nr(new_block); - - new_block->parent = get_block_nr(old_block); - new_block->left = new_block->right = BLOCK_INVALID; - } + return block; } -static inline void codeblock_tree_delete(codeblock_t *block) +static inline void +codeblock_tree_add(codeblock_t *new_block) { - uint16_t parent_nr = block->parent; - codeblock_t *parent; + codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head]; + uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32); - if (block->parent) - parent = &codeblock[block->parent]; + if (!pages[new_block->phys >> 12].head) { + pages[new_block->phys >> 12].head = get_block_nr(new_block); + new_block->parent = new_block->left = new_block->right = BLOCK_INVALID; + } else { + codeblock_t *old_block = NULL; + uint64_t old_block_cmp = 0; + + while (block) { + old_block = block; + old_block_cmp = old_block->_cs | ((uint64_t) old_block->phys << 32); + + if (a < old_block_cmp) + block = block->left ? &codeblock[block->left] : NULL; + else + block = block->right ? &codeblock[block->right] : NULL; + } + + if (a < old_block_cmp) + old_block->left = get_block_nr(new_block); else - parent = NULL; + old_block->right = get_block_nr(new_block); - if (!block->left && !block->right) - { - /*Easy case - remove from parent*/ - if (!parent) - pages[block->phys >> 12].head = BLOCK_INVALID; - else - { - uint16_t block_nr = get_block_nr(block); - - if (parent->left == block_nr) - parent->left = BLOCK_INVALID; - if (parent->right == block_nr) - parent->right = BLOCK_INVALID; - } - return; - } - else if (!block->left) - { - /*Only right node*/ - if (!parent_nr) - { - pages[block->phys >> 12].head = block->right; - codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; - } - else - { - uint16_t block_nr = get_block_nr(block); - - if (parent->left == block_nr) - { - parent->left = block->right; - codeblock[parent->left].parent = parent_nr; - } - if (parent->right == block_nr) - { - parent->right = block->right; - codeblock[parent->right].parent = parent_nr; - } - } - return; - } - else if (!block->right) - { - /*Only left node*/ - if (!parent_nr) - { - pages[block->phys >> 12].head = block->left; - codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; - } - else - { - uint16_t block_nr = get_block_nr(block); - - if (parent->left == block_nr) - { - parent->left = block->left; - codeblock[parent->left].parent = parent_nr; - } - if (parent->right == block_nr) - { - parent->right = block->left; - codeblock[parent->right].parent = parent_nr; - } - } - return; - } - else - { - /*Difficult case - node has two children. Walk right child to find lowest node*/ - codeblock_t *lowest = &codeblock[block->right], *highest; - codeblock_t *old_parent; - uint16_t lowest_nr; - - while (lowest->left) - lowest = &codeblock[lowest->left]; - lowest_nr = get_block_nr(lowest); - - old_parent = &codeblock[lowest->parent]; - - /*Replace deleted node with lowest node*/ - if (!parent_nr) - pages[block->phys >> 12].head = lowest_nr; - else - { - uint16_t block_nr = get_block_nr(block); - - if (parent->left == block_nr) - parent->left = lowest_nr; - if (parent->right == block_nr) - parent->right = lowest_nr; - } - - lowest->parent = parent_nr; - lowest->left = block->left; - if (lowest->left) - codeblock[lowest->left].parent = lowest_nr; - - old_parent->left = BLOCK_INVALID; - - highest = &codeblock[lowest->right]; - if (!lowest->right) - { - if (lowest_nr != block->right) - { - lowest->right = block->right; - codeblock[block->right].parent = lowest_nr; - } - return; - } - - while (highest->right) - highest = &codeblock[highest->right]; - - if (block->right && block->right != lowest_nr) - { - highest->right = block->right; - codeblock[block->right].parent = get_block_nr(highest); - } - } + new_block->parent = get_block_nr(old_block); + new_block->left = new_block->right = BLOCK_INVALID; + } } -#define PAGE_MASK_MASK 63 +static inline void +codeblock_tree_delete(codeblock_t *block) +{ + uint16_t parent_nr = block->parent; + codeblock_t *parent; + + if (block->parent) + parent = &codeblock[block->parent]; + else + parent = NULL; + + if (!block->left && !block->right) { + /*Easy case - remove from parent*/ + if (!parent) + pages[block->phys >> 12].head = BLOCK_INVALID; + else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) + parent->left = BLOCK_INVALID; + if (parent->right == block_nr) + parent->right = BLOCK_INVALID; + } + return; + } else if (!block->left) { + /*Only right node*/ + if (!parent_nr) { + pages[block->phys >> 12].head = block->right; + codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; + } else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) { + parent->left = block->right; + codeblock[parent->left].parent = parent_nr; + } + if (parent->right == block_nr) { + parent->right = block->right; + codeblock[parent->right].parent = parent_nr; + } + } + return; + } else if (!block->right) { + /*Only left node*/ + if (!parent_nr) { + pages[block->phys >> 12].head = block->left; + codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID; + } else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) { + parent->left = block->left; + codeblock[parent->left].parent = parent_nr; + } + if (parent->right == block_nr) { + parent->right = block->left; + codeblock[parent->right].parent = parent_nr; + } + } + return; + } else { + /*Difficult case - node has two children. Walk right child to find lowest node*/ + codeblock_t *lowest = &codeblock[block->right], *highest; + codeblock_t *old_parent; + uint16_t lowest_nr; + + while (lowest->left) + lowest = &codeblock[lowest->left]; + lowest_nr = get_block_nr(lowest); + + old_parent = &codeblock[lowest->parent]; + + /*Replace deleted node with lowest node*/ + if (!parent_nr) + pages[block->phys >> 12].head = lowest_nr; + else { + uint16_t block_nr = get_block_nr(block); + + if (parent->left == block_nr) + parent->left = lowest_nr; + if (parent->right == block_nr) + parent->right = lowest_nr; + } + + lowest->parent = parent_nr; + lowest->left = block->left; + if (lowest->left) + codeblock[lowest->left].parent = lowest_nr; + + old_parent->left = BLOCK_INVALID; + + highest = &codeblock[lowest->right]; + if (!lowest->right) { + if (lowest_nr != block->right) { + lowest->right = block->right; + codeblock[block->right].parent = lowest_nr; + } + return; + } + + while (highest->right) + highest = &codeblock[highest->right]; + + if (block->right && block->right != lowest_nr) { + highest->right = block->right; + codeblock[block->right].parent = get_block_nr(highest); + } + } +} + +#define PAGE_MASK_MASK 63 #define PAGE_MASK_SHIFT 6 void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len); -static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len) +static inline void +codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len) { - if (len == 1) - { - if (block->flags & CODEBLOCK_BYTE_MASK) - { - if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/ - block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK)); - else - block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK)); - } - else - { - if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/ - block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); - else - block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); - } + if (len == 1) { + if (block->flags & CODEBLOCK_BYTE_MASK) { + if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/ + block->page_mask |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK)); + else + block->page_mask2 |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK)); + } else { + if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/ + block->page_mask |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); + else + block->page_mask2 |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK)); } - else - codegen_mark_code_present_multibyte(block, start_pc, len); + } else + codegen_mark_code_present_multibyte(block, start_pc, len); } extern void codegen_init(void); @@ -329,7 +299,7 @@ extern void codegen_set_op32(void); extern void codegen_flush(void); extern void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr); struct ir_data_t; -x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset); +x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset); extern void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); extern void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg); @@ -338,7 +308,7 @@ extern int codegen_purge_purgable_list(void); will only be called when the allocator is out of memory*/ extern void codegen_delete_random_block(int required_mem_block); -extern int cpu_block_end; +extern int cpu_block_end; extern uint32_t codegen_endpc; extern int cpu_reps; @@ -353,14 +323,13 @@ extern void (*codegen_timing_block_start)(void); extern void (*codegen_timing_block_end)(void); extern int (*codegen_timing_jump_cycles)(void); -typedef struct codegen_timing_t -{ - void (*start)(void); - void (*prefix)(uint8_t prefix, uint32_t fetchdat); - void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); - void (*block_start)(void); - void (*block_end)(void); - int (*jump_cycles)(void); +typedef struct codegen_timing_t { + void (*start)(void); + void (*prefix)(uint8_t prefix, uint32_t fetchdat); + void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc); + void (*block_start)(void); + void (*block_end)(void); + int (*jump_cycles)(void); } codegen_timing_t; extern codegen_timing_t codegen_timing_pentium; @@ -371,7 +340,6 @@ extern codegen_timing_t codegen_timing_winchip2; extern codegen_timing_t codegen_timing_k6; extern codegen_timing_t codegen_timing_p6; - void codegen_timing_set(codegen_timing_t *timing); extern int block_current; @@ -382,8 +350,8 @@ extern int block_pos; /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; -extern x86seg *op_ea_seg; -extern int op_ssegs; +extern x86seg *op_ea_seg; +extern int op_ssegs; extern uint32_t op_old_pc; /*Set to 1 if flags have been changed in the block being recompiled, and hence @@ -400,11 +368,11 @@ extern int codegen_in_recompile; void codegen_generate_reset(void); -int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP); +int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP); void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction); #ifdef DEBUG_EXTRA -extern uint32_t instr_counts[256*256]; +extern uint32_t instr_counts[256 * 256]; #endif #endif diff --git a/src/codegen_new/codegen_accumulate.c b/src/codegen_new/codegen_accumulate.c index b9ec78577..d9ae38af8 100644 --- a/src/codegen_new/codegen_accumulate.c +++ b/src/codegen_new/codegen_accumulate.c @@ -9,34 +9,36 @@ static struct { - int count; - int dest_reg; -} acc_regs[] = -{ - [ACCREG_cycles] = {0, IREG_cycles} + int count; + int dest_reg; +} acc_regs[] = { + [ACCREG_cycles] = {0, IREG_cycles} }; -void codegen_accumulate(ir_data_t *ir, int acc_reg, int delta) +void +codegen_accumulate(ir_data_t *ir, int acc_reg, int delta) { - acc_regs[acc_reg].count += delta; + acc_regs[acc_reg].count += delta; #ifdef USE_ACYCS - if ((acc_reg == ACCREG_cycles) && (delta != 0)) { - uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta); - } + if ((acc_reg == ACCREG_cycles) && (delta != 0)) { + uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta); + } #endif } -void codegen_accumulate_flush(ir_data_t *ir) +void +codegen_accumulate_flush(ir_data_t *ir) { - if (acc_regs[0].count) { - uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count); - } + if (acc_regs[0].count) { + uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count); + } - acc_regs[0].count = 0; + acc_regs[0].count = 0; } -void codegen_accumulate_reset(void) +void +codegen_accumulate_reset(void) { - acc_regs[0].count = 0; + acc_regs[0].count = 0; } diff --git a/src/codegen_new/codegen_accumulate.h b/src/codegen_new/codegen_accumulate.h index ccbed2afa..5744c6362 100644 --- a/src/codegen_new/codegen_accumulate.h +++ b/src/codegen_new/codegen_accumulate.h @@ -1,8 +1,7 @@ -enum -{ - ACCREG_cycles = 0, +enum { + ACCREG_cycles = 0, - ACCREG_COUNT + ACCREG_COUNT }; struct ir_data_t; diff --git a/src/codegen_new/codegen_allocator.c b/src/codegen_new/codegen_allocator.c index 84f837a97..2badc35e8 100644 --- a/src/codegen_new/codegen_allocator.c +++ b/src/codegen_new/codegen_allocator.c @@ -1,10 +1,10 @@ #if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) -#include -#include -#include +# include +# include +# include #endif #if defined WIN32 || defined _WIN32 || defined _WIN32 -#include +# include #endif #include @@ -17,118 +17,116 @@ #include "codegen.h" #include "codegen_allocator.h" -typedef struct mem_block_t -{ - uint32_t offset; /*Offset into mem_block_alloc*/ - uint32_t next; - uint16_t code_block; +typedef struct mem_block_t { + uint32_t offset; /*Offset into mem_block_alloc*/ + uint32_t next; + uint16_t code_block; } mem_block_t; static mem_block_t mem_blocks[MEM_BLOCK_NR]; -static uint32_t mem_block_free_list; -static uint8_t *mem_block_alloc = NULL; +static uint32_t mem_block_free_list; +static uint8_t *mem_block_alloc = NULL; int codegen_allocator_usage = 0; -void codegen_allocator_init(void) +void +codegen_allocator_init(void) { - int c; + int c; #if defined WIN32 || defined _WIN32 || defined _WIN32 - mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - /* TODO: check deployment target: older Intel-based versions of macOS don't play - nice with MAP_JIT. */ + mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + /* TODO: check deployment target: older Intel-based versions of macOS don't play + nice with MAP_JIT. */ #elif defined(__APPLE__) && defined(MAP_JIT) - mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_JIT, -1, 0); + mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0); #else - mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0); + mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); #endif - for (c = 0; c < MEM_BLOCK_NR; c++) - { - mem_blocks[c].offset = c * MEM_BLOCK_SIZE; - mem_blocks[c].code_block = BLOCK_INVALID; - if (c < MEM_BLOCK_NR-1) - mem_blocks[c].next = c+2; - else - mem_blocks[c].next = 0; - } - mem_block_free_list = 1; -} - -mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block) -{ - mem_block_t *block; - uint32_t block_nr; - - while (!mem_block_free_list) - { - /*Pick a random memory block and free the owning code block*/ - block_nr = rand() & MEM_BLOCK_MASK; - block = &mem_blocks[block_nr]; - - if (block->code_block && block->code_block != code_block) - codegen_delete_block(&codeblock[block->code_block]); - } - - /*Remove from free list*/ - block_nr = mem_block_free_list; - block = &mem_blocks[block_nr-1]; - mem_block_free_list = block->next; - - block->code_block = code_block; - if (parent) - { - /*Add to parent list*/ - block->next = parent->next; - parent->next = block_nr; - } + for (c = 0; c < MEM_BLOCK_NR; c++) { + mem_blocks[c].offset = c * MEM_BLOCK_SIZE; + mem_blocks[c].code_block = BLOCK_INVALID; + if (c < MEM_BLOCK_NR - 1) + mem_blocks[c].next = c + 2; else - block->next = 0; - - codegen_allocator_usage++; - return block; + mem_blocks[c].next = 0; + } + mem_block_free_list = 1; } -void codegen_allocator_free(mem_block_t *block) + +mem_block_t * +codegen_allocator_allocate(mem_block_t *parent, int code_block) { - int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1; + mem_block_t *block; + uint32_t block_nr; - while (1) - { - int next_block_nr = block->next; - codegen_allocator_usage--; + while (!mem_block_free_list) { + /*Pick a random memory block and free the owning code block*/ + block_nr = rand() & MEM_BLOCK_MASK; + block = &mem_blocks[block_nr]; - block->next = mem_block_free_list; - block->code_block = BLOCK_INVALID; - mem_block_free_list = block_nr; - block_nr = next_block_nr; + if (block->code_block && block->code_block != code_block) + codegen_delete_block(&codeblock[block->code_block]); + } - if (block_nr) - block = &mem_blocks[block_nr - 1]; - else - break; - } + /*Remove from free list*/ + block_nr = mem_block_free_list; + block = &mem_blocks[block_nr - 1]; + mem_block_free_list = block->next; + + block->code_block = code_block; + if (parent) { + /*Add to parent list*/ + block->next = parent->next; + parent->next = block_nr; + } else + block->next = 0; + + codegen_allocator_usage++; + return block; } - -uint8_t *codeblock_allocator_get_ptr(mem_block_t *block) +void +codegen_allocator_free(mem_block_t *block) { - return &mem_block_alloc[block->offset]; + int block_nr = (((uintptr_t) block - (uintptr_t) mem_blocks) / sizeof(mem_block_t)) + 1; + + while (1) { + int next_block_nr = block->next; + codegen_allocator_usage--; + + block->next = mem_block_free_list; + block->code_block = BLOCK_INVALID; + mem_block_free_list = block_nr; + block_nr = next_block_nr; + + if (block_nr) + block = &mem_blocks[block_nr - 1]; + else + break; + } } -void codegen_allocator_clean_blocks(struct mem_block_t *block) +uint8_t * +codeblock_allocator_get_ptr(mem_block_t *block) +{ + return &mem_block_alloc[block->offset]; +} + +void +codegen_allocator_clean_blocks(struct mem_block_t *block) { #if defined __ARM_EABI__ || defined _ARM_ || defined __aarch64__ || defined _M_ARM || defined _M_ARM64 - while (1) - { -#ifndef _MSC_VER - __clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]); -#else - FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE); -#endif - if (block->next) - block = &mem_blocks[block->next - 1]; - else - break; - } + while (1) { +# ifndef _MSC_VER + __clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]); +# else + FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE); +# endif + if (block->next) + block = &mem_blocks[block->next - 1]; + else + break; + } #endif } diff --git a/src/codegen_new/codegen_allocator.h b/src/codegen_new/codegen_allocator.h index 1b808f127..21d4dbb0c 100644 --- a/src/codegen_new/codegen_allocator.h +++ b/src/codegen_new/codegen_allocator.h @@ -14,12 +14,12 @@ instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to +/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#define MEM_BLOCK_NR 32768 +# define MEM_BLOCK_NR 32768 #else -#define MEM_BLOCK_NR 131072 +# define MEM_BLOCK_NR 131072 #endif -#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1) +#define MEM_BLOCK_MASK (MEM_BLOCK_NR - 1) #define MEM_BLOCK_SIZE 0x3c0 void codegen_allocator_init(void); diff --git a/src/codegen_new/codegen_backend.h b/src/codegen_new/codegen_backend.h index c45e0be88..901b5e9d9 100644 --- a/src/codegen_new/codegen_backend.h +++ b/src/codegen_new/codegen_backend.h @@ -2,15 +2,15 @@ #define _CODEGEN_BACKEND_H_ #if defined __amd64__ || defined _M_X64 -#include "codegen_backend_x86-64.h" +# include "codegen_backend_x86-64.h" #elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include "codegen_backend_x86.h" +# include "codegen_backend_x86.h" #elif defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include "codegen_backend_arm.h" +# include "codegen_backend_arm.h" #elif defined __aarch64__ || defined _M_ARM64 -#include "codegen_backend_arm64.h" +# include "codegen_backend_arm64.h" #else -#error Dynamic recompiler not implemented on your platform +# error Dynamic recompiler not implemented on your platform #endif void codegen_backend_init(void); @@ -29,10 +29,9 @@ extern const uOpFn uop_handlers[]; /*Register will not be preserved across function calls*/ #define HOST_REG_FLAG_VOLATILE (1 << 0) -typedef struct host_reg_def_t -{ - int reg; - int flags; +typedef struct host_reg_def_t { + int reg; + int flags; } host_reg_def_t; extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS]; diff --git a/src/codegen_new/codegen_backend_arm.c b/src/codegen_new/codegen_backend_arm.c index 478a97f0d..a389f239f 100644 --- a/src/codegen_new/codegen_backend_arm.c +++ b/src/codegen_new/codegen_backend_arm.c @@ -1,28 +1,28 @@ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm_defs.h" -#include "codegen_backend_arm_ops.h" -#include "codegen_reg.h" -#include "x86.h" -#include "x87.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm_defs.h" +# include "codegen_backend_arm_ops.h" +# include "codegen_reg.h" +# include "x86.h" +# include "x87.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -43,329 +43,325 @@ void *codegen_fp_round; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - {REG_R4, 0}, - {REG_R5, 0}, - {REG_R6, 0}, - {REG_R7, 0}, - {REG_R8, 0}, - {REG_R9, 0}, - {REG_R11, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + {REG_R4, 0}, + { REG_R5, 0}, + { REG_R6, 0}, + { REG_R7, 0}, + { REG_R8, 0}, + { REG_R9, 0}, + { REG_R11, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ - {REG_D8, 0}, - {REG_D9, 0}, - {REG_D10, 0}, - {REG_D11, 0}, - {REG_D12, 0}, - {REG_D13, 0}, - {REG_D14, 0}, - {REG_D15, 0} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { + {REG_D8, 0}, + { REG_D9, 0}, + { REG_D10, 0}, + { REG_D11, 0}, + { REG_D12, 0}, + { REG_D13, 0}, + { REG_D14, 0}, + { REG_D15, 0} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - R0 = address - Out - R0 = data, R1 = abrt*/ - /*MOV R1, R0, LSR #12 - MOV R2, #readlookup2 - LDR R1, [R2, R1, LSL #2] - CMP R1, #-1 - BNE + - LDRB R0, [R1, R0] - MOV R1, #0 - MOV PC, LR - * STR LR, [SP, -4]! - BL readmembl - LDRB R1, cpu_state.abrt - LDR PC, [SP], #4 - */ - codegen_alloc(block, 80); - host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12); - host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2); - host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2); - if (size != 1) - { - host_arm_TST_IMM(block, REG_R0, size-1); - misaligned_offset = host_arm_BNE_(block); - } - host_arm_CMP_IMM(block, REG_R1, -1); - branch_offset = host_arm_BEQ_(block); - if (size == 1 && !is_float) - host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 2 && !is_float) - host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 4 && !is_float) - host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0); - else if (size == 4 && is_float) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); - host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); - } - else if (size == 8) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); - host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); - } - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_MOV_REG(block, REG_PC, REG_LR); + /*In - R0 = address + Out - R0 = data, R1 = abrt*/ + /*MOV R1, R0, LSR #12 + MOV R2, #readlookup2 + LDR R1, [R2, R1, LSL #2] + CMP R1, #-1 + BNE + + LDRB R0, [R1, R0] + MOV R1, #0 + MOV PC, LR + * STR LR, [SP, -4]! + BL readmembl + LDRB R1, cpu_state.abrt + LDR PC, [SP], #4 + */ + codegen_alloc(block, 80); + host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12); + host_arm_MOV_IMM(block, REG_R2, (uint32_t) readlookup2); + host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2); + if (size != 1) { + host_arm_TST_IMM(block, REG_R0, size - 1); + misaligned_offset = host_arm_BNE_(block); + } + host_arm_CMP_IMM(block, REG_R1, -1); + branch_offset = host_arm_BEQ_(block); + if (size == 1 && !is_float) + host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 2 && !is_float) + host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 4 && !is_float) + host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0); + else if (size == 4 && is_float) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); + host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0); + } else if (size == 8) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1); + host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0); + } + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_MOV_REG(block, REG_PC, REG_LR); - *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; - if (size != 1) - *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; - host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); - if (size == 1) - host_arm_BL(block, (uintptr_t)readmembl); - else if (size == 2) - host_arm_BL(block, (uintptr_t)readmemwl); - else if (size == 4) - host_arm_BL(block, (uintptr_t)readmemll); - else if (size == 8) - host_arm_BL(block, (uintptr_t)readmemql); - else - fatal("build_load_routine - unknown size %i\n", size); - if (size == 4 && is_float) - host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); - else if (size == 8) - host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); - host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); - host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); + *branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2; + host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); + if (size == 1) + host_arm_BL(block, (uintptr_t) readmembl); + else if (size == 2) + host_arm_BL(block, (uintptr_t) readmemwl); + else if (size == 4) + host_arm_BL(block, (uintptr_t) readmemll); + else if (size == 8) + host_arm_BL(block, (uintptr_t) readmemql); + else + fatal("build_load_routine - unknown size %i\n", size); + if (size == 4 && is_float) + host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0); + else if (size == 8) + host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); + host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - R0 = address - Out - R0 = data, R1 = abrt*/ - /*MOV R1, R0, LSR #12 - MOV R2, #readlookup2 - LDR R1, [R2, R1, LSL #2] - CMP R1, #-1 - BNE + - LDRB R0, [R1, R0] - MOV R1, #0 - MOV PC, LR - * STR LR, [SP, -4]! - BL readmembl - LDRB R1, cpu_state.abrt - LDR PC, [SP], #4 - */ - codegen_alloc(block, 80); - host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12); - host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2); - host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2); - if (size != 1) - { - host_arm_TST_IMM(block, REG_R0, size-1); - misaligned_offset = host_arm_BNE_(block); - } - host_arm_CMP_IMM(block, REG_R2, -1); - branch_offset = host_arm_BEQ_(block); - if (size == 1 && !is_float) - host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 2 && !is_float) - host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 4 && !is_float) - host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0); - else if (size == 4 && is_float) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); - host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0); - } - else if (size == 8) - { - host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); - host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0); - } - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_MOV_REG(block, REG_PC, REG_LR); + /*In - R0 = address + Out - R0 = data, R1 = abrt*/ + /*MOV R1, R0, LSR #12 + MOV R2, #readlookup2 + LDR R1, [R2, R1, LSL #2] + CMP R1, #-1 + BNE + + LDRB R0, [R1, R0] + MOV R1, #0 + MOV PC, LR + * STR LR, [SP, -4]! + BL readmembl + LDRB R1, cpu_state.abrt + LDR PC, [SP], #4 + */ + codegen_alloc(block, 80); + host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12); + host_arm_MOV_IMM(block, REG_R3, (uint32_t) writelookup2); + host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2); + if (size != 1) { + host_arm_TST_IMM(block, REG_R0, size - 1); + misaligned_offset = host_arm_BNE_(block); + } + host_arm_CMP_IMM(block, REG_R2, -1); + branch_offset = host_arm_BEQ_(block); + if (size == 1 && !is_float) + host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 2 && !is_float) + host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 4 && !is_float) + host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0); + else if (size == 4 && is_float) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); + host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0); + } else if (size == 8) { + host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2); + host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0); + } + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_MOV_REG(block, REG_PC, REG_LR); - *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; - if (size != 1) - *misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2; - host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); - if (size == 4 && is_float) - host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); - else if (size == 8) - host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); - if (size == 1) - host_arm_BL(block, (uintptr_t)writemembl); - else if (size == 2) - host_arm_BL(block, (uintptr_t)writememwl); - else if (size == 4) - host_arm_BL(block, (uintptr_t)writememll); - else if (size == 8) - host_arm_BL_r1(block, (uintptr_t)writememql); - else - fatal("build_store_routine - unknown size %i\n", size); - host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); - host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); + *branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2; + if (size != 1) + *misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2; + host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4); + if (size == 4 && is_float) + host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP); + else if (size == 8) + host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP); + if (size == 1) + host_arm_BL(block, (uintptr_t) writemembl); + else if (size == 2) + host_arm_BL(block, (uintptr_t) writememwl); + else if (size == 4) + host_arm_BL(block, (uintptr_t) writememll); + else if (size == 8) + host_arm_BL_r1(block, (uintptr_t) writememql); + else + fatal("build_store_routine - unknown size %i\n", size); + host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt); + host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4); } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &block_write_data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &block_write_data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &block_write_data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &block_write_data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &block_write_data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &block_write_data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &block_write_data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &block_write_data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &block_write_data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &block_write_data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &block_write_data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &block_write_data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &block_write_data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &block_write_data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &block_write_data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &block_write_data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &block_write_data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &block_write_data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &block_write_data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &block_write_data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &block_write_data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &block_write_data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &block_write_data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &block_write_data[block_pos]; + build_store_routine(block, 8, 1); } /*VFP has a specific round-to-zero instruction, and the default rounding mode is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/ -#define FPCSR_ROUNDING_MASK (3 << 22) -#define FPCSR_ROUNDING_UP (1 << 22) -#define FPCSR_ROUNDING_DOWN (2 << 22) +# define FPCSR_ROUNDING_MASK (3 << 22) +# define FPCSR_ROUNDING_UP (1 << 22) +# define FPCSR_ROUNDING_DOWN (2 << 22) -static void build_fp_round_routine(codeblock_t *block) +static void +build_fp_round_routine(codeblock_t *block) { - uint32_t *jump_table; + uint32_t *jump_table; - codegen_alloc(block, 80); + codegen_alloc(block, 80); - host_arm_MOV_REG(block, REG_TEMP2, REG_LR); - host_arm_MOV_REG(block, REG_LR, REG_TEMP2); - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); - host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); - host_arm_NOP(block); + host_arm_MOV_REG(block, REG_TEMP2, REG_LR); + host_arm_MOV_REG(block, REG_LR, REG_TEMP2); + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state); + host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP); + host_arm_NOP(block); - jump_table = (uint32_t *)&block_write_data[block_pos]; - host_arm_NOP(block); - host_arm_NOP(block); - host_arm_NOP(block); - host_arm_NOP(block); + jump_table = (uint32_t *) &block_write_data[block_pos]; + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); + host_arm_NOP(block); - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even - host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); - host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); - host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP); - host_arm_VMSR_FPSCR(block, REG_TEMP2); - host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_VMSR_FPSCR(block, REG_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state); + host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); + host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP); + host_arm_VMSR_FPSCR(block, REG_TEMP2); + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_VMSR_FPSCR(block, REG_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state); - host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); - host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN); - host_arm_VMSR_FPSCR(block, REG_TEMP2); - host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_VMSR_FPSCR(block, REG_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state); + host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK); + host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN); + host_arm_VMSR_FPSCR(block, REG_TEMP2); + host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_VMSR_FPSCR(block, REG_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero - host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); - host_arm_MOV_REG(block, REG_PC, REG_LR); + jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero + host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP); + host_arm_MOV_REG(block, REG_PC, REG_LR); } -void codegen_backend_init(void) +void +codegen_backend_init(void) { - codeblock_t *block; - int c; + codeblock_t *block; + int c; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block_write_data = block->data; - build_loadstore_routines(&codeblock[block_current]); -//pclog("block_pos=%i\n", block_pos); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(&codeblock[block_current]); + // pclog("block_pos=%i\n", block_pos); - codegen_fp_round = &block_write_data[block_pos]; - build_fp_round_routine(&codeblock[block_current]); + codegen_fp_round = &block_write_data[block_pos]; + build_fp_round_routine(&codeblock[block_current]); - codegen_alloc(block, 80); - codegen_gpf_rout = &block_write_data[block_pos]; - host_arm_MOV_IMM(block, REG_R0, 0); - host_arm_MOV_IMM(block, REG_R1, 0); - host_arm_call(block, x86gpf); + codegen_alloc(block, 80); + codegen_gpf_rout = &block_write_data[block_pos]; + host_arm_MOV_IMM(block, REG_R0, 0); + host_arm_MOV_IMM(block, REG_R1, 0); + host_arm_call(block, x86gpf); - codegen_exit_rout = &block_write_data[block_pos]; - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); + codegen_exit_rout = &block_write_data[block_pos]; + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - block_write_data = NULL; -//fatal("block_pos=%i\n", block_pos); - asm("vmrs %0, fpscr\n" - : "=r" (cpu_state.old_fp_control) - ); - if ((cpu_state.old_fp_control >> 22) & 3) - fatal("VFP not in nearest rounding mode\n"); + block_write_data = NULL; + // fatal("block_pos=%i\n", block_pos); + asm("vmrs %0, fpscr\n" + : "=r"(cpu_state.old_fp_control)); + if ((cpu_state.old_fp_control >> 22) & 3) + fatal("VFP not in nearest rounding mode\n"); } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - if (mode < 0 || mode > 3) - fatal("codegen_set_rounding_mode - invalid mode\n"); - cpu_state.new_fp_control = mode << 2; + if (mode < 0 || mode > 3) + fatal("codegen_set_rounding_mode - invalid mode\n"); + cpu_state.new_fp_control = mode << 2; } /*R10 - cpu_state*/ -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; + block_pos = BLOCK_START; - /*Entry code*/ + /*Entry code*/ - host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); - host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); - host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - } + host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR); + host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t) &cpu_state); + if (block->flags & CODEBLOCK_HAS_FPU) { + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); + host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + } } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); - host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); + host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40); + host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC); - codegen_allocator_clean_blocks(block->head_mem_block); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_new/codegen_backend_arm.h b/src/codegen_new/codegen_backend_arm.h index 8b8936a98..a3e236d4e 100644 --- a/src/codegen_new/codegen_backend_arm.h +++ b/src/codegen_new/codegen_backend_arm.h @@ -1,15 +1,15 @@ #include "codegen_backend_arm_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) -#define BLOCK_MAX 0x3c0 +#define BLOCK_MAX 0x3c0 void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask); diff --git a/src/codegen_new/codegen_backend_arm64.c b/src/codegen_new/codegen_backend_arm64.c index 8941285cd..48d949406 100644 --- a/src/codegen_new/codegen_backend_arm64.c +++ b/src/codegen_new/codegen_backend_arm64.c @@ -1,28 +1,28 @@ #if defined __aarch64__ || defined _M_ARM64 -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm64_defs.h" -#include "codegen_backend_arm64_ops.h" -#include "codegen_reg.h" -#include "x86.h" -#include "x87.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm64_defs.h" +# include "codegen_backend_arm64_ops.h" +# include "codegen_reg.h" +# include "x86.h" +# include "x87.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -44,334 +44,335 @@ void *codegen_fp_round_quad; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - {REG_X19, 0}, - {REG_X20, 0}, - {REG_X21, 0}, - {REG_X22, 0}, - {REG_X23, 0}, - {REG_X24, 0}, - {REG_X25, 0}, - {REG_X26, 0}, - {REG_X27, 0}, - {REG_X28, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + {REG_X19, 0}, + { REG_X20, 0}, + { REG_X21, 0}, + { REG_X22, 0}, + { REG_X23, 0}, + { REG_X24, 0}, + { REG_X25, 0}, + { REG_X26, 0}, + { REG_X27, 0}, + { REG_X28, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ - {REG_V8, 0}, - {REG_V9, 0}, - {REG_V10, 0}, - {REG_V11, 0}, - {REG_V12, 0}, - {REG_V13, 0}, - {REG_V14, 0}, - {REG_V15, 0} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { + {REG_V8, 0}, + { REG_V9, 0}, + { REG_V10, 0}, + { REG_V11, 0}, + { REG_V12, 0}, + { REG_V13, 0}, + { REG_V14, 0}, + { REG_V15, 0} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - W0 = address - Out - W0 = data, W1 = abrt*/ - /*MOV W1, W0, LSR #12 - MOV X2, #readlookup2 - LDR X1, [X2, X1, LSL #3] - CMP X1, #-1 - BEQ + - LDRB W0, [X1, X0] - MOV W1, #0 - RET - * STP X29, X30, [SP, #-16] - BL readmembl - LDRB R1, cpu_state.abrt - LDP X29, X30, [SP, #-16] - RET - */ - codegen_alloc(block, 80); - host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); - host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2); - host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); - if (size != 1) - { - host_arm64_TST_IMM(block, REG_W0, size-1); - misaligned_offset = host_arm64_BNE_(block); - } - host_arm64_CMPX_IMM(block, REG_X1, -1); - branch_offset = host_arm64_BEQ_(block); - if (size == 1 && !is_float) - host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 2 && !is_float) - host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 4 && !is_float) - host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); - else if (size == 4 && is_float) - host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); - else if (size == 8) - host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); - host_arm64_MOVZ_IMM(block, REG_W1, 0); - host_arm64_RET(block, REG_X30); + /*In - W0 = address + Out - W0 = data, W1 = abrt*/ + /*MOV W1, W0, LSR #12 + MOV X2, #readlookup2 + LDR X1, [X2, X1, LSL #3] + CMP X1, #-1 + BEQ + + LDRB W0, [X1, X0] + MOV W1, #0 + RET + * STP X29, X30, [SP, #-16] + BL readmembl + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + codegen_alloc(block, 80); + host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12); + host_arm64_MOVX_IMM(block, REG_X2, (uint64_t) readlookup2); + host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1); + if (size != 1) { + host_arm64_TST_IMM(block, REG_W0, size - 1); + misaligned_offset = host_arm64_BNE_(block); + } + host_arm64_CMPX_IMM(block, REG_X1, -1); + branch_offset = host_arm64_BEQ_(block); + if (size == 1 && !is_float) + host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 2 && !is_float) + host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 4 && !is_float) + host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0); + else if (size == 4 && is_float) + host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0); + else if (size == 8) + host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0); + host_arm64_MOVZ_IMM(block, REG_W1, 0); + host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); - if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); - if (size == 1) - host_arm64_call(block, (void *)readmembl); - else if (size == 2) - host_arm64_call(block, (void *)readmemwl); - else if (size == 4) - host_arm64_call(block, (void *)readmemll); - else if (size == 8) - host_arm64_call(block, (void *)readmemql); - else - fatal("build_load_routine - unknown size %i\n", size); - codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); - if (size == 4 && is_float) - host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); - else if (size == 8) - host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); + if (size != 1) + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + if (size == 1) + host_arm64_call(block, (void *) readmembl); + else if (size == 2) + host_arm64_call(block, (void *) readmemwl); + else if (size == 4) + host_arm64_call(block, (void *) readmemll); + else if (size == 8) + host_arm64_call(block, (void *) readmemql); + else + fatal("build_load_routine - unknown size %i\n", size); + codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + if (size == 4 && is_float) + host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0); + else if (size == 8) + host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint32_t *branch_offset; - uint32_t *misaligned_offset; + uint32_t *branch_offset; + uint32_t *misaligned_offset; - /*In - R0 = address, R1 = data - Out - R1 = abrt*/ - /*MOV W2, W0, LSR #12 - MOV X3, #writelookup2 - LDR X2, [X3, X2, LSL #3] - CMP X2, #-1 - BEQ + - STRB W1, [X2, X0] - MOV W1, #0 - RET - * STP X29, X30, [SP, #-16] - BL writemembl - LDRB R1, cpu_state.abrt - LDP X29, X30, [SP, #-16] - RET - */ - codegen_alloc(block, 80); - host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); - host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2); - host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); - if (size != 1) - { - host_arm64_TST_IMM(block, REG_W0, size-1); - misaligned_offset = host_arm64_BNE_(block); - } - host_arm64_CMPX_IMM(block, REG_X2, -1); - branch_offset = host_arm64_BEQ_(block); - if (size == 1 && !is_float) - host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 2 && !is_float) - host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 4 && !is_float) - host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); - else if (size == 4 && is_float) - host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0); - else if (size == 8) - host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0); - host_arm64_MOVZ_IMM(block, REG_X1, 0); - host_arm64_RET(block, REG_X30); + /*In - R0 = address, R1 = data + Out - R1 = abrt*/ + /*MOV W2, W0, LSR #12 + MOV X3, #writelookup2 + LDR X2, [X3, X2, LSL #3] + CMP X2, #-1 + BEQ + + STRB W1, [X2, X0] + MOV W1, #0 + RET + * STP X29, X30, [SP, #-16] + BL writemembl + LDRB R1, cpu_state.abrt + LDP X29, X30, [SP, #-16] + RET + */ + codegen_alloc(block, 80); + host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12); + host_arm64_MOVX_IMM(block, REG_X3, (uint64_t) writelookup2); + host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2); + if (size != 1) { + host_arm64_TST_IMM(block, REG_W0, size - 1); + misaligned_offset = host_arm64_BNE_(block); + } + host_arm64_CMPX_IMM(block, REG_X2, -1); + branch_offset = host_arm64_BEQ_(block); + if (size == 1 && !is_float) + host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 2 && !is_float) + host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 4 && !is_float) + host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0); + else if (size == 4 && is_float) + host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0); + else if (size == 8) + host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0); + host_arm64_MOVZ_IMM(block, REG_X1, 0); + host_arm64_RET(block, REG_X30); - host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); - if (size != 1) - host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); - if (size == 4 && is_float) - host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); - else if (size == 8) - host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); - if (size == 1) - host_arm64_call(block, (void *)writemembl); - else if (size == 2) - host_arm64_call(block, (void *)writememwl); - else if (size == 4) - host_arm64_call(block, (void *)writememll); - else if (size == 8) - host_arm64_call(block, (void *)writememql); - else - fatal("build_store_routine - unknown size %i\n", size); - codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); + if (size != 1) + host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + if (size == 4 && is_float) + host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP); + else if (size == 8) + host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP); + if (size == 1) + host_arm64_call(block, (void *) writemembl); + else if (size == 2) + host_arm64_call(block, (void *) writememwl); + else if (size == 4) + host_arm64_call(block, (void *) writememll); + else if (size == 8) + host_arm64_call(block, (void *) writememql); + else + fatal("build_store_routine - unknown size %i\n", size); + codegen_direct_read_8(block, REG_W1, &cpu_state.abrt); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &block_write_data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &block_write_data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &block_write_data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &block_write_data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &block_write_data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &block_write_data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &block_write_data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &block_write_data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &block_write_data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &block_write_data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &block_write_data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &block_write_data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &block_write_data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &block_write_data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &block_write_data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &block_write_data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &block_write_data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &block_write_data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &block_write_data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &block_write_data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &block_write_data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &block_write_data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &block_write_data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &block_write_data[block_pos]; + build_store_routine(block, 8, 1); } -static void build_fp_round_routine(codeblock_t *block, int is_quad) +static void +build_fp_round_routine(codeblock_t *block, int is_quad) { - uint64_t *jump_table; + uint64_t *jump_table; - codegen_alloc(block, 80); - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state); - host_arm64_ADR(block, REG_TEMP2, 12); - host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); - host_arm64_BR(block, REG_TEMP2); + codegen_alloc(block, 80); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state); + host_arm64_ADR(block, REG_TEMP2, 12); + host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP); + host_arm64_BR(block, REG_TEMP2); - jump_table = (uint64_t *)&block_write_data[block_pos]; - block_pos += 4*8; + jump_table = (uint64_t *) &block_write_data[block_pos]; + block_pos += 4 * 8; - jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even - if (is_quad) - host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even + if (is_quad) + host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf - if (is_quad) - host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf + if (is_quad) + host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf - if (is_quad) - host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf + if (is_quad) + host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); - jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero - if (is_quad) - host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); - else - host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); - host_arm64_RET(block, REG_X30); + jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero + if (is_quad) + host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP); + else + host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP); + host_arm64_RET(block, REG_X30); } -void codegen_backend_init(void) +void +codegen_backend_init(void) { - codeblock_t *block; - int c; + codeblock_t *block; + int c; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].pc = BLOCK_PC_INVALID; - } + for (c = 0; c < BLOCK_SIZE; c++) { + codeblock[c].pc = BLOCK_PC_INVALID; + } - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block_write_data = block->data; - build_loadstore_routines(block); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); - codegen_fp_round = &block_write_data[block_pos]; - build_fp_round_routine(block, 0); - codegen_fp_round_quad = &block_write_data[block_pos]; - build_fp_round_routine(block, 1); + codegen_fp_round = &block_write_data[block_pos]; + build_fp_round_routine(block, 0); + codegen_fp_round_quad = &block_write_data[block_pos]; + build_fp_round_routine(block, 1); - codegen_alloc(block, 80); - codegen_gpf_rout = &block_write_data[block_pos]; - host_arm64_mov_imm(block, REG_ARG0, 0); - host_arm64_mov_imm(block, REG_ARG1, 0); - host_arm64_call(block, (void *)x86gpf); + codegen_alloc(block, 80); + codegen_gpf_rout = &block_write_data[block_pos]; + host_arm64_mov_imm(block, REG_ARG0, 0); + host_arm64_mov_imm(block, REG_ARG1, 0); + host_arm64_call(block, (void *) x86gpf); - codegen_exit_rout = &block_write_data[block_pos]; - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + codegen_exit_rout = &block_write_data[block_pos]; + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); - block_write_data = NULL; + block_write_data = NULL; - codegen_allocator_clean_blocks(block->head_mem_block); + codegen_allocator_clean_blocks(block->head_mem_block); - asm("mrs %0, fpcr\n" - : "=r" (cpu_state.old_fp_control) - ); + asm("mrs %0, fpcr\n" + : "=r"(cpu_state.old_fp_control)); } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - if (mode < 0 || mode > 3) - fatal("codegen_set_rounding_mode - invalid mode\n"); - cpu_state.new_fp_control = mode << 3; + if (mode < 0 || mode > 3) + fatal("codegen_set_rounding_mode - invalid mode\n"); + cpu_state.new_fp_control = mode << 3; } /*R10 - cpu_state*/ -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; + block_pos = BLOCK_START; - /*Entry code*/ + /*Entry code*/ - host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16); - host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64); + host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16); + host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64); - host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state); + host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t) &cpu_state); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - } + if (block->flags & CODEBLOCK_HAS_FPU) { + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + } } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); - host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); - host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); - host_arm64_RET(block, REG_X30); + host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64); + host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16); + host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16); + host_arm64_RET(block, REG_X30); - codegen_allocator_clean_blocks(block->head_mem_block); + codegen_allocator_clean_blocks(block->head_mem_block); } #endif diff --git a/src/codegen_new/codegen_backend_arm64.h b/src/codegen_new/codegen_backend_arm64.h index 3e3d16575..bf3084f58 100644 --- a/src/codegen_new/codegen_backend_arm64.h +++ b/src/codegen_new/codegen_backend_arm64.h @@ -1,16 +1,15 @@ #include "codegen_backend_arm64_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) - -#define BLOCK_MAX 0x3c0 +#define HASH(l) ((l) &0x1ffff) +#define BLOCK_MAX 0x3c0 void host_arm64_BLR(codeblock_t *block, int addr_reg); void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); diff --git a/src/codegen_new/codegen_backend_arm64_defs.h b/src/codegen_new/codegen_backend_arm64_defs.h index ac2d238da..c36f1c4a2 100644 --- a/src/codegen_new/codegen_backend_arm64_defs.h +++ b/src/codegen_new/codegen_backend_arm64_defs.h @@ -1,117 +1,117 @@ -#define REG_W0 0 -#define REG_W1 1 -#define REG_W2 2 -#define REG_W3 3 -#define REG_W4 4 -#define REG_W5 5 -#define REG_W6 6 -#define REG_W7 7 -#define REG_W8 8 -#define REG_W9 9 -#define REG_W10 10 -#define REG_W11 11 -#define REG_W12 12 -#define REG_W13 13 -#define REG_W14 14 -#define REG_W15 15 -#define REG_W16 16 -#define REG_W17 17 -#define REG_W18 18 -#define REG_W19 19 -#define REG_W20 20 -#define REG_W21 21 -#define REG_W22 22 -#define REG_W23 23 -#define REG_W24 24 -#define REG_W25 25 -#define REG_W26 26 -#define REG_W27 27 -#define REG_W28 28 -#define REG_W29 29 -#define REG_W30 30 -#define REG_WZR 31 +#define REG_W0 0 +#define REG_W1 1 +#define REG_W2 2 +#define REG_W3 3 +#define REG_W4 4 +#define REG_W5 5 +#define REG_W6 6 +#define REG_W7 7 +#define REG_W8 8 +#define REG_W9 9 +#define REG_W10 10 +#define REG_W11 11 +#define REG_W12 12 +#define REG_W13 13 +#define REG_W14 14 +#define REG_W15 15 +#define REG_W16 16 +#define REG_W17 17 +#define REG_W18 18 +#define REG_W19 19 +#define REG_W20 20 +#define REG_W21 21 +#define REG_W22 22 +#define REG_W23 23 +#define REG_W24 24 +#define REG_W25 25 +#define REG_W26 26 +#define REG_W27 27 +#define REG_W28 28 +#define REG_W29 29 +#define REG_W30 30 +#define REG_WZR 31 -#define REG_X0 0 -#define REG_X1 1 -#define REG_X2 2 -#define REG_X3 3 -#define REG_X4 4 -#define REG_X5 5 -#define REG_X6 6 -#define REG_X7 7 -#define REG_X8 8 -#define REG_X9 9 -#define REG_X10 10 -#define REG_X11 11 -#define REG_X12 12 -#define REG_X13 13 -#define REG_X14 14 -#define REG_X15 15 -#define REG_X16 16 -#define REG_X17 17 -#define REG_X18 18 -#define REG_X19 19 -#define REG_X20 20 -#define REG_X21 21 -#define REG_X22 22 -#define REG_X23 23 -#define REG_X24 24 -#define REG_X25 25 -#define REG_X26 26 -#define REG_X27 27 -#define REG_X28 28 -#define REG_X29 29 -#define REG_X30 30 -#define REG_XZR 31 +#define REG_X0 0 +#define REG_X1 1 +#define REG_X2 2 +#define REG_X3 3 +#define REG_X4 4 +#define REG_X5 5 +#define REG_X6 6 +#define REG_X7 7 +#define REG_X8 8 +#define REG_X9 9 +#define REG_X10 10 +#define REG_X11 11 +#define REG_X12 12 +#define REG_X13 13 +#define REG_X14 14 +#define REG_X15 15 +#define REG_X16 16 +#define REG_X17 17 +#define REG_X18 18 +#define REG_X19 19 +#define REG_X20 20 +#define REG_X21 21 +#define REG_X22 22 +#define REG_X23 23 +#define REG_X24 24 +#define REG_X25 25 +#define REG_X26 26 +#define REG_X27 27 +#define REG_X28 28 +#define REG_X29 29 +#define REG_X30 30 +#define REG_XZR 31 -#define REG_V0 0 -#define REG_V1 1 -#define REG_V2 2 -#define REG_V3 3 -#define REG_V4 4 -#define REG_V5 5 -#define REG_V6 6 -#define REG_V7 7 -#define REG_V8 8 -#define REG_V9 9 -#define REG_V10 10 -#define REG_V11 11 -#define REG_V12 12 -#define REG_V13 13 -#define REG_V14 14 -#define REG_V15 15 -#define REG_V16 16 -#define REG_V17 17 -#define REG_V18 18 -#define REG_V19 19 -#define REG_V20 20 -#define REG_V21 21 -#define REG_V22 22 -#define REG_V23 23 -#define REG_V24 24 -#define REG_V25 25 -#define REG_V26 26 -#define REG_V27 27 -#define REG_V28 28 -#define REG_V29 29 -#define REG_V30 30 -#define REG_V31 31 +#define REG_V0 0 +#define REG_V1 1 +#define REG_V2 2 +#define REG_V3 3 +#define REG_V4 4 +#define REG_V5 5 +#define REG_V6 6 +#define REG_V7 7 +#define REG_V8 8 +#define REG_V9 9 +#define REG_V10 10 +#define REG_V11 11 +#define REG_V12 12 +#define REG_V13 13 +#define REG_V14 14 +#define REG_V15 15 +#define REG_V16 16 +#define REG_V17 17 +#define REG_V18 18 +#define REG_V19 19 +#define REG_V20 20 +#define REG_V21 21 +#define REG_V22 22 +#define REG_V23 23 +#define REG_V24 24 +#define REG_V25 25 +#define REG_V26 26 +#define REG_V27 27 +#define REG_V28 28 +#define REG_V29 29 +#define REG_V30 30 +#define REG_V31 31 -#define REG_XSP 31 +#define REG_XSP 31 -#define REG_ARG0 REG_X0 -#define REG_ARG1 REG_X1 -#define REG_ARG2 REG_X2 -#define REG_ARG3 REG_X3 +#define REG_ARG0 REG_X0 +#define REG_ARG1 REG_X1 +#define REG_ARG2 REG_X2 +#define REG_ARG3 REG_X3 -#define REG_CPUSTATE REG_X29 +#define REG_CPUSTATE REG_X29 -#define REG_TEMP REG_X7 -#define REG_TEMP2 REG_X6 +#define REG_TEMP REG_X7 +#define REG_TEMP2 REG_X6 -#define REG_V_TEMP REG_V0 +#define REG_V_TEMP REG_V0 -#define CODEGEN_HOST_REGS 10 +#define CODEGEN_HOST_REGS 10 #define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_arm64_imm.c b/src/codegen_new/codegen_backend_arm64_imm.c index 0362b71d6..5e1e1038f 100644 --- a/src/codegen_new/codegen_backend_arm64_imm.c +++ b/src/codegen_new/codegen_backend_arm64_imm.c @@ -5,1326 +5,1325 @@ All valid values are in the table below, which we perform a binary search over*/ #define IMM_NR 1302 -static uint32_t imm_table[][2] = -{ - {0x800, 0x00000001}, - {0xfc0, 0x00000002}, - {0x801, 0x00000003}, - {0xf80, 0x00000004}, - {0xfc1, 0x00000006}, - {0x802, 0x00000007}, - {0xf40, 0x00000008}, - {0xf81, 0x0000000c}, - {0xfc2, 0x0000000e}, - {0x803, 0x0000000f}, - {0xf00, 0x00000010}, - {0xf41, 0x00000018}, - {0xf82, 0x0000001c}, - {0xfc3, 0x0000001e}, - {0x804, 0x0000001f}, - {0xec0, 0x00000020}, - {0xf01, 0x00000030}, - {0xf42, 0x00000038}, - {0xf83, 0x0000003c}, - {0xfc4, 0x0000003e}, - {0x805, 0x0000003f}, - {0xe80, 0x00000040}, - {0xec1, 0x00000060}, - {0xf02, 0x00000070}, - {0xf43, 0x00000078}, - {0xf84, 0x0000007c}, - {0xfc5, 0x0000007e}, - {0x806, 0x0000007f}, - {0xe40, 0x00000080}, - {0xe81, 0x000000c0}, - {0xec2, 0x000000e0}, - {0xf03, 0x000000f0}, - {0xf44, 0x000000f8}, - {0xf85, 0x000000fc}, - {0xfc6, 0x000000fe}, - {0x807, 0x000000ff}, - {0xe00, 0x00000100}, - {0xe41, 0x00000180}, - {0xe82, 0x000001c0}, - {0xec3, 0x000001e0}, - {0xf04, 0x000001f0}, - {0xf45, 0x000001f8}, - {0xf86, 0x000001fc}, - {0xfc7, 0x000001fe}, - {0x808, 0x000001ff}, - {0xdc0, 0x00000200}, - {0xe01, 0x00000300}, - {0xe42, 0x00000380}, - {0xe83, 0x000003c0}, - {0xec4, 0x000003e0}, - {0xf05, 0x000003f0}, - {0xf46, 0x000003f8}, - {0xf87, 0x000003fc}, - {0xfc8, 0x000003fe}, - {0x809, 0x000003ff}, - {0xd80, 0x00000400}, - {0xdc1, 0x00000600}, - {0xe02, 0x00000700}, - {0xe43, 0x00000780}, - {0xe84, 0x000007c0}, - {0xec5, 0x000007e0}, - {0xf06, 0x000007f0}, - {0xf47, 0x000007f8}, - {0xf88, 0x000007fc}, - {0xfc9, 0x000007fe}, - {0x80a, 0x000007ff}, - {0xd40, 0x00000800}, - {0xd81, 0x00000c00}, - {0xdc2, 0x00000e00}, - {0xe03, 0x00000f00}, - {0xe44, 0x00000f80}, - {0xe85, 0x00000fc0}, - {0xec6, 0x00000fe0}, - {0xf07, 0x00000ff0}, - {0xf48, 0x00000ff8}, - {0xf89, 0x00000ffc}, - {0xfca, 0x00000ffe}, - {0x80b, 0x00000fff}, - {0xd00, 0x00001000}, - {0xd41, 0x00001800}, - {0xd82, 0x00001c00}, - {0xdc3, 0x00001e00}, - {0xe04, 0x00001f00}, - {0xe45, 0x00001f80}, - {0xe86, 0x00001fc0}, - {0xec7, 0x00001fe0}, - {0xf08, 0x00001ff0}, - {0xf49, 0x00001ff8}, - {0xf8a, 0x00001ffc}, - {0xfcb, 0x00001ffe}, - {0x80c, 0x00001fff}, - {0xcc0, 0x00002000}, - {0xd01, 0x00003000}, - {0xd42, 0x00003800}, - {0xd83, 0x00003c00}, - {0xdc4, 0x00003e00}, - {0xe05, 0x00003f00}, - {0xe46, 0x00003f80}, - {0xe87, 0x00003fc0}, - {0xec8, 0x00003fe0}, - {0xf09, 0x00003ff0}, - {0xf4a, 0x00003ff8}, - {0xf8b, 0x00003ffc}, - {0xfcc, 0x00003ffe}, - {0x80d, 0x00003fff}, - {0xc80, 0x00004000}, - {0xcc1, 0x00006000}, - {0xd02, 0x00007000}, - {0xd43, 0x00007800}, - {0xd84, 0x00007c00}, - {0xdc5, 0x00007e00}, - {0xe06, 0x00007f00}, - {0xe47, 0x00007f80}, - {0xe88, 0x00007fc0}, - {0xec9, 0x00007fe0}, - {0xf0a, 0x00007ff0}, - {0xf4b, 0x00007ff8}, - {0xf8c, 0x00007ffc}, - {0xfcd, 0x00007ffe}, - {0x80e, 0x00007fff}, - {0xc40, 0x00008000}, - {0xc81, 0x0000c000}, - {0xcc2, 0x0000e000}, - {0xd03, 0x0000f000}, - {0xd44, 0x0000f800}, - {0xd85, 0x0000fc00}, - {0xdc6, 0x0000fe00}, - {0xe07, 0x0000ff00}, - {0xe48, 0x0000ff80}, - {0xe89, 0x0000ffc0}, - {0xeca, 0x0000ffe0}, - {0xf0b, 0x0000fff0}, - {0xf4c, 0x0000fff8}, - {0xf8d, 0x0000fffc}, - {0xfce, 0x0000fffe}, - {0x80f, 0x0000ffff}, - {0xc00, 0x00010000}, - {0xc20, 0x00010001}, - {0xc41, 0x00018000}, - {0xc82, 0x0001c000}, - {0xcc3, 0x0001e000}, - {0xd04, 0x0001f000}, - {0xd45, 0x0001f800}, - {0xd86, 0x0001fc00}, - {0xdc7, 0x0001fe00}, - {0xe08, 0x0001ff00}, - {0xe49, 0x0001ff80}, - {0xe8a, 0x0001ffc0}, - {0xecb, 0x0001ffe0}, - {0xf0c, 0x0001fff0}, - {0xf4d, 0x0001fff8}, - {0xf8e, 0x0001fffc}, - {0xfcf, 0x0001fffe}, - {0x810, 0x0001ffff}, - {0xbc0, 0x00020000}, - {0xfe0, 0x00020002}, - {0xc01, 0x00030000}, - {0xc21, 0x00030003}, - {0xc42, 0x00038000}, - {0xc83, 0x0003c000}, - {0xcc4, 0x0003e000}, - {0xd05, 0x0003f000}, - {0xd46, 0x0003f800}, - {0xd87, 0x0003fc00}, - {0xdc8, 0x0003fe00}, - {0xe09, 0x0003ff00}, - {0xe4a, 0x0003ff80}, - {0xe8b, 0x0003ffc0}, - {0xecc, 0x0003ffe0}, - {0xf0d, 0x0003fff0}, - {0xf4e, 0x0003fff8}, - {0xf8f, 0x0003fffc}, - {0xfd0, 0x0003fffe}, - {0x811, 0x0003ffff}, - {0xb80, 0x00040000}, - {0xfa0, 0x00040004}, - {0xbc1, 0x00060000}, - {0xfe1, 0x00060006}, - {0xc02, 0x00070000}, - {0xc22, 0x00070007}, - {0xc43, 0x00078000}, - {0xc84, 0x0007c000}, - {0xcc5, 0x0007e000}, - {0xd06, 0x0007f000}, - {0xd47, 0x0007f800}, - {0xd88, 0x0007fc00}, - {0xdc9, 0x0007fe00}, - {0xe0a, 0x0007ff00}, - {0xe4b, 0x0007ff80}, - {0xe8c, 0x0007ffc0}, - {0xecd, 0x0007ffe0}, - {0xf0e, 0x0007fff0}, - {0xf4f, 0x0007fff8}, - {0xf90, 0x0007fffc}, - {0xfd1, 0x0007fffe}, - {0x812, 0x0007ffff}, - {0xb40, 0x00080000}, - {0xf60, 0x00080008}, - {0xb81, 0x000c0000}, - {0xfa1, 0x000c000c}, - {0xbc2, 0x000e0000}, - {0xfe2, 0x000e000e}, - {0xc03, 0x000f0000}, - {0xc23, 0x000f000f}, - {0xc44, 0x000f8000}, - {0xc85, 0x000fc000}, - {0xcc6, 0x000fe000}, - {0xd07, 0x000ff000}, - {0xd48, 0x000ff800}, - {0xd89, 0x000ffc00}, - {0xdca, 0x000ffe00}, - {0xe0b, 0x000fff00}, - {0xe4c, 0x000fff80}, - {0xe8d, 0x000fffc0}, - {0xece, 0x000fffe0}, - {0xf0f, 0x000ffff0}, - {0xf50, 0x000ffff8}, - {0xf91, 0x000ffffc}, - {0xfd2, 0x000ffffe}, - {0x813, 0x000fffff}, - {0xb00, 0x00100000}, - {0xf20, 0x00100010}, - {0xb41, 0x00180000}, - {0xf61, 0x00180018}, - {0xb82, 0x001c0000}, - {0xfa2, 0x001c001c}, - {0xbc3, 0x001e0000}, - {0xfe3, 0x001e001e}, - {0xc04, 0x001f0000}, - {0xc24, 0x001f001f}, - {0xc45, 0x001f8000}, - {0xc86, 0x001fc000}, - {0xcc7, 0x001fe000}, - {0xd08, 0x001ff000}, - {0xd49, 0x001ff800}, - {0xd8a, 0x001ffc00}, - {0xdcb, 0x001ffe00}, - {0xe0c, 0x001fff00}, - {0xe4d, 0x001fff80}, - {0xe8e, 0x001fffc0}, - {0xecf, 0x001fffe0}, - {0xf10, 0x001ffff0}, - {0xf51, 0x001ffff8}, - {0xf92, 0x001ffffc}, - {0xfd3, 0x001ffffe}, - {0x814, 0x001fffff}, - {0xac0, 0x00200000}, - {0xee0, 0x00200020}, - {0xb01, 0x00300000}, - {0xf21, 0x00300030}, - {0xb42, 0x00380000}, - {0xf62, 0x00380038}, - {0xb83, 0x003c0000}, - {0xfa3, 0x003c003c}, - {0xbc4, 0x003e0000}, - {0xfe4, 0x003e003e}, - {0xc05, 0x003f0000}, - {0xc25, 0x003f003f}, - {0xc46, 0x003f8000}, - {0xc87, 0x003fc000}, - {0xcc8, 0x003fe000}, - {0xd09, 0x003ff000}, - {0xd4a, 0x003ff800}, - {0xd8b, 0x003ffc00}, - {0xdcc, 0x003ffe00}, - {0xe0d, 0x003fff00}, - {0xe4e, 0x003fff80}, - {0xe8f, 0x003fffc0}, - {0xed0, 0x003fffe0}, - {0xf11, 0x003ffff0}, - {0xf52, 0x003ffff8}, - {0xf93, 0x003ffffc}, - {0xfd4, 0x003ffffe}, - {0x815, 0x003fffff}, - {0xa80, 0x00400000}, - {0xea0, 0x00400040}, - {0xac1, 0x00600000}, - {0xee1, 0x00600060}, - {0xb02, 0x00700000}, - {0xf22, 0x00700070}, - {0xb43, 0x00780000}, - {0xf63, 0x00780078}, - {0xb84, 0x007c0000}, - {0xfa4, 0x007c007c}, - {0xbc5, 0x007e0000}, - {0xfe5, 0x007e007e}, - {0xc06, 0x007f0000}, - {0xc26, 0x007f007f}, - {0xc47, 0x007f8000}, - {0xc88, 0x007fc000}, - {0xcc9, 0x007fe000}, - {0xd0a, 0x007ff000}, - {0xd4b, 0x007ff800}, - {0xd8c, 0x007ffc00}, - {0xdcd, 0x007ffe00}, - {0xe0e, 0x007fff00}, - {0xe4f, 0x007fff80}, - {0xe90, 0x007fffc0}, - {0xed1, 0x007fffe0}, - {0xf12, 0x007ffff0}, - {0xf53, 0x007ffff8}, - {0xf94, 0x007ffffc}, - {0xfd5, 0x007ffffe}, - {0x816, 0x007fffff}, - {0xa40, 0x00800000}, - {0xe60, 0x00800080}, - {0xa81, 0x00c00000}, - {0xea1, 0x00c000c0}, - {0xac2, 0x00e00000}, - {0xee2, 0x00e000e0}, - {0xb03, 0x00f00000}, - {0xf23, 0x00f000f0}, - {0xb44, 0x00f80000}, - {0xf64, 0x00f800f8}, - {0xb85, 0x00fc0000}, - {0xfa5, 0x00fc00fc}, - {0xbc6, 0x00fe0000}, - {0xfe6, 0x00fe00fe}, - {0xc07, 0x00ff0000}, - {0xc27, 0x00ff00ff}, - {0xc48, 0x00ff8000}, - {0xc89, 0x00ffc000}, - {0xcca, 0x00ffe000}, - {0xd0b, 0x00fff000}, - {0xd4c, 0x00fff800}, - {0xd8d, 0x00fffc00}, - {0xdce, 0x00fffe00}, - {0xe0f, 0x00ffff00}, - {0xe50, 0x00ffff80}, - {0xe91, 0x00ffffc0}, - {0xed2, 0x00ffffe0}, - {0xf13, 0x00fffff0}, - {0xf54, 0x00fffff8}, - {0xf95, 0x00fffffc}, - {0xfd6, 0x00fffffe}, - {0x817, 0x00ffffff}, - {0xa00, 0x01000000}, - {0xe20, 0x01000100}, - {0xe30, 0x01010101}, - {0xa41, 0x01800000}, - {0xe61, 0x01800180}, - {0xa82, 0x01c00000}, - {0xea2, 0x01c001c0}, - {0xac3, 0x01e00000}, - {0xee3, 0x01e001e0}, - {0xb04, 0x01f00000}, - {0xf24, 0x01f001f0}, - {0xb45, 0x01f80000}, - {0xf65, 0x01f801f8}, - {0xb86, 0x01fc0000}, - {0xfa6, 0x01fc01fc}, - {0xbc7, 0x01fe0000}, - {0xfe7, 0x01fe01fe}, - {0xc08, 0x01ff0000}, - {0xc28, 0x01ff01ff}, - {0xc49, 0x01ff8000}, - {0xc8a, 0x01ffc000}, - {0xccb, 0x01ffe000}, - {0xd0c, 0x01fff000}, - {0xd4d, 0x01fff800}, - {0xd8e, 0x01fffc00}, - {0xdcf, 0x01fffe00}, - {0xe10, 0x01ffff00}, - {0xe51, 0x01ffff80}, - {0xe92, 0x01ffffc0}, - {0xed3, 0x01ffffe0}, - {0xf14, 0x01fffff0}, - {0xf55, 0x01fffff8}, - {0xf96, 0x01fffffc}, - {0xfd7, 0x01fffffe}, - {0x818, 0x01ffffff}, - {0x9c0, 0x02000000}, - {0xde0, 0x02000200}, - {0xff0, 0x02020202}, - {0xa01, 0x03000000}, - {0xe21, 0x03000300}, - {0xe31, 0x03030303}, - {0xa42, 0x03800000}, - {0xe62, 0x03800380}, - {0xa83, 0x03c00000}, - {0xea3, 0x03c003c0}, - {0xac4, 0x03e00000}, - {0xee4, 0x03e003e0}, - {0xb05, 0x03f00000}, - {0xf25, 0x03f003f0}, - {0xb46, 0x03f80000}, - {0xf66, 0x03f803f8}, - {0xb87, 0x03fc0000}, - {0xfa7, 0x03fc03fc}, - {0xbc8, 0x03fe0000}, - {0xfe8, 0x03fe03fe}, - {0xc09, 0x03ff0000}, - {0xc29, 0x03ff03ff}, - {0xc4a, 0x03ff8000}, - {0xc8b, 0x03ffc000}, - {0xccc, 0x03ffe000}, - {0xd0d, 0x03fff000}, - {0xd4e, 0x03fff800}, - {0xd8f, 0x03fffc00}, - {0xdd0, 0x03fffe00}, - {0xe11, 0x03ffff00}, - {0xe52, 0x03ffff80}, - {0xe93, 0x03ffffc0}, - {0xed4, 0x03ffffe0}, - {0xf15, 0x03fffff0}, - {0xf56, 0x03fffff8}, - {0xf97, 0x03fffffc}, - {0xfd8, 0x03fffffe}, - {0x819, 0x03ffffff}, - {0x980, 0x04000000}, - {0xda0, 0x04000400}, - {0xfb0, 0x04040404}, - {0x9c1, 0x06000000}, - {0xde1, 0x06000600}, - {0xff1, 0x06060606}, - {0xa02, 0x07000000}, - {0xe22, 0x07000700}, - {0xe32, 0x07070707}, - {0xa43, 0x07800000}, - {0xe63, 0x07800780}, - {0xa84, 0x07c00000}, - {0xea4, 0x07c007c0}, - {0xac5, 0x07e00000}, - {0xee5, 0x07e007e0}, - {0xb06, 0x07f00000}, - {0xf26, 0x07f007f0}, - {0xb47, 0x07f80000}, - {0xf67, 0x07f807f8}, - {0xb88, 0x07fc0000}, - {0xfa8, 0x07fc07fc}, - {0xbc9, 0x07fe0000}, - {0xfe9, 0x07fe07fe}, - {0xc0a, 0x07ff0000}, - {0xc2a, 0x07ff07ff}, - {0xc4b, 0x07ff8000}, - {0xc8c, 0x07ffc000}, - {0xccd, 0x07ffe000}, - {0xd0e, 0x07fff000}, - {0xd4f, 0x07fff800}, - {0xd90, 0x07fffc00}, - {0xdd1, 0x07fffe00}, - {0xe12, 0x07ffff00}, - {0xe53, 0x07ffff80}, - {0xe94, 0x07ffffc0}, - {0xed5, 0x07ffffe0}, - {0xf16, 0x07fffff0}, - {0xf57, 0x07fffff8}, - {0xf98, 0x07fffffc}, - {0xfd9, 0x07fffffe}, - {0x81a, 0x07ffffff}, - {0x940, 0x08000000}, - {0xd60, 0x08000800}, - {0xf70, 0x08080808}, - {0x981, 0x0c000000}, - {0xda1, 0x0c000c00}, - {0xfb1, 0x0c0c0c0c}, - {0x9c2, 0x0e000000}, - {0xde2, 0x0e000e00}, - {0xff2, 0x0e0e0e0e}, - {0xa03, 0x0f000000}, - {0xe23, 0x0f000f00}, - {0xe33, 0x0f0f0f0f}, - {0xa44, 0x0f800000}, - {0xe64, 0x0f800f80}, - {0xa85, 0x0fc00000}, - {0xea5, 0x0fc00fc0}, - {0xac6, 0x0fe00000}, - {0xee6, 0x0fe00fe0}, - {0xb07, 0x0ff00000}, - {0xf27, 0x0ff00ff0}, - {0xb48, 0x0ff80000}, - {0xf68, 0x0ff80ff8}, - {0xb89, 0x0ffc0000}, - {0xfa9, 0x0ffc0ffc}, - {0xbca, 0x0ffe0000}, - {0xfea, 0x0ffe0ffe}, - {0xc0b, 0x0fff0000}, - {0xc2b, 0x0fff0fff}, - {0xc4c, 0x0fff8000}, - {0xc8d, 0x0fffc000}, - {0xcce, 0x0fffe000}, - {0xd0f, 0x0ffff000}, - {0xd50, 0x0ffff800}, - {0xd91, 0x0ffffc00}, - {0xdd2, 0x0ffffe00}, - {0xe13, 0x0fffff00}, - {0xe54, 0x0fffff80}, - {0xe95, 0x0fffffc0}, - {0xed6, 0x0fffffe0}, - {0xf17, 0x0ffffff0}, - {0xf58, 0x0ffffff8}, - {0xf99, 0x0ffffffc}, - {0xfda, 0x0ffffffe}, - {0x81b, 0x0fffffff}, - {0x900, 0x10000000}, - {0xd20, 0x10001000}, - {0xf30, 0x10101010}, - {0xf38, 0x11111111}, - {0x941, 0x18000000}, - {0xd61, 0x18001800}, - {0xf71, 0x18181818}, - {0x982, 0x1c000000}, - {0xda2, 0x1c001c00}, - {0xfb2, 0x1c1c1c1c}, - {0x9c3, 0x1e000000}, - {0xde3, 0x1e001e00}, - {0xff3, 0x1e1e1e1e}, - {0xa04, 0x1f000000}, - {0xe24, 0x1f001f00}, - {0xe34, 0x1f1f1f1f}, - {0xa45, 0x1f800000}, - {0xe65, 0x1f801f80}, - {0xa86, 0x1fc00000}, - {0xea6, 0x1fc01fc0}, - {0xac7, 0x1fe00000}, - {0xee7, 0x1fe01fe0}, - {0xb08, 0x1ff00000}, - {0xf28, 0x1ff01ff0}, - {0xb49, 0x1ff80000}, - {0xf69, 0x1ff81ff8}, - {0xb8a, 0x1ffc0000}, - {0xfaa, 0x1ffc1ffc}, - {0xbcb, 0x1ffe0000}, - {0xfeb, 0x1ffe1ffe}, - {0xc0c, 0x1fff0000}, - {0xc2c, 0x1fff1fff}, - {0xc4d, 0x1fff8000}, - {0xc8e, 0x1fffc000}, - {0xccf, 0x1fffe000}, - {0xd10, 0x1ffff000}, - {0xd51, 0x1ffff800}, - {0xd92, 0x1ffffc00}, - {0xdd3, 0x1ffffe00}, - {0xe14, 0x1fffff00}, - {0xe55, 0x1fffff80}, - {0xe96, 0x1fffffc0}, - {0xed7, 0x1fffffe0}, - {0xf18, 0x1ffffff0}, - {0xf59, 0x1ffffff8}, - {0xf9a, 0x1ffffffc}, - {0xfdb, 0x1ffffffe}, - {0x81c, 0x1fffffff}, - {0x8c0, 0x20000000}, - {0xce0, 0x20002000}, - {0xef0, 0x20202020}, - {0xff8, 0x22222222}, - {0x901, 0x30000000}, - {0xd21, 0x30003000}, - {0xf31, 0x30303030}, - {0xf39, 0x33333333}, - {0x942, 0x38000000}, - {0xd62, 0x38003800}, - {0xf72, 0x38383838}, - {0x983, 0x3c000000}, - {0xda3, 0x3c003c00}, - {0xfb3, 0x3c3c3c3c}, - {0x9c4, 0x3e000000}, - {0xde4, 0x3e003e00}, - {0xff4, 0x3e3e3e3e}, - {0xa05, 0x3f000000}, - {0xe25, 0x3f003f00}, - {0xe35, 0x3f3f3f3f}, - {0xa46, 0x3f800000}, - {0xe66, 0x3f803f80}, - {0xa87, 0x3fc00000}, - {0xea7, 0x3fc03fc0}, - {0xac8, 0x3fe00000}, - {0xee8, 0x3fe03fe0}, - {0xb09, 0x3ff00000}, - {0xf29, 0x3ff03ff0}, - {0xb4a, 0x3ff80000}, - {0xf6a, 0x3ff83ff8}, - {0xb8b, 0x3ffc0000}, - {0xfab, 0x3ffc3ffc}, - {0xbcc, 0x3ffe0000}, - {0xfec, 0x3ffe3ffe}, - {0xc0d, 0x3fff0000}, - {0xc2d, 0x3fff3fff}, - {0xc4e, 0x3fff8000}, - {0xc8f, 0x3fffc000}, - {0xcd0, 0x3fffe000}, - {0xd11, 0x3ffff000}, - {0xd52, 0x3ffff800}, - {0xd93, 0x3ffffc00}, - {0xdd4, 0x3ffffe00}, - {0xe15, 0x3fffff00}, - {0xe56, 0x3fffff80}, - {0xe97, 0x3fffffc0}, - {0xed8, 0x3fffffe0}, - {0xf19, 0x3ffffff0}, - {0xf5a, 0x3ffffff8}, - {0xf9b, 0x3ffffffc}, - {0xfdc, 0x3ffffffe}, - {0x81d, 0x3fffffff}, - {0x880, 0x40000000}, - {0xca0, 0x40004000}, - {0xeb0, 0x40404040}, - {0xfb8, 0x44444444}, - {0xfbc, 0x55555555}, - {0x8c1, 0x60000000}, - {0xce1, 0x60006000}, - {0xef1, 0x60606060}, - {0xff9, 0x66666666}, - {0x902, 0x70000000}, - {0xd22, 0x70007000}, - {0xf32, 0x70707070}, - {0xf3a, 0x77777777}, - {0x943, 0x78000000}, - {0xd63, 0x78007800}, - {0xf73, 0x78787878}, - {0x984, 0x7c000000}, - {0xda4, 0x7c007c00}, - {0xfb4, 0x7c7c7c7c}, - {0x9c5, 0x7e000000}, - {0xde5, 0x7e007e00}, - {0xff5, 0x7e7e7e7e}, - {0xa06, 0x7f000000}, - {0xe26, 0x7f007f00}, - {0xe36, 0x7f7f7f7f}, - {0xa47, 0x7f800000}, - {0xe67, 0x7f807f80}, - {0xa88, 0x7fc00000}, - {0xea8, 0x7fc07fc0}, - {0xac9, 0x7fe00000}, - {0xee9, 0x7fe07fe0}, - {0xb0a, 0x7ff00000}, - {0xf2a, 0x7ff07ff0}, - {0xb4b, 0x7ff80000}, - {0xf6b, 0x7ff87ff8}, - {0xb8c, 0x7ffc0000}, - {0xfac, 0x7ffc7ffc}, - {0xbcd, 0x7ffe0000}, - {0xfed, 0x7ffe7ffe}, - {0xc0e, 0x7fff0000}, - {0xc2e, 0x7fff7fff}, - {0xc4f, 0x7fff8000}, - {0xc90, 0x7fffc000}, - {0xcd1, 0x7fffe000}, - {0xd12, 0x7ffff000}, - {0xd53, 0x7ffff800}, - {0xd94, 0x7ffffc00}, - {0xdd5, 0x7ffffe00}, - {0xe16, 0x7fffff00}, - {0xe57, 0x7fffff80}, - {0xe98, 0x7fffffc0}, - {0xed9, 0x7fffffe0}, - {0xf1a, 0x7ffffff0}, - {0xf5b, 0x7ffffff8}, - {0xf9c, 0x7ffffffc}, - {0xfdd, 0x7ffffffe}, - {0x81e, 0x7fffffff}, - {0x840, 0x80000000}, - {0x841, 0x80000001}, - {0x842, 0x80000003}, - {0x843, 0x80000007}, - {0x844, 0x8000000f}, - {0x845, 0x8000001f}, - {0x846, 0x8000003f}, - {0x847, 0x8000007f}, - {0x848, 0x800000ff}, - {0x849, 0x800001ff}, - {0x84a, 0x800003ff}, - {0x84b, 0x800007ff}, - {0x84c, 0x80000fff}, - {0x84d, 0x80001fff}, - {0x84e, 0x80003fff}, - {0x84f, 0x80007fff}, - {0xc60, 0x80008000}, - {0x850, 0x8000ffff}, - {0xc61, 0x80018001}, - {0x851, 0x8001ffff}, - {0xc62, 0x80038003}, - {0x852, 0x8003ffff}, - {0xc63, 0x80078007}, - {0x853, 0x8007ffff}, - {0xc64, 0x800f800f}, - {0x854, 0x800fffff}, - {0xc65, 0x801f801f}, - {0x855, 0x801fffff}, - {0xc66, 0x803f803f}, - {0x856, 0x803fffff}, - {0xc67, 0x807f807f}, - {0x857, 0x807fffff}, - {0xe70, 0x80808080}, - {0xc68, 0x80ff80ff}, - {0x858, 0x80ffffff}, - {0xe71, 0x81818181}, - {0xc69, 0x81ff81ff}, - {0x859, 0x81ffffff}, - {0xe72, 0x83838383}, - {0xc6a, 0x83ff83ff}, - {0x85a, 0x83ffffff}, - {0xe73, 0x87878787}, - {0xc6b, 0x87ff87ff}, - {0x85b, 0x87ffffff}, - {0xf78, 0x88888888}, - {0xe74, 0x8f8f8f8f}, - {0xc6c, 0x8fff8fff}, - {0x85c, 0x8fffffff}, - {0xf79, 0x99999999}, - {0xe75, 0x9f9f9f9f}, - {0xc6d, 0x9fff9fff}, - {0x85d, 0x9fffffff}, - {0xffc, 0xaaaaaaaa}, - {0xf7a, 0xbbbbbbbb}, - {0xe76, 0xbfbfbfbf}, - {0xc6e, 0xbfffbfff}, - {0x85e, 0xbfffffff}, - {0x881, 0xc0000000}, - {0x882, 0xc0000001}, - {0x883, 0xc0000003}, - {0x884, 0xc0000007}, - {0x885, 0xc000000f}, - {0x886, 0xc000001f}, - {0x887, 0xc000003f}, - {0x888, 0xc000007f}, - {0x889, 0xc00000ff}, - {0x88a, 0xc00001ff}, - {0x88b, 0xc00003ff}, - {0x88c, 0xc00007ff}, - {0x88d, 0xc0000fff}, - {0x88e, 0xc0001fff}, - {0x88f, 0xc0003fff}, - {0x890, 0xc0007fff}, - {0xca1, 0xc000c000}, - {0x891, 0xc000ffff}, - {0xca2, 0xc001c001}, - {0x892, 0xc001ffff}, - {0xca3, 0xc003c003}, - {0x893, 0xc003ffff}, - {0xca4, 0xc007c007}, - {0x894, 0xc007ffff}, - {0xca5, 0xc00fc00f}, - {0x895, 0xc00fffff}, - {0xca6, 0xc01fc01f}, - {0x896, 0xc01fffff}, - {0xca7, 0xc03fc03f}, - {0x897, 0xc03fffff}, - {0xca8, 0xc07fc07f}, - {0x898, 0xc07fffff}, - {0xeb1, 0xc0c0c0c0}, - {0xca9, 0xc0ffc0ff}, - {0x899, 0xc0ffffff}, - {0xeb2, 0xc1c1c1c1}, - {0xcaa, 0xc1ffc1ff}, - {0x89a, 0xc1ffffff}, - {0xeb3, 0xc3c3c3c3}, - {0xcab, 0xc3ffc3ff}, - {0x89b, 0xc3ffffff}, - {0xeb4, 0xc7c7c7c7}, - {0xcac, 0xc7ffc7ff}, - {0x89c, 0xc7ffffff}, - {0xfb9, 0xcccccccc}, - {0xeb5, 0xcfcfcfcf}, - {0xcad, 0xcfffcfff}, - {0x89d, 0xcfffffff}, - {0xfba, 0xdddddddd}, - {0xeb6, 0xdfdfdfdf}, - {0xcae, 0xdfffdfff}, - {0x89e, 0xdfffffff}, - {0x8c2, 0xe0000000}, - {0x8c3, 0xe0000001}, - {0x8c4, 0xe0000003}, - {0x8c5, 0xe0000007}, - {0x8c6, 0xe000000f}, - {0x8c7, 0xe000001f}, - {0x8c8, 0xe000003f}, - {0x8c9, 0xe000007f}, - {0x8ca, 0xe00000ff}, - {0x8cb, 0xe00001ff}, - {0x8cc, 0xe00003ff}, - {0x8cd, 0xe00007ff}, - {0x8ce, 0xe0000fff}, - {0x8cf, 0xe0001fff}, - {0x8d0, 0xe0003fff}, - {0x8d1, 0xe0007fff}, - {0xce2, 0xe000e000}, - {0x8d2, 0xe000ffff}, - {0xce3, 0xe001e001}, - {0x8d3, 0xe001ffff}, - {0xce4, 0xe003e003}, - {0x8d4, 0xe003ffff}, - {0xce5, 0xe007e007}, - {0x8d5, 0xe007ffff}, - {0xce6, 0xe00fe00f}, - {0x8d6, 0xe00fffff}, - {0xce7, 0xe01fe01f}, - {0x8d7, 0xe01fffff}, - {0xce8, 0xe03fe03f}, - {0x8d8, 0xe03fffff}, - {0xce9, 0xe07fe07f}, - {0x8d9, 0xe07fffff}, - {0xef2, 0xe0e0e0e0}, - {0xcea, 0xe0ffe0ff}, - {0x8da, 0xe0ffffff}, - {0xef3, 0xe1e1e1e1}, - {0xceb, 0xe1ffe1ff}, - {0x8db, 0xe1ffffff}, - {0xef4, 0xe3e3e3e3}, - {0xcec, 0xe3ffe3ff}, - {0x8dc, 0xe3ffffff}, - {0xef5, 0xe7e7e7e7}, - {0xced, 0xe7ffe7ff}, - {0x8dd, 0xe7ffffff}, - {0xffa, 0xeeeeeeee}, - {0xef6, 0xefefefef}, - {0xcee, 0xefffefff}, - {0x8de, 0xefffffff}, - {0x903, 0xf0000000}, - {0x904, 0xf0000001}, - {0x905, 0xf0000003}, - {0x906, 0xf0000007}, - {0x907, 0xf000000f}, - {0x908, 0xf000001f}, - {0x909, 0xf000003f}, - {0x90a, 0xf000007f}, - {0x90b, 0xf00000ff}, - {0x90c, 0xf00001ff}, - {0x90d, 0xf00003ff}, - {0x90e, 0xf00007ff}, - {0x90f, 0xf0000fff}, - {0x910, 0xf0001fff}, - {0x911, 0xf0003fff}, - {0x912, 0xf0007fff}, - {0xd23, 0xf000f000}, - {0x913, 0xf000ffff}, - {0xd24, 0xf001f001}, - {0x914, 0xf001ffff}, - {0xd25, 0xf003f003}, - {0x915, 0xf003ffff}, - {0xd26, 0xf007f007}, - {0x916, 0xf007ffff}, - {0xd27, 0xf00ff00f}, - {0x917, 0xf00fffff}, - {0xd28, 0xf01ff01f}, - {0x918, 0xf01fffff}, - {0xd29, 0xf03ff03f}, - {0x919, 0xf03fffff}, - {0xd2a, 0xf07ff07f}, - {0x91a, 0xf07fffff}, - {0xf33, 0xf0f0f0f0}, - {0xd2b, 0xf0fff0ff}, - {0x91b, 0xf0ffffff}, - {0xf34, 0xf1f1f1f1}, - {0xd2c, 0xf1fff1ff}, - {0x91c, 0xf1ffffff}, - {0xf35, 0xf3f3f3f3}, - {0xd2d, 0xf3fff3ff}, - {0x91d, 0xf3ffffff}, - {0xf36, 0xf7f7f7f7}, - {0xd2e, 0xf7fff7ff}, - {0x91e, 0xf7ffffff}, - {0x944, 0xf8000000}, - {0x945, 0xf8000001}, - {0x946, 0xf8000003}, - {0x947, 0xf8000007}, - {0x948, 0xf800000f}, - {0x949, 0xf800001f}, - {0x94a, 0xf800003f}, - {0x94b, 0xf800007f}, - {0x94c, 0xf80000ff}, - {0x94d, 0xf80001ff}, - {0x94e, 0xf80003ff}, - {0x94f, 0xf80007ff}, - {0x950, 0xf8000fff}, - {0x951, 0xf8001fff}, - {0x952, 0xf8003fff}, - {0x953, 0xf8007fff}, - {0xd64, 0xf800f800}, - {0x954, 0xf800ffff}, - {0xd65, 0xf801f801}, - {0x955, 0xf801ffff}, - {0xd66, 0xf803f803}, - {0x956, 0xf803ffff}, - {0xd67, 0xf807f807}, - {0x957, 0xf807ffff}, - {0xd68, 0xf80ff80f}, - {0x958, 0xf80fffff}, - {0xd69, 0xf81ff81f}, - {0x959, 0xf81fffff}, - {0xd6a, 0xf83ff83f}, - {0x95a, 0xf83fffff}, - {0xd6b, 0xf87ff87f}, - {0x95b, 0xf87fffff}, - {0xf74, 0xf8f8f8f8}, - {0xd6c, 0xf8fff8ff}, - {0x95c, 0xf8ffffff}, - {0xf75, 0xf9f9f9f9}, - {0xd6d, 0xf9fff9ff}, - {0x95d, 0xf9ffffff}, - {0xf76, 0xfbfbfbfb}, - {0xd6e, 0xfbfffbff}, - {0x95e, 0xfbffffff}, - {0x985, 0xfc000000}, - {0x986, 0xfc000001}, - {0x987, 0xfc000003}, - {0x988, 0xfc000007}, - {0x989, 0xfc00000f}, - {0x98a, 0xfc00001f}, - {0x98b, 0xfc00003f}, - {0x98c, 0xfc00007f}, - {0x98d, 0xfc0000ff}, - {0x98e, 0xfc0001ff}, - {0x98f, 0xfc0003ff}, - {0x990, 0xfc0007ff}, - {0x991, 0xfc000fff}, - {0x992, 0xfc001fff}, - {0x993, 0xfc003fff}, - {0x994, 0xfc007fff}, - {0xda5, 0xfc00fc00}, - {0x995, 0xfc00ffff}, - {0xda6, 0xfc01fc01}, - {0x996, 0xfc01ffff}, - {0xda7, 0xfc03fc03}, - {0x997, 0xfc03ffff}, - {0xda8, 0xfc07fc07}, - {0x998, 0xfc07ffff}, - {0xda9, 0xfc0ffc0f}, - {0x999, 0xfc0fffff}, - {0xdaa, 0xfc1ffc1f}, - {0x99a, 0xfc1fffff}, - {0xdab, 0xfc3ffc3f}, - {0x99b, 0xfc3fffff}, - {0xdac, 0xfc7ffc7f}, - {0x99c, 0xfc7fffff}, - {0xfb5, 0xfcfcfcfc}, - {0xdad, 0xfcfffcff}, - {0x99d, 0xfcffffff}, - {0xfb6, 0xfdfdfdfd}, - {0xdae, 0xfdfffdff}, - {0x99e, 0xfdffffff}, - {0x9c6, 0xfe000000}, - {0x9c7, 0xfe000001}, - {0x9c8, 0xfe000003}, - {0x9c9, 0xfe000007}, - {0x9ca, 0xfe00000f}, - {0x9cb, 0xfe00001f}, - {0x9cc, 0xfe00003f}, - {0x9cd, 0xfe00007f}, - {0x9ce, 0xfe0000ff}, - {0x9cf, 0xfe0001ff}, - {0x9d0, 0xfe0003ff}, - {0x9d1, 0xfe0007ff}, - {0x9d2, 0xfe000fff}, - {0x9d3, 0xfe001fff}, - {0x9d4, 0xfe003fff}, - {0x9d5, 0xfe007fff}, - {0xde6, 0xfe00fe00}, - {0x9d6, 0xfe00ffff}, - {0xde7, 0xfe01fe01}, - {0x9d7, 0xfe01ffff}, - {0xde8, 0xfe03fe03}, - {0x9d8, 0xfe03ffff}, - {0xde9, 0xfe07fe07}, - {0x9d9, 0xfe07ffff}, - {0xdea, 0xfe0ffe0f}, - {0x9da, 0xfe0fffff}, - {0xdeb, 0xfe1ffe1f}, - {0x9db, 0xfe1fffff}, - {0xdec, 0xfe3ffe3f}, - {0x9dc, 0xfe3fffff}, - {0xded, 0xfe7ffe7f}, - {0x9dd, 0xfe7fffff}, - {0xff6, 0xfefefefe}, - {0xdee, 0xfefffeff}, - {0x9de, 0xfeffffff}, - {0xa07, 0xff000000}, - {0xa08, 0xff000001}, - {0xa09, 0xff000003}, - {0xa0a, 0xff000007}, - {0xa0b, 0xff00000f}, - {0xa0c, 0xff00001f}, - {0xa0d, 0xff00003f}, - {0xa0e, 0xff00007f}, - {0xa0f, 0xff0000ff}, - {0xa10, 0xff0001ff}, - {0xa11, 0xff0003ff}, - {0xa12, 0xff0007ff}, - {0xa13, 0xff000fff}, - {0xa14, 0xff001fff}, - {0xa15, 0xff003fff}, - {0xa16, 0xff007fff}, - {0xe27, 0xff00ff00}, - {0xa17, 0xff00ffff}, - {0xe28, 0xff01ff01}, - {0xa18, 0xff01ffff}, - {0xe29, 0xff03ff03}, - {0xa19, 0xff03ffff}, - {0xe2a, 0xff07ff07}, - {0xa1a, 0xff07ffff}, - {0xe2b, 0xff0fff0f}, - {0xa1b, 0xff0fffff}, - {0xe2c, 0xff1fff1f}, - {0xa1c, 0xff1fffff}, - {0xe2d, 0xff3fff3f}, - {0xa1d, 0xff3fffff}, - {0xe2e, 0xff7fff7f}, - {0xa1e, 0xff7fffff}, - {0xa48, 0xff800000}, - {0xa49, 0xff800001}, - {0xa4a, 0xff800003}, - {0xa4b, 0xff800007}, - {0xa4c, 0xff80000f}, - {0xa4d, 0xff80001f}, - {0xa4e, 0xff80003f}, - {0xa4f, 0xff80007f}, - {0xa50, 0xff8000ff}, - {0xa51, 0xff8001ff}, - {0xa52, 0xff8003ff}, - {0xa53, 0xff8007ff}, - {0xa54, 0xff800fff}, - {0xa55, 0xff801fff}, - {0xa56, 0xff803fff}, - {0xa57, 0xff807fff}, - {0xe68, 0xff80ff80}, - {0xa58, 0xff80ffff}, - {0xe69, 0xff81ff81}, - {0xa59, 0xff81ffff}, - {0xe6a, 0xff83ff83}, - {0xa5a, 0xff83ffff}, - {0xe6b, 0xff87ff87}, - {0xa5b, 0xff87ffff}, - {0xe6c, 0xff8fff8f}, - {0xa5c, 0xff8fffff}, - {0xe6d, 0xff9fff9f}, - {0xa5d, 0xff9fffff}, - {0xe6e, 0xffbfffbf}, - {0xa5e, 0xffbfffff}, - {0xa89, 0xffc00000}, - {0xa8a, 0xffc00001}, - {0xa8b, 0xffc00003}, - {0xa8c, 0xffc00007}, - {0xa8d, 0xffc0000f}, - {0xa8e, 0xffc0001f}, - {0xa8f, 0xffc0003f}, - {0xa90, 0xffc0007f}, - {0xa91, 0xffc000ff}, - {0xa92, 0xffc001ff}, - {0xa93, 0xffc003ff}, - {0xa94, 0xffc007ff}, - {0xa95, 0xffc00fff}, - {0xa96, 0xffc01fff}, - {0xa97, 0xffc03fff}, - {0xa98, 0xffc07fff}, - {0xea9, 0xffc0ffc0}, - {0xa99, 0xffc0ffff}, - {0xeaa, 0xffc1ffc1}, - {0xa9a, 0xffc1ffff}, - {0xeab, 0xffc3ffc3}, - {0xa9b, 0xffc3ffff}, - {0xeac, 0xffc7ffc7}, - {0xa9c, 0xffc7ffff}, - {0xead, 0xffcfffcf}, - {0xa9d, 0xffcfffff}, - {0xeae, 0xffdfffdf}, - {0xa9e, 0xffdfffff}, - {0xaca, 0xffe00000}, - {0xacb, 0xffe00001}, - {0xacc, 0xffe00003}, - {0xacd, 0xffe00007}, - {0xace, 0xffe0000f}, - {0xacf, 0xffe0001f}, - {0xad0, 0xffe0003f}, - {0xad1, 0xffe0007f}, - {0xad2, 0xffe000ff}, - {0xad3, 0xffe001ff}, - {0xad4, 0xffe003ff}, - {0xad5, 0xffe007ff}, - {0xad6, 0xffe00fff}, - {0xad7, 0xffe01fff}, - {0xad8, 0xffe03fff}, - {0xad9, 0xffe07fff}, - {0xeea, 0xffe0ffe0}, - {0xada, 0xffe0ffff}, - {0xeeb, 0xffe1ffe1}, - {0xadb, 0xffe1ffff}, - {0xeec, 0xffe3ffe3}, - {0xadc, 0xffe3ffff}, - {0xeed, 0xffe7ffe7}, - {0xadd, 0xffe7ffff}, - {0xeee, 0xffefffef}, - {0xade, 0xffefffff}, - {0xb0b, 0xfff00000}, - {0xb0c, 0xfff00001}, - {0xb0d, 0xfff00003}, - {0xb0e, 0xfff00007}, - {0xb0f, 0xfff0000f}, - {0xb10, 0xfff0001f}, - {0xb11, 0xfff0003f}, - {0xb12, 0xfff0007f}, - {0xb13, 0xfff000ff}, - {0xb14, 0xfff001ff}, - {0xb15, 0xfff003ff}, - {0xb16, 0xfff007ff}, - {0xb17, 0xfff00fff}, - {0xb18, 0xfff01fff}, - {0xb19, 0xfff03fff}, - {0xb1a, 0xfff07fff}, - {0xf2b, 0xfff0fff0}, - {0xb1b, 0xfff0ffff}, - {0xf2c, 0xfff1fff1}, - {0xb1c, 0xfff1ffff}, - {0xf2d, 0xfff3fff3}, - {0xb1d, 0xfff3ffff}, - {0xf2e, 0xfff7fff7}, - {0xb1e, 0xfff7ffff}, - {0xb4c, 0xfff80000}, - {0xb4d, 0xfff80001}, - {0xb4e, 0xfff80003}, - {0xb4f, 0xfff80007}, - {0xb50, 0xfff8000f}, - {0xb51, 0xfff8001f}, - {0xb52, 0xfff8003f}, - {0xb53, 0xfff8007f}, - {0xb54, 0xfff800ff}, - {0xb55, 0xfff801ff}, - {0xb56, 0xfff803ff}, - {0xb57, 0xfff807ff}, - {0xb58, 0xfff80fff}, - {0xb59, 0xfff81fff}, - {0xb5a, 0xfff83fff}, - {0xb5b, 0xfff87fff}, - {0xf6c, 0xfff8fff8}, - {0xb5c, 0xfff8ffff}, - {0xf6d, 0xfff9fff9}, - {0xb5d, 0xfff9ffff}, - {0xf6e, 0xfffbfffb}, - {0xb5e, 0xfffbffff}, - {0xb8d, 0xfffc0000}, - {0xb8e, 0xfffc0001}, - {0xb8f, 0xfffc0003}, - {0xb90, 0xfffc0007}, - {0xb91, 0xfffc000f}, - {0xb92, 0xfffc001f}, - {0xb93, 0xfffc003f}, - {0xb94, 0xfffc007f}, - {0xb95, 0xfffc00ff}, - {0xb96, 0xfffc01ff}, - {0xb97, 0xfffc03ff}, - {0xb98, 0xfffc07ff}, - {0xb99, 0xfffc0fff}, - {0xb9a, 0xfffc1fff}, - {0xb9b, 0xfffc3fff}, - {0xb9c, 0xfffc7fff}, - {0xfad, 0xfffcfffc}, - {0xb9d, 0xfffcffff}, - {0xfae, 0xfffdfffd}, - {0xb9e, 0xfffdffff}, - {0xbce, 0xfffe0000}, - {0xbcf, 0xfffe0001}, - {0xbd0, 0xfffe0003}, - {0xbd1, 0xfffe0007}, - {0xbd2, 0xfffe000f}, - {0xbd3, 0xfffe001f}, - {0xbd4, 0xfffe003f}, - {0xbd5, 0xfffe007f}, - {0xbd6, 0xfffe00ff}, - {0xbd7, 0xfffe01ff}, - {0xbd8, 0xfffe03ff}, - {0xbd9, 0xfffe07ff}, - {0xbda, 0xfffe0fff}, - {0xbdb, 0xfffe1fff}, - {0xbdc, 0xfffe3fff}, - {0xbdd, 0xfffe7fff}, - {0xfee, 0xfffefffe}, - {0xbde, 0xfffeffff}, - {0xc0f, 0xffff0000}, - {0xc10, 0xffff0001}, - {0xc11, 0xffff0003}, - {0xc12, 0xffff0007}, - {0xc13, 0xffff000f}, - {0xc14, 0xffff001f}, - {0xc15, 0xffff003f}, - {0xc16, 0xffff007f}, - {0xc17, 0xffff00ff}, - {0xc18, 0xffff01ff}, - {0xc19, 0xffff03ff}, - {0xc1a, 0xffff07ff}, - {0xc1b, 0xffff0fff}, - {0xc1c, 0xffff1fff}, - {0xc1d, 0xffff3fff}, - {0xc1e, 0xffff7fff}, - {0xc50, 0xffff8000}, - {0xc51, 0xffff8001}, - {0xc52, 0xffff8003}, - {0xc53, 0xffff8007}, - {0xc54, 0xffff800f}, - {0xc55, 0xffff801f}, - {0xc56, 0xffff803f}, - {0xc57, 0xffff807f}, - {0xc58, 0xffff80ff}, - {0xc59, 0xffff81ff}, - {0xc5a, 0xffff83ff}, - {0xc5b, 0xffff87ff}, - {0xc5c, 0xffff8fff}, - {0xc5d, 0xffff9fff}, - {0xc5e, 0xffffbfff}, - {0xc91, 0xffffc000}, - {0xc92, 0xffffc001}, - {0xc93, 0xffffc003}, - {0xc94, 0xffffc007}, - {0xc95, 0xffffc00f}, - {0xc96, 0xffffc01f}, - {0xc97, 0xffffc03f}, - {0xc98, 0xffffc07f}, - {0xc99, 0xffffc0ff}, - {0xc9a, 0xffffc1ff}, - {0xc9b, 0xffffc3ff}, - {0xc9c, 0xffffc7ff}, - {0xc9d, 0xffffcfff}, - {0xc9e, 0xffffdfff}, - {0xcd2, 0xffffe000}, - {0xcd3, 0xffffe001}, - {0xcd4, 0xffffe003}, - {0xcd5, 0xffffe007}, - {0xcd6, 0xffffe00f}, - {0xcd7, 0xffffe01f}, - {0xcd8, 0xffffe03f}, - {0xcd9, 0xffffe07f}, - {0xcda, 0xffffe0ff}, - {0xcdb, 0xffffe1ff}, - {0xcdc, 0xffffe3ff}, - {0xcdd, 0xffffe7ff}, - {0xcde, 0xffffefff}, - {0xd13, 0xfffff000}, - {0xd14, 0xfffff001}, - {0xd15, 0xfffff003}, - {0xd16, 0xfffff007}, - {0xd17, 0xfffff00f}, - {0xd18, 0xfffff01f}, - {0xd19, 0xfffff03f}, - {0xd1a, 0xfffff07f}, - {0xd1b, 0xfffff0ff}, - {0xd1c, 0xfffff1ff}, - {0xd1d, 0xfffff3ff}, - {0xd1e, 0xfffff7ff}, - {0xd54, 0xfffff800}, - {0xd55, 0xfffff801}, - {0xd56, 0xfffff803}, - {0xd57, 0xfffff807}, - {0xd58, 0xfffff80f}, - {0xd59, 0xfffff81f}, - {0xd5a, 0xfffff83f}, - {0xd5b, 0xfffff87f}, - {0xd5c, 0xfffff8ff}, - {0xd5d, 0xfffff9ff}, - {0xd5e, 0xfffffbff}, - {0xd95, 0xfffffc00}, - {0xd96, 0xfffffc01}, - {0xd97, 0xfffffc03}, - {0xd98, 0xfffffc07}, - {0xd99, 0xfffffc0f}, - {0xd9a, 0xfffffc1f}, - {0xd9b, 0xfffffc3f}, - {0xd9c, 0xfffffc7f}, - {0xd9d, 0xfffffcff}, - {0xd9e, 0xfffffdff}, - {0xdd6, 0xfffffe00}, - {0xdd7, 0xfffffe01}, - {0xdd8, 0xfffffe03}, - {0xdd9, 0xfffffe07}, - {0xdda, 0xfffffe0f}, - {0xddb, 0xfffffe1f}, - {0xddc, 0xfffffe3f}, - {0xddd, 0xfffffe7f}, - {0xdde, 0xfffffeff}, - {0xe17, 0xffffff00}, - {0xe18, 0xffffff01}, - {0xe19, 0xffffff03}, - {0xe1a, 0xffffff07}, - {0xe1b, 0xffffff0f}, - {0xe1c, 0xffffff1f}, - {0xe1d, 0xffffff3f}, - {0xe1e, 0xffffff7f}, - {0xe58, 0xffffff80}, - {0xe59, 0xffffff81}, - {0xe5a, 0xffffff83}, - {0xe5b, 0xffffff87}, - {0xe5c, 0xffffff8f}, - {0xe5d, 0xffffff9f}, - {0xe5e, 0xffffffbf}, - {0xe99, 0xffffffc0}, - {0xe9a, 0xffffffc1}, - {0xe9b, 0xffffffc3}, - {0xe9c, 0xffffffc7}, - {0xe9d, 0xffffffcf}, - {0xe9e, 0xffffffdf}, - {0xeda, 0xffffffe0}, - {0xedb, 0xffffffe1}, - {0xedc, 0xffffffe3}, - {0xedd, 0xffffffe7}, - {0xede, 0xffffffef}, - {0xf1b, 0xfffffff0}, - {0xf1c, 0xfffffff1}, - {0xf1d, 0xfffffff3}, - {0xf1e, 0xfffffff7}, - {0xf5c, 0xfffffff8}, - {0xf5d, 0xfffffff9}, - {0xf5e, 0xfffffffb}, - {0xf9d, 0xfffffffc}, - {0xf9e, 0xfffffffd}, - {0xfde, 0xfffffffe}, +static uint32_t imm_table[][2] = { + {0x800, 0x00000001}, + { 0xfc0, 0x00000002}, + { 0x801, 0x00000003}, + { 0xf80, 0x00000004}, + { 0xfc1, 0x00000006}, + { 0x802, 0x00000007}, + { 0xf40, 0x00000008}, + { 0xf81, 0x0000000c}, + { 0xfc2, 0x0000000e}, + { 0x803, 0x0000000f}, + { 0xf00, 0x00000010}, + { 0xf41, 0x00000018}, + { 0xf82, 0x0000001c}, + { 0xfc3, 0x0000001e}, + { 0x804, 0x0000001f}, + { 0xec0, 0x00000020}, + { 0xf01, 0x00000030}, + { 0xf42, 0x00000038}, + { 0xf83, 0x0000003c}, + { 0xfc4, 0x0000003e}, + { 0x805, 0x0000003f}, + { 0xe80, 0x00000040}, + { 0xec1, 0x00000060}, + { 0xf02, 0x00000070}, + { 0xf43, 0x00000078}, + { 0xf84, 0x0000007c}, + { 0xfc5, 0x0000007e}, + { 0x806, 0x0000007f}, + { 0xe40, 0x00000080}, + { 0xe81, 0x000000c0}, + { 0xec2, 0x000000e0}, + { 0xf03, 0x000000f0}, + { 0xf44, 0x000000f8}, + { 0xf85, 0x000000fc}, + { 0xfc6, 0x000000fe}, + { 0x807, 0x000000ff}, + { 0xe00, 0x00000100}, + { 0xe41, 0x00000180}, + { 0xe82, 0x000001c0}, + { 0xec3, 0x000001e0}, + { 0xf04, 0x000001f0}, + { 0xf45, 0x000001f8}, + { 0xf86, 0x000001fc}, + { 0xfc7, 0x000001fe}, + { 0x808, 0x000001ff}, + { 0xdc0, 0x00000200}, + { 0xe01, 0x00000300}, + { 0xe42, 0x00000380}, + { 0xe83, 0x000003c0}, + { 0xec4, 0x000003e0}, + { 0xf05, 0x000003f0}, + { 0xf46, 0x000003f8}, + { 0xf87, 0x000003fc}, + { 0xfc8, 0x000003fe}, + { 0x809, 0x000003ff}, + { 0xd80, 0x00000400}, + { 0xdc1, 0x00000600}, + { 0xe02, 0x00000700}, + { 0xe43, 0x00000780}, + { 0xe84, 0x000007c0}, + { 0xec5, 0x000007e0}, + { 0xf06, 0x000007f0}, + { 0xf47, 0x000007f8}, + { 0xf88, 0x000007fc}, + { 0xfc9, 0x000007fe}, + { 0x80a, 0x000007ff}, + { 0xd40, 0x00000800}, + { 0xd81, 0x00000c00}, + { 0xdc2, 0x00000e00}, + { 0xe03, 0x00000f00}, + { 0xe44, 0x00000f80}, + { 0xe85, 0x00000fc0}, + { 0xec6, 0x00000fe0}, + { 0xf07, 0x00000ff0}, + { 0xf48, 0x00000ff8}, + { 0xf89, 0x00000ffc}, + { 0xfca, 0x00000ffe}, + { 0x80b, 0x00000fff}, + { 0xd00, 0x00001000}, + { 0xd41, 0x00001800}, + { 0xd82, 0x00001c00}, + { 0xdc3, 0x00001e00}, + { 0xe04, 0x00001f00}, + { 0xe45, 0x00001f80}, + { 0xe86, 0x00001fc0}, + { 0xec7, 0x00001fe0}, + { 0xf08, 0x00001ff0}, + { 0xf49, 0x00001ff8}, + { 0xf8a, 0x00001ffc}, + { 0xfcb, 0x00001ffe}, + { 0x80c, 0x00001fff}, + { 0xcc0, 0x00002000}, + { 0xd01, 0x00003000}, + { 0xd42, 0x00003800}, + { 0xd83, 0x00003c00}, + { 0xdc4, 0x00003e00}, + { 0xe05, 0x00003f00}, + { 0xe46, 0x00003f80}, + { 0xe87, 0x00003fc0}, + { 0xec8, 0x00003fe0}, + { 0xf09, 0x00003ff0}, + { 0xf4a, 0x00003ff8}, + { 0xf8b, 0x00003ffc}, + { 0xfcc, 0x00003ffe}, + { 0x80d, 0x00003fff}, + { 0xc80, 0x00004000}, + { 0xcc1, 0x00006000}, + { 0xd02, 0x00007000}, + { 0xd43, 0x00007800}, + { 0xd84, 0x00007c00}, + { 0xdc5, 0x00007e00}, + { 0xe06, 0x00007f00}, + { 0xe47, 0x00007f80}, + { 0xe88, 0x00007fc0}, + { 0xec9, 0x00007fe0}, + { 0xf0a, 0x00007ff0}, + { 0xf4b, 0x00007ff8}, + { 0xf8c, 0x00007ffc}, + { 0xfcd, 0x00007ffe}, + { 0x80e, 0x00007fff}, + { 0xc40, 0x00008000}, + { 0xc81, 0x0000c000}, + { 0xcc2, 0x0000e000}, + { 0xd03, 0x0000f000}, + { 0xd44, 0x0000f800}, + { 0xd85, 0x0000fc00}, + { 0xdc6, 0x0000fe00}, + { 0xe07, 0x0000ff00}, + { 0xe48, 0x0000ff80}, + { 0xe89, 0x0000ffc0}, + { 0xeca, 0x0000ffe0}, + { 0xf0b, 0x0000fff0}, + { 0xf4c, 0x0000fff8}, + { 0xf8d, 0x0000fffc}, + { 0xfce, 0x0000fffe}, + { 0x80f, 0x0000ffff}, + { 0xc00, 0x00010000}, + { 0xc20, 0x00010001}, + { 0xc41, 0x00018000}, + { 0xc82, 0x0001c000}, + { 0xcc3, 0x0001e000}, + { 0xd04, 0x0001f000}, + { 0xd45, 0x0001f800}, + { 0xd86, 0x0001fc00}, + { 0xdc7, 0x0001fe00}, + { 0xe08, 0x0001ff00}, + { 0xe49, 0x0001ff80}, + { 0xe8a, 0x0001ffc0}, + { 0xecb, 0x0001ffe0}, + { 0xf0c, 0x0001fff0}, + { 0xf4d, 0x0001fff8}, + { 0xf8e, 0x0001fffc}, + { 0xfcf, 0x0001fffe}, + { 0x810, 0x0001ffff}, + { 0xbc0, 0x00020000}, + { 0xfe0, 0x00020002}, + { 0xc01, 0x00030000}, + { 0xc21, 0x00030003}, + { 0xc42, 0x00038000}, + { 0xc83, 0x0003c000}, + { 0xcc4, 0x0003e000}, + { 0xd05, 0x0003f000}, + { 0xd46, 0x0003f800}, + { 0xd87, 0x0003fc00}, + { 0xdc8, 0x0003fe00}, + { 0xe09, 0x0003ff00}, + { 0xe4a, 0x0003ff80}, + { 0xe8b, 0x0003ffc0}, + { 0xecc, 0x0003ffe0}, + { 0xf0d, 0x0003fff0}, + { 0xf4e, 0x0003fff8}, + { 0xf8f, 0x0003fffc}, + { 0xfd0, 0x0003fffe}, + { 0x811, 0x0003ffff}, + { 0xb80, 0x00040000}, + { 0xfa0, 0x00040004}, + { 0xbc1, 0x00060000}, + { 0xfe1, 0x00060006}, + { 0xc02, 0x00070000}, + { 0xc22, 0x00070007}, + { 0xc43, 0x00078000}, + { 0xc84, 0x0007c000}, + { 0xcc5, 0x0007e000}, + { 0xd06, 0x0007f000}, + { 0xd47, 0x0007f800}, + { 0xd88, 0x0007fc00}, + { 0xdc9, 0x0007fe00}, + { 0xe0a, 0x0007ff00}, + { 0xe4b, 0x0007ff80}, + { 0xe8c, 0x0007ffc0}, + { 0xecd, 0x0007ffe0}, + { 0xf0e, 0x0007fff0}, + { 0xf4f, 0x0007fff8}, + { 0xf90, 0x0007fffc}, + { 0xfd1, 0x0007fffe}, + { 0x812, 0x0007ffff}, + { 0xb40, 0x00080000}, + { 0xf60, 0x00080008}, + { 0xb81, 0x000c0000}, + { 0xfa1, 0x000c000c}, + { 0xbc2, 0x000e0000}, + { 0xfe2, 0x000e000e}, + { 0xc03, 0x000f0000}, + { 0xc23, 0x000f000f}, + { 0xc44, 0x000f8000}, + { 0xc85, 0x000fc000}, + { 0xcc6, 0x000fe000}, + { 0xd07, 0x000ff000}, + { 0xd48, 0x000ff800}, + { 0xd89, 0x000ffc00}, + { 0xdca, 0x000ffe00}, + { 0xe0b, 0x000fff00}, + { 0xe4c, 0x000fff80}, + { 0xe8d, 0x000fffc0}, + { 0xece, 0x000fffe0}, + { 0xf0f, 0x000ffff0}, + { 0xf50, 0x000ffff8}, + { 0xf91, 0x000ffffc}, + { 0xfd2, 0x000ffffe}, + { 0x813, 0x000fffff}, + { 0xb00, 0x00100000}, + { 0xf20, 0x00100010}, + { 0xb41, 0x00180000}, + { 0xf61, 0x00180018}, + { 0xb82, 0x001c0000}, + { 0xfa2, 0x001c001c}, + { 0xbc3, 0x001e0000}, + { 0xfe3, 0x001e001e}, + { 0xc04, 0x001f0000}, + { 0xc24, 0x001f001f}, + { 0xc45, 0x001f8000}, + { 0xc86, 0x001fc000}, + { 0xcc7, 0x001fe000}, + { 0xd08, 0x001ff000}, + { 0xd49, 0x001ff800}, + { 0xd8a, 0x001ffc00}, + { 0xdcb, 0x001ffe00}, + { 0xe0c, 0x001fff00}, + { 0xe4d, 0x001fff80}, + { 0xe8e, 0x001fffc0}, + { 0xecf, 0x001fffe0}, + { 0xf10, 0x001ffff0}, + { 0xf51, 0x001ffff8}, + { 0xf92, 0x001ffffc}, + { 0xfd3, 0x001ffffe}, + { 0x814, 0x001fffff}, + { 0xac0, 0x00200000}, + { 0xee0, 0x00200020}, + { 0xb01, 0x00300000}, + { 0xf21, 0x00300030}, + { 0xb42, 0x00380000}, + { 0xf62, 0x00380038}, + { 0xb83, 0x003c0000}, + { 0xfa3, 0x003c003c}, + { 0xbc4, 0x003e0000}, + { 0xfe4, 0x003e003e}, + { 0xc05, 0x003f0000}, + { 0xc25, 0x003f003f}, + { 0xc46, 0x003f8000}, + { 0xc87, 0x003fc000}, + { 0xcc8, 0x003fe000}, + { 0xd09, 0x003ff000}, + { 0xd4a, 0x003ff800}, + { 0xd8b, 0x003ffc00}, + { 0xdcc, 0x003ffe00}, + { 0xe0d, 0x003fff00}, + { 0xe4e, 0x003fff80}, + { 0xe8f, 0x003fffc0}, + { 0xed0, 0x003fffe0}, + { 0xf11, 0x003ffff0}, + { 0xf52, 0x003ffff8}, + { 0xf93, 0x003ffffc}, + { 0xfd4, 0x003ffffe}, + { 0x815, 0x003fffff}, + { 0xa80, 0x00400000}, + { 0xea0, 0x00400040}, + { 0xac1, 0x00600000}, + { 0xee1, 0x00600060}, + { 0xb02, 0x00700000}, + { 0xf22, 0x00700070}, + { 0xb43, 0x00780000}, + { 0xf63, 0x00780078}, + { 0xb84, 0x007c0000}, + { 0xfa4, 0x007c007c}, + { 0xbc5, 0x007e0000}, + { 0xfe5, 0x007e007e}, + { 0xc06, 0x007f0000}, + { 0xc26, 0x007f007f}, + { 0xc47, 0x007f8000}, + { 0xc88, 0x007fc000}, + { 0xcc9, 0x007fe000}, + { 0xd0a, 0x007ff000}, + { 0xd4b, 0x007ff800}, + { 0xd8c, 0x007ffc00}, + { 0xdcd, 0x007ffe00}, + { 0xe0e, 0x007fff00}, + { 0xe4f, 0x007fff80}, + { 0xe90, 0x007fffc0}, + { 0xed1, 0x007fffe0}, + { 0xf12, 0x007ffff0}, + { 0xf53, 0x007ffff8}, + { 0xf94, 0x007ffffc}, + { 0xfd5, 0x007ffffe}, + { 0x816, 0x007fffff}, + { 0xa40, 0x00800000}, + { 0xe60, 0x00800080}, + { 0xa81, 0x00c00000}, + { 0xea1, 0x00c000c0}, + { 0xac2, 0x00e00000}, + { 0xee2, 0x00e000e0}, + { 0xb03, 0x00f00000}, + { 0xf23, 0x00f000f0}, + { 0xb44, 0x00f80000}, + { 0xf64, 0x00f800f8}, + { 0xb85, 0x00fc0000}, + { 0xfa5, 0x00fc00fc}, + { 0xbc6, 0x00fe0000}, + { 0xfe6, 0x00fe00fe}, + { 0xc07, 0x00ff0000}, + { 0xc27, 0x00ff00ff}, + { 0xc48, 0x00ff8000}, + { 0xc89, 0x00ffc000}, + { 0xcca, 0x00ffe000}, + { 0xd0b, 0x00fff000}, + { 0xd4c, 0x00fff800}, + { 0xd8d, 0x00fffc00}, + { 0xdce, 0x00fffe00}, + { 0xe0f, 0x00ffff00}, + { 0xe50, 0x00ffff80}, + { 0xe91, 0x00ffffc0}, + { 0xed2, 0x00ffffe0}, + { 0xf13, 0x00fffff0}, + { 0xf54, 0x00fffff8}, + { 0xf95, 0x00fffffc}, + { 0xfd6, 0x00fffffe}, + { 0x817, 0x00ffffff}, + { 0xa00, 0x01000000}, + { 0xe20, 0x01000100}, + { 0xe30, 0x01010101}, + { 0xa41, 0x01800000}, + { 0xe61, 0x01800180}, + { 0xa82, 0x01c00000}, + { 0xea2, 0x01c001c0}, + { 0xac3, 0x01e00000}, + { 0xee3, 0x01e001e0}, + { 0xb04, 0x01f00000}, + { 0xf24, 0x01f001f0}, + { 0xb45, 0x01f80000}, + { 0xf65, 0x01f801f8}, + { 0xb86, 0x01fc0000}, + { 0xfa6, 0x01fc01fc}, + { 0xbc7, 0x01fe0000}, + { 0xfe7, 0x01fe01fe}, + { 0xc08, 0x01ff0000}, + { 0xc28, 0x01ff01ff}, + { 0xc49, 0x01ff8000}, + { 0xc8a, 0x01ffc000}, + { 0xccb, 0x01ffe000}, + { 0xd0c, 0x01fff000}, + { 0xd4d, 0x01fff800}, + { 0xd8e, 0x01fffc00}, + { 0xdcf, 0x01fffe00}, + { 0xe10, 0x01ffff00}, + { 0xe51, 0x01ffff80}, + { 0xe92, 0x01ffffc0}, + { 0xed3, 0x01ffffe0}, + { 0xf14, 0x01fffff0}, + { 0xf55, 0x01fffff8}, + { 0xf96, 0x01fffffc}, + { 0xfd7, 0x01fffffe}, + { 0x818, 0x01ffffff}, + { 0x9c0, 0x02000000}, + { 0xde0, 0x02000200}, + { 0xff0, 0x02020202}, + { 0xa01, 0x03000000}, + { 0xe21, 0x03000300}, + { 0xe31, 0x03030303}, + { 0xa42, 0x03800000}, + { 0xe62, 0x03800380}, + { 0xa83, 0x03c00000}, + { 0xea3, 0x03c003c0}, + { 0xac4, 0x03e00000}, + { 0xee4, 0x03e003e0}, + { 0xb05, 0x03f00000}, + { 0xf25, 0x03f003f0}, + { 0xb46, 0x03f80000}, + { 0xf66, 0x03f803f8}, + { 0xb87, 0x03fc0000}, + { 0xfa7, 0x03fc03fc}, + { 0xbc8, 0x03fe0000}, + { 0xfe8, 0x03fe03fe}, + { 0xc09, 0x03ff0000}, + { 0xc29, 0x03ff03ff}, + { 0xc4a, 0x03ff8000}, + { 0xc8b, 0x03ffc000}, + { 0xccc, 0x03ffe000}, + { 0xd0d, 0x03fff000}, + { 0xd4e, 0x03fff800}, + { 0xd8f, 0x03fffc00}, + { 0xdd0, 0x03fffe00}, + { 0xe11, 0x03ffff00}, + { 0xe52, 0x03ffff80}, + { 0xe93, 0x03ffffc0}, + { 0xed4, 0x03ffffe0}, + { 0xf15, 0x03fffff0}, + { 0xf56, 0x03fffff8}, + { 0xf97, 0x03fffffc}, + { 0xfd8, 0x03fffffe}, + { 0x819, 0x03ffffff}, + { 0x980, 0x04000000}, + { 0xda0, 0x04000400}, + { 0xfb0, 0x04040404}, + { 0x9c1, 0x06000000}, + { 0xde1, 0x06000600}, + { 0xff1, 0x06060606}, + { 0xa02, 0x07000000}, + { 0xe22, 0x07000700}, + { 0xe32, 0x07070707}, + { 0xa43, 0x07800000}, + { 0xe63, 0x07800780}, + { 0xa84, 0x07c00000}, + { 0xea4, 0x07c007c0}, + { 0xac5, 0x07e00000}, + { 0xee5, 0x07e007e0}, + { 0xb06, 0x07f00000}, + { 0xf26, 0x07f007f0}, + { 0xb47, 0x07f80000}, + { 0xf67, 0x07f807f8}, + { 0xb88, 0x07fc0000}, + { 0xfa8, 0x07fc07fc}, + { 0xbc9, 0x07fe0000}, + { 0xfe9, 0x07fe07fe}, + { 0xc0a, 0x07ff0000}, + { 0xc2a, 0x07ff07ff}, + { 0xc4b, 0x07ff8000}, + { 0xc8c, 0x07ffc000}, + { 0xccd, 0x07ffe000}, + { 0xd0e, 0x07fff000}, + { 0xd4f, 0x07fff800}, + { 0xd90, 0x07fffc00}, + { 0xdd1, 0x07fffe00}, + { 0xe12, 0x07ffff00}, + { 0xe53, 0x07ffff80}, + { 0xe94, 0x07ffffc0}, + { 0xed5, 0x07ffffe0}, + { 0xf16, 0x07fffff0}, + { 0xf57, 0x07fffff8}, + { 0xf98, 0x07fffffc}, + { 0xfd9, 0x07fffffe}, + { 0x81a, 0x07ffffff}, + { 0x940, 0x08000000}, + { 0xd60, 0x08000800}, + { 0xf70, 0x08080808}, + { 0x981, 0x0c000000}, + { 0xda1, 0x0c000c00}, + { 0xfb1, 0x0c0c0c0c}, + { 0x9c2, 0x0e000000}, + { 0xde2, 0x0e000e00}, + { 0xff2, 0x0e0e0e0e}, + { 0xa03, 0x0f000000}, + { 0xe23, 0x0f000f00}, + { 0xe33, 0x0f0f0f0f}, + { 0xa44, 0x0f800000}, + { 0xe64, 0x0f800f80}, + { 0xa85, 0x0fc00000}, + { 0xea5, 0x0fc00fc0}, + { 0xac6, 0x0fe00000}, + { 0xee6, 0x0fe00fe0}, + { 0xb07, 0x0ff00000}, + { 0xf27, 0x0ff00ff0}, + { 0xb48, 0x0ff80000}, + { 0xf68, 0x0ff80ff8}, + { 0xb89, 0x0ffc0000}, + { 0xfa9, 0x0ffc0ffc}, + { 0xbca, 0x0ffe0000}, + { 0xfea, 0x0ffe0ffe}, + { 0xc0b, 0x0fff0000}, + { 0xc2b, 0x0fff0fff}, + { 0xc4c, 0x0fff8000}, + { 0xc8d, 0x0fffc000}, + { 0xcce, 0x0fffe000}, + { 0xd0f, 0x0ffff000}, + { 0xd50, 0x0ffff800}, + { 0xd91, 0x0ffffc00}, + { 0xdd2, 0x0ffffe00}, + { 0xe13, 0x0fffff00}, + { 0xe54, 0x0fffff80}, + { 0xe95, 0x0fffffc0}, + { 0xed6, 0x0fffffe0}, + { 0xf17, 0x0ffffff0}, + { 0xf58, 0x0ffffff8}, + { 0xf99, 0x0ffffffc}, + { 0xfda, 0x0ffffffe}, + { 0x81b, 0x0fffffff}, + { 0x900, 0x10000000}, + { 0xd20, 0x10001000}, + { 0xf30, 0x10101010}, + { 0xf38, 0x11111111}, + { 0x941, 0x18000000}, + { 0xd61, 0x18001800}, + { 0xf71, 0x18181818}, + { 0x982, 0x1c000000}, + { 0xda2, 0x1c001c00}, + { 0xfb2, 0x1c1c1c1c}, + { 0x9c3, 0x1e000000}, + { 0xde3, 0x1e001e00}, + { 0xff3, 0x1e1e1e1e}, + { 0xa04, 0x1f000000}, + { 0xe24, 0x1f001f00}, + { 0xe34, 0x1f1f1f1f}, + { 0xa45, 0x1f800000}, + { 0xe65, 0x1f801f80}, + { 0xa86, 0x1fc00000}, + { 0xea6, 0x1fc01fc0}, + { 0xac7, 0x1fe00000}, + { 0xee7, 0x1fe01fe0}, + { 0xb08, 0x1ff00000}, + { 0xf28, 0x1ff01ff0}, + { 0xb49, 0x1ff80000}, + { 0xf69, 0x1ff81ff8}, + { 0xb8a, 0x1ffc0000}, + { 0xfaa, 0x1ffc1ffc}, + { 0xbcb, 0x1ffe0000}, + { 0xfeb, 0x1ffe1ffe}, + { 0xc0c, 0x1fff0000}, + { 0xc2c, 0x1fff1fff}, + { 0xc4d, 0x1fff8000}, + { 0xc8e, 0x1fffc000}, + { 0xccf, 0x1fffe000}, + { 0xd10, 0x1ffff000}, + { 0xd51, 0x1ffff800}, + { 0xd92, 0x1ffffc00}, + { 0xdd3, 0x1ffffe00}, + { 0xe14, 0x1fffff00}, + { 0xe55, 0x1fffff80}, + { 0xe96, 0x1fffffc0}, + { 0xed7, 0x1fffffe0}, + { 0xf18, 0x1ffffff0}, + { 0xf59, 0x1ffffff8}, + { 0xf9a, 0x1ffffffc}, + { 0xfdb, 0x1ffffffe}, + { 0x81c, 0x1fffffff}, + { 0x8c0, 0x20000000}, + { 0xce0, 0x20002000}, + { 0xef0, 0x20202020}, + { 0xff8, 0x22222222}, + { 0x901, 0x30000000}, + { 0xd21, 0x30003000}, + { 0xf31, 0x30303030}, + { 0xf39, 0x33333333}, + { 0x942, 0x38000000}, + { 0xd62, 0x38003800}, + { 0xf72, 0x38383838}, + { 0x983, 0x3c000000}, + { 0xda3, 0x3c003c00}, + { 0xfb3, 0x3c3c3c3c}, + { 0x9c4, 0x3e000000}, + { 0xde4, 0x3e003e00}, + { 0xff4, 0x3e3e3e3e}, + { 0xa05, 0x3f000000}, + { 0xe25, 0x3f003f00}, + { 0xe35, 0x3f3f3f3f}, + { 0xa46, 0x3f800000}, + { 0xe66, 0x3f803f80}, + { 0xa87, 0x3fc00000}, + { 0xea7, 0x3fc03fc0}, + { 0xac8, 0x3fe00000}, + { 0xee8, 0x3fe03fe0}, + { 0xb09, 0x3ff00000}, + { 0xf29, 0x3ff03ff0}, + { 0xb4a, 0x3ff80000}, + { 0xf6a, 0x3ff83ff8}, + { 0xb8b, 0x3ffc0000}, + { 0xfab, 0x3ffc3ffc}, + { 0xbcc, 0x3ffe0000}, + { 0xfec, 0x3ffe3ffe}, + { 0xc0d, 0x3fff0000}, + { 0xc2d, 0x3fff3fff}, + { 0xc4e, 0x3fff8000}, + { 0xc8f, 0x3fffc000}, + { 0xcd0, 0x3fffe000}, + { 0xd11, 0x3ffff000}, + { 0xd52, 0x3ffff800}, + { 0xd93, 0x3ffffc00}, + { 0xdd4, 0x3ffffe00}, + { 0xe15, 0x3fffff00}, + { 0xe56, 0x3fffff80}, + { 0xe97, 0x3fffffc0}, + { 0xed8, 0x3fffffe0}, + { 0xf19, 0x3ffffff0}, + { 0xf5a, 0x3ffffff8}, + { 0xf9b, 0x3ffffffc}, + { 0xfdc, 0x3ffffffe}, + { 0x81d, 0x3fffffff}, + { 0x880, 0x40000000}, + { 0xca0, 0x40004000}, + { 0xeb0, 0x40404040}, + { 0xfb8, 0x44444444}, + { 0xfbc, 0x55555555}, + { 0x8c1, 0x60000000}, + { 0xce1, 0x60006000}, + { 0xef1, 0x60606060}, + { 0xff9, 0x66666666}, + { 0x902, 0x70000000}, + { 0xd22, 0x70007000}, + { 0xf32, 0x70707070}, + { 0xf3a, 0x77777777}, + { 0x943, 0x78000000}, + { 0xd63, 0x78007800}, + { 0xf73, 0x78787878}, + { 0x984, 0x7c000000}, + { 0xda4, 0x7c007c00}, + { 0xfb4, 0x7c7c7c7c}, + { 0x9c5, 0x7e000000}, + { 0xde5, 0x7e007e00}, + { 0xff5, 0x7e7e7e7e}, + { 0xa06, 0x7f000000}, + { 0xe26, 0x7f007f00}, + { 0xe36, 0x7f7f7f7f}, + { 0xa47, 0x7f800000}, + { 0xe67, 0x7f807f80}, + { 0xa88, 0x7fc00000}, + { 0xea8, 0x7fc07fc0}, + { 0xac9, 0x7fe00000}, + { 0xee9, 0x7fe07fe0}, + { 0xb0a, 0x7ff00000}, + { 0xf2a, 0x7ff07ff0}, + { 0xb4b, 0x7ff80000}, + { 0xf6b, 0x7ff87ff8}, + { 0xb8c, 0x7ffc0000}, + { 0xfac, 0x7ffc7ffc}, + { 0xbcd, 0x7ffe0000}, + { 0xfed, 0x7ffe7ffe}, + { 0xc0e, 0x7fff0000}, + { 0xc2e, 0x7fff7fff}, + { 0xc4f, 0x7fff8000}, + { 0xc90, 0x7fffc000}, + { 0xcd1, 0x7fffe000}, + { 0xd12, 0x7ffff000}, + { 0xd53, 0x7ffff800}, + { 0xd94, 0x7ffffc00}, + { 0xdd5, 0x7ffffe00}, + { 0xe16, 0x7fffff00}, + { 0xe57, 0x7fffff80}, + { 0xe98, 0x7fffffc0}, + { 0xed9, 0x7fffffe0}, + { 0xf1a, 0x7ffffff0}, + { 0xf5b, 0x7ffffff8}, + { 0xf9c, 0x7ffffffc}, + { 0xfdd, 0x7ffffffe}, + { 0x81e, 0x7fffffff}, + { 0x840, 0x80000000}, + { 0x841, 0x80000001}, + { 0x842, 0x80000003}, + { 0x843, 0x80000007}, + { 0x844, 0x8000000f}, + { 0x845, 0x8000001f}, + { 0x846, 0x8000003f}, + { 0x847, 0x8000007f}, + { 0x848, 0x800000ff}, + { 0x849, 0x800001ff}, + { 0x84a, 0x800003ff}, + { 0x84b, 0x800007ff}, + { 0x84c, 0x80000fff}, + { 0x84d, 0x80001fff}, + { 0x84e, 0x80003fff}, + { 0x84f, 0x80007fff}, + { 0xc60, 0x80008000}, + { 0x850, 0x8000ffff}, + { 0xc61, 0x80018001}, + { 0x851, 0x8001ffff}, + { 0xc62, 0x80038003}, + { 0x852, 0x8003ffff}, + { 0xc63, 0x80078007}, + { 0x853, 0x8007ffff}, + { 0xc64, 0x800f800f}, + { 0x854, 0x800fffff}, + { 0xc65, 0x801f801f}, + { 0x855, 0x801fffff}, + { 0xc66, 0x803f803f}, + { 0x856, 0x803fffff}, + { 0xc67, 0x807f807f}, + { 0x857, 0x807fffff}, + { 0xe70, 0x80808080}, + { 0xc68, 0x80ff80ff}, + { 0x858, 0x80ffffff}, + { 0xe71, 0x81818181}, + { 0xc69, 0x81ff81ff}, + { 0x859, 0x81ffffff}, + { 0xe72, 0x83838383}, + { 0xc6a, 0x83ff83ff}, + { 0x85a, 0x83ffffff}, + { 0xe73, 0x87878787}, + { 0xc6b, 0x87ff87ff}, + { 0x85b, 0x87ffffff}, + { 0xf78, 0x88888888}, + { 0xe74, 0x8f8f8f8f}, + { 0xc6c, 0x8fff8fff}, + { 0x85c, 0x8fffffff}, + { 0xf79, 0x99999999}, + { 0xe75, 0x9f9f9f9f}, + { 0xc6d, 0x9fff9fff}, + { 0x85d, 0x9fffffff}, + { 0xffc, 0xaaaaaaaa}, + { 0xf7a, 0xbbbbbbbb}, + { 0xe76, 0xbfbfbfbf}, + { 0xc6e, 0xbfffbfff}, + { 0x85e, 0xbfffffff}, + { 0x881, 0xc0000000}, + { 0x882, 0xc0000001}, + { 0x883, 0xc0000003}, + { 0x884, 0xc0000007}, + { 0x885, 0xc000000f}, + { 0x886, 0xc000001f}, + { 0x887, 0xc000003f}, + { 0x888, 0xc000007f}, + { 0x889, 0xc00000ff}, + { 0x88a, 0xc00001ff}, + { 0x88b, 0xc00003ff}, + { 0x88c, 0xc00007ff}, + { 0x88d, 0xc0000fff}, + { 0x88e, 0xc0001fff}, + { 0x88f, 0xc0003fff}, + { 0x890, 0xc0007fff}, + { 0xca1, 0xc000c000}, + { 0x891, 0xc000ffff}, + { 0xca2, 0xc001c001}, + { 0x892, 0xc001ffff}, + { 0xca3, 0xc003c003}, + { 0x893, 0xc003ffff}, + { 0xca4, 0xc007c007}, + { 0x894, 0xc007ffff}, + { 0xca5, 0xc00fc00f}, + { 0x895, 0xc00fffff}, + { 0xca6, 0xc01fc01f}, + { 0x896, 0xc01fffff}, + { 0xca7, 0xc03fc03f}, + { 0x897, 0xc03fffff}, + { 0xca8, 0xc07fc07f}, + { 0x898, 0xc07fffff}, + { 0xeb1, 0xc0c0c0c0}, + { 0xca9, 0xc0ffc0ff}, + { 0x899, 0xc0ffffff}, + { 0xeb2, 0xc1c1c1c1}, + { 0xcaa, 0xc1ffc1ff}, + { 0x89a, 0xc1ffffff}, + { 0xeb3, 0xc3c3c3c3}, + { 0xcab, 0xc3ffc3ff}, + { 0x89b, 0xc3ffffff}, + { 0xeb4, 0xc7c7c7c7}, + { 0xcac, 0xc7ffc7ff}, + { 0x89c, 0xc7ffffff}, + { 0xfb9, 0xcccccccc}, + { 0xeb5, 0xcfcfcfcf}, + { 0xcad, 0xcfffcfff}, + { 0x89d, 0xcfffffff}, + { 0xfba, 0xdddddddd}, + { 0xeb6, 0xdfdfdfdf}, + { 0xcae, 0xdfffdfff}, + { 0x89e, 0xdfffffff}, + { 0x8c2, 0xe0000000}, + { 0x8c3, 0xe0000001}, + { 0x8c4, 0xe0000003}, + { 0x8c5, 0xe0000007}, + { 0x8c6, 0xe000000f}, + { 0x8c7, 0xe000001f}, + { 0x8c8, 0xe000003f}, + { 0x8c9, 0xe000007f}, + { 0x8ca, 0xe00000ff}, + { 0x8cb, 0xe00001ff}, + { 0x8cc, 0xe00003ff}, + { 0x8cd, 0xe00007ff}, + { 0x8ce, 0xe0000fff}, + { 0x8cf, 0xe0001fff}, + { 0x8d0, 0xe0003fff}, + { 0x8d1, 0xe0007fff}, + { 0xce2, 0xe000e000}, + { 0x8d2, 0xe000ffff}, + { 0xce3, 0xe001e001}, + { 0x8d3, 0xe001ffff}, + { 0xce4, 0xe003e003}, + { 0x8d4, 0xe003ffff}, + { 0xce5, 0xe007e007}, + { 0x8d5, 0xe007ffff}, + { 0xce6, 0xe00fe00f}, + { 0x8d6, 0xe00fffff}, + { 0xce7, 0xe01fe01f}, + { 0x8d7, 0xe01fffff}, + { 0xce8, 0xe03fe03f}, + { 0x8d8, 0xe03fffff}, + { 0xce9, 0xe07fe07f}, + { 0x8d9, 0xe07fffff}, + { 0xef2, 0xe0e0e0e0}, + { 0xcea, 0xe0ffe0ff}, + { 0x8da, 0xe0ffffff}, + { 0xef3, 0xe1e1e1e1}, + { 0xceb, 0xe1ffe1ff}, + { 0x8db, 0xe1ffffff}, + { 0xef4, 0xe3e3e3e3}, + { 0xcec, 0xe3ffe3ff}, + { 0x8dc, 0xe3ffffff}, + { 0xef5, 0xe7e7e7e7}, + { 0xced, 0xe7ffe7ff}, + { 0x8dd, 0xe7ffffff}, + { 0xffa, 0xeeeeeeee}, + { 0xef6, 0xefefefef}, + { 0xcee, 0xefffefff}, + { 0x8de, 0xefffffff}, + { 0x903, 0xf0000000}, + { 0x904, 0xf0000001}, + { 0x905, 0xf0000003}, + { 0x906, 0xf0000007}, + { 0x907, 0xf000000f}, + { 0x908, 0xf000001f}, + { 0x909, 0xf000003f}, + { 0x90a, 0xf000007f}, + { 0x90b, 0xf00000ff}, + { 0x90c, 0xf00001ff}, + { 0x90d, 0xf00003ff}, + { 0x90e, 0xf00007ff}, + { 0x90f, 0xf0000fff}, + { 0x910, 0xf0001fff}, + { 0x911, 0xf0003fff}, + { 0x912, 0xf0007fff}, + { 0xd23, 0xf000f000}, + { 0x913, 0xf000ffff}, + { 0xd24, 0xf001f001}, + { 0x914, 0xf001ffff}, + { 0xd25, 0xf003f003}, + { 0x915, 0xf003ffff}, + { 0xd26, 0xf007f007}, + { 0x916, 0xf007ffff}, + { 0xd27, 0xf00ff00f}, + { 0x917, 0xf00fffff}, + { 0xd28, 0xf01ff01f}, + { 0x918, 0xf01fffff}, + { 0xd29, 0xf03ff03f}, + { 0x919, 0xf03fffff}, + { 0xd2a, 0xf07ff07f}, + { 0x91a, 0xf07fffff}, + { 0xf33, 0xf0f0f0f0}, + { 0xd2b, 0xf0fff0ff}, + { 0x91b, 0xf0ffffff}, + { 0xf34, 0xf1f1f1f1}, + { 0xd2c, 0xf1fff1ff}, + { 0x91c, 0xf1ffffff}, + { 0xf35, 0xf3f3f3f3}, + { 0xd2d, 0xf3fff3ff}, + { 0x91d, 0xf3ffffff}, + { 0xf36, 0xf7f7f7f7}, + { 0xd2e, 0xf7fff7ff}, + { 0x91e, 0xf7ffffff}, + { 0x944, 0xf8000000}, + { 0x945, 0xf8000001}, + { 0x946, 0xf8000003}, + { 0x947, 0xf8000007}, + { 0x948, 0xf800000f}, + { 0x949, 0xf800001f}, + { 0x94a, 0xf800003f}, + { 0x94b, 0xf800007f}, + { 0x94c, 0xf80000ff}, + { 0x94d, 0xf80001ff}, + { 0x94e, 0xf80003ff}, + { 0x94f, 0xf80007ff}, + { 0x950, 0xf8000fff}, + { 0x951, 0xf8001fff}, + { 0x952, 0xf8003fff}, + { 0x953, 0xf8007fff}, + { 0xd64, 0xf800f800}, + { 0x954, 0xf800ffff}, + { 0xd65, 0xf801f801}, + { 0x955, 0xf801ffff}, + { 0xd66, 0xf803f803}, + { 0x956, 0xf803ffff}, + { 0xd67, 0xf807f807}, + { 0x957, 0xf807ffff}, + { 0xd68, 0xf80ff80f}, + { 0x958, 0xf80fffff}, + { 0xd69, 0xf81ff81f}, + { 0x959, 0xf81fffff}, + { 0xd6a, 0xf83ff83f}, + { 0x95a, 0xf83fffff}, + { 0xd6b, 0xf87ff87f}, + { 0x95b, 0xf87fffff}, + { 0xf74, 0xf8f8f8f8}, + { 0xd6c, 0xf8fff8ff}, + { 0x95c, 0xf8ffffff}, + { 0xf75, 0xf9f9f9f9}, + { 0xd6d, 0xf9fff9ff}, + { 0x95d, 0xf9ffffff}, + { 0xf76, 0xfbfbfbfb}, + { 0xd6e, 0xfbfffbff}, + { 0x95e, 0xfbffffff}, + { 0x985, 0xfc000000}, + { 0x986, 0xfc000001}, + { 0x987, 0xfc000003}, + { 0x988, 0xfc000007}, + { 0x989, 0xfc00000f}, + { 0x98a, 0xfc00001f}, + { 0x98b, 0xfc00003f}, + { 0x98c, 0xfc00007f}, + { 0x98d, 0xfc0000ff}, + { 0x98e, 0xfc0001ff}, + { 0x98f, 0xfc0003ff}, + { 0x990, 0xfc0007ff}, + { 0x991, 0xfc000fff}, + { 0x992, 0xfc001fff}, + { 0x993, 0xfc003fff}, + { 0x994, 0xfc007fff}, + { 0xda5, 0xfc00fc00}, + { 0x995, 0xfc00ffff}, + { 0xda6, 0xfc01fc01}, + { 0x996, 0xfc01ffff}, + { 0xda7, 0xfc03fc03}, + { 0x997, 0xfc03ffff}, + { 0xda8, 0xfc07fc07}, + { 0x998, 0xfc07ffff}, + { 0xda9, 0xfc0ffc0f}, + { 0x999, 0xfc0fffff}, + { 0xdaa, 0xfc1ffc1f}, + { 0x99a, 0xfc1fffff}, + { 0xdab, 0xfc3ffc3f}, + { 0x99b, 0xfc3fffff}, + { 0xdac, 0xfc7ffc7f}, + { 0x99c, 0xfc7fffff}, + { 0xfb5, 0xfcfcfcfc}, + { 0xdad, 0xfcfffcff}, + { 0x99d, 0xfcffffff}, + { 0xfb6, 0xfdfdfdfd}, + { 0xdae, 0xfdfffdff}, + { 0x99e, 0xfdffffff}, + { 0x9c6, 0xfe000000}, + { 0x9c7, 0xfe000001}, + { 0x9c8, 0xfe000003}, + { 0x9c9, 0xfe000007}, + { 0x9ca, 0xfe00000f}, + { 0x9cb, 0xfe00001f}, + { 0x9cc, 0xfe00003f}, + { 0x9cd, 0xfe00007f}, + { 0x9ce, 0xfe0000ff}, + { 0x9cf, 0xfe0001ff}, + { 0x9d0, 0xfe0003ff}, + { 0x9d1, 0xfe0007ff}, + { 0x9d2, 0xfe000fff}, + { 0x9d3, 0xfe001fff}, + { 0x9d4, 0xfe003fff}, + { 0x9d5, 0xfe007fff}, + { 0xde6, 0xfe00fe00}, + { 0x9d6, 0xfe00ffff}, + { 0xde7, 0xfe01fe01}, + { 0x9d7, 0xfe01ffff}, + { 0xde8, 0xfe03fe03}, + { 0x9d8, 0xfe03ffff}, + { 0xde9, 0xfe07fe07}, + { 0x9d9, 0xfe07ffff}, + { 0xdea, 0xfe0ffe0f}, + { 0x9da, 0xfe0fffff}, + { 0xdeb, 0xfe1ffe1f}, + { 0x9db, 0xfe1fffff}, + { 0xdec, 0xfe3ffe3f}, + { 0x9dc, 0xfe3fffff}, + { 0xded, 0xfe7ffe7f}, + { 0x9dd, 0xfe7fffff}, + { 0xff6, 0xfefefefe}, + { 0xdee, 0xfefffeff}, + { 0x9de, 0xfeffffff}, + { 0xa07, 0xff000000}, + { 0xa08, 0xff000001}, + { 0xa09, 0xff000003}, + { 0xa0a, 0xff000007}, + { 0xa0b, 0xff00000f}, + { 0xa0c, 0xff00001f}, + { 0xa0d, 0xff00003f}, + { 0xa0e, 0xff00007f}, + { 0xa0f, 0xff0000ff}, + { 0xa10, 0xff0001ff}, + { 0xa11, 0xff0003ff}, + { 0xa12, 0xff0007ff}, + { 0xa13, 0xff000fff}, + { 0xa14, 0xff001fff}, + { 0xa15, 0xff003fff}, + { 0xa16, 0xff007fff}, + { 0xe27, 0xff00ff00}, + { 0xa17, 0xff00ffff}, + { 0xe28, 0xff01ff01}, + { 0xa18, 0xff01ffff}, + { 0xe29, 0xff03ff03}, + { 0xa19, 0xff03ffff}, + { 0xe2a, 0xff07ff07}, + { 0xa1a, 0xff07ffff}, + { 0xe2b, 0xff0fff0f}, + { 0xa1b, 0xff0fffff}, + { 0xe2c, 0xff1fff1f}, + { 0xa1c, 0xff1fffff}, + { 0xe2d, 0xff3fff3f}, + { 0xa1d, 0xff3fffff}, + { 0xe2e, 0xff7fff7f}, + { 0xa1e, 0xff7fffff}, + { 0xa48, 0xff800000}, + { 0xa49, 0xff800001}, + { 0xa4a, 0xff800003}, + { 0xa4b, 0xff800007}, + { 0xa4c, 0xff80000f}, + { 0xa4d, 0xff80001f}, + { 0xa4e, 0xff80003f}, + { 0xa4f, 0xff80007f}, + { 0xa50, 0xff8000ff}, + { 0xa51, 0xff8001ff}, + { 0xa52, 0xff8003ff}, + { 0xa53, 0xff8007ff}, + { 0xa54, 0xff800fff}, + { 0xa55, 0xff801fff}, + { 0xa56, 0xff803fff}, + { 0xa57, 0xff807fff}, + { 0xe68, 0xff80ff80}, + { 0xa58, 0xff80ffff}, + { 0xe69, 0xff81ff81}, + { 0xa59, 0xff81ffff}, + { 0xe6a, 0xff83ff83}, + { 0xa5a, 0xff83ffff}, + { 0xe6b, 0xff87ff87}, + { 0xa5b, 0xff87ffff}, + { 0xe6c, 0xff8fff8f}, + { 0xa5c, 0xff8fffff}, + { 0xe6d, 0xff9fff9f}, + { 0xa5d, 0xff9fffff}, + { 0xe6e, 0xffbfffbf}, + { 0xa5e, 0xffbfffff}, + { 0xa89, 0xffc00000}, + { 0xa8a, 0xffc00001}, + { 0xa8b, 0xffc00003}, + { 0xa8c, 0xffc00007}, + { 0xa8d, 0xffc0000f}, + { 0xa8e, 0xffc0001f}, + { 0xa8f, 0xffc0003f}, + { 0xa90, 0xffc0007f}, + { 0xa91, 0xffc000ff}, + { 0xa92, 0xffc001ff}, + { 0xa93, 0xffc003ff}, + { 0xa94, 0xffc007ff}, + { 0xa95, 0xffc00fff}, + { 0xa96, 0xffc01fff}, + { 0xa97, 0xffc03fff}, + { 0xa98, 0xffc07fff}, + { 0xea9, 0xffc0ffc0}, + { 0xa99, 0xffc0ffff}, + { 0xeaa, 0xffc1ffc1}, + { 0xa9a, 0xffc1ffff}, + { 0xeab, 0xffc3ffc3}, + { 0xa9b, 0xffc3ffff}, + { 0xeac, 0xffc7ffc7}, + { 0xa9c, 0xffc7ffff}, + { 0xead, 0xffcfffcf}, + { 0xa9d, 0xffcfffff}, + { 0xeae, 0xffdfffdf}, + { 0xa9e, 0xffdfffff}, + { 0xaca, 0xffe00000}, + { 0xacb, 0xffe00001}, + { 0xacc, 0xffe00003}, + { 0xacd, 0xffe00007}, + { 0xace, 0xffe0000f}, + { 0xacf, 0xffe0001f}, + { 0xad0, 0xffe0003f}, + { 0xad1, 0xffe0007f}, + { 0xad2, 0xffe000ff}, + { 0xad3, 0xffe001ff}, + { 0xad4, 0xffe003ff}, + { 0xad5, 0xffe007ff}, + { 0xad6, 0xffe00fff}, + { 0xad7, 0xffe01fff}, + { 0xad8, 0xffe03fff}, + { 0xad9, 0xffe07fff}, + { 0xeea, 0xffe0ffe0}, + { 0xada, 0xffe0ffff}, + { 0xeeb, 0xffe1ffe1}, + { 0xadb, 0xffe1ffff}, + { 0xeec, 0xffe3ffe3}, + { 0xadc, 0xffe3ffff}, + { 0xeed, 0xffe7ffe7}, + { 0xadd, 0xffe7ffff}, + { 0xeee, 0xffefffef}, + { 0xade, 0xffefffff}, + { 0xb0b, 0xfff00000}, + { 0xb0c, 0xfff00001}, + { 0xb0d, 0xfff00003}, + { 0xb0e, 0xfff00007}, + { 0xb0f, 0xfff0000f}, + { 0xb10, 0xfff0001f}, + { 0xb11, 0xfff0003f}, + { 0xb12, 0xfff0007f}, + { 0xb13, 0xfff000ff}, + { 0xb14, 0xfff001ff}, + { 0xb15, 0xfff003ff}, + { 0xb16, 0xfff007ff}, + { 0xb17, 0xfff00fff}, + { 0xb18, 0xfff01fff}, + { 0xb19, 0xfff03fff}, + { 0xb1a, 0xfff07fff}, + { 0xf2b, 0xfff0fff0}, + { 0xb1b, 0xfff0ffff}, + { 0xf2c, 0xfff1fff1}, + { 0xb1c, 0xfff1ffff}, + { 0xf2d, 0xfff3fff3}, + { 0xb1d, 0xfff3ffff}, + { 0xf2e, 0xfff7fff7}, + { 0xb1e, 0xfff7ffff}, + { 0xb4c, 0xfff80000}, + { 0xb4d, 0xfff80001}, + { 0xb4e, 0xfff80003}, + { 0xb4f, 0xfff80007}, + { 0xb50, 0xfff8000f}, + { 0xb51, 0xfff8001f}, + { 0xb52, 0xfff8003f}, + { 0xb53, 0xfff8007f}, + { 0xb54, 0xfff800ff}, + { 0xb55, 0xfff801ff}, + { 0xb56, 0xfff803ff}, + { 0xb57, 0xfff807ff}, + { 0xb58, 0xfff80fff}, + { 0xb59, 0xfff81fff}, + { 0xb5a, 0xfff83fff}, + { 0xb5b, 0xfff87fff}, + { 0xf6c, 0xfff8fff8}, + { 0xb5c, 0xfff8ffff}, + { 0xf6d, 0xfff9fff9}, + { 0xb5d, 0xfff9ffff}, + { 0xf6e, 0xfffbfffb}, + { 0xb5e, 0xfffbffff}, + { 0xb8d, 0xfffc0000}, + { 0xb8e, 0xfffc0001}, + { 0xb8f, 0xfffc0003}, + { 0xb90, 0xfffc0007}, + { 0xb91, 0xfffc000f}, + { 0xb92, 0xfffc001f}, + { 0xb93, 0xfffc003f}, + { 0xb94, 0xfffc007f}, + { 0xb95, 0xfffc00ff}, + { 0xb96, 0xfffc01ff}, + { 0xb97, 0xfffc03ff}, + { 0xb98, 0xfffc07ff}, + { 0xb99, 0xfffc0fff}, + { 0xb9a, 0xfffc1fff}, + { 0xb9b, 0xfffc3fff}, + { 0xb9c, 0xfffc7fff}, + { 0xfad, 0xfffcfffc}, + { 0xb9d, 0xfffcffff}, + { 0xfae, 0xfffdfffd}, + { 0xb9e, 0xfffdffff}, + { 0xbce, 0xfffe0000}, + { 0xbcf, 0xfffe0001}, + { 0xbd0, 0xfffe0003}, + { 0xbd1, 0xfffe0007}, + { 0xbd2, 0xfffe000f}, + { 0xbd3, 0xfffe001f}, + { 0xbd4, 0xfffe003f}, + { 0xbd5, 0xfffe007f}, + { 0xbd6, 0xfffe00ff}, + { 0xbd7, 0xfffe01ff}, + { 0xbd8, 0xfffe03ff}, + { 0xbd9, 0xfffe07ff}, + { 0xbda, 0xfffe0fff}, + { 0xbdb, 0xfffe1fff}, + { 0xbdc, 0xfffe3fff}, + { 0xbdd, 0xfffe7fff}, + { 0xfee, 0xfffefffe}, + { 0xbde, 0xfffeffff}, + { 0xc0f, 0xffff0000}, + { 0xc10, 0xffff0001}, + { 0xc11, 0xffff0003}, + { 0xc12, 0xffff0007}, + { 0xc13, 0xffff000f}, + { 0xc14, 0xffff001f}, + { 0xc15, 0xffff003f}, + { 0xc16, 0xffff007f}, + { 0xc17, 0xffff00ff}, + { 0xc18, 0xffff01ff}, + { 0xc19, 0xffff03ff}, + { 0xc1a, 0xffff07ff}, + { 0xc1b, 0xffff0fff}, + { 0xc1c, 0xffff1fff}, + { 0xc1d, 0xffff3fff}, + { 0xc1e, 0xffff7fff}, + { 0xc50, 0xffff8000}, + { 0xc51, 0xffff8001}, + { 0xc52, 0xffff8003}, + { 0xc53, 0xffff8007}, + { 0xc54, 0xffff800f}, + { 0xc55, 0xffff801f}, + { 0xc56, 0xffff803f}, + { 0xc57, 0xffff807f}, + { 0xc58, 0xffff80ff}, + { 0xc59, 0xffff81ff}, + { 0xc5a, 0xffff83ff}, + { 0xc5b, 0xffff87ff}, + { 0xc5c, 0xffff8fff}, + { 0xc5d, 0xffff9fff}, + { 0xc5e, 0xffffbfff}, + { 0xc91, 0xffffc000}, + { 0xc92, 0xffffc001}, + { 0xc93, 0xffffc003}, + { 0xc94, 0xffffc007}, + { 0xc95, 0xffffc00f}, + { 0xc96, 0xffffc01f}, + { 0xc97, 0xffffc03f}, + { 0xc98, 0xffffc07f}, + { 0xc99, 0xffffc0ff}, + { 0xc9a, 0xffffc1ff}, + { 0xc9b, 0xffffc3ff}, + { 0xc9c, 0xffffc7ff}, + { 0xc9d, 0xffffcfff}, + { 0xc9e, 0xffffdfff}, + { 0xcd2, 0xffffe000}, + { 0xcd3, 0xffffe001}, + { 0xcd4, 0xffffe003}, + { 0xcd5, 0xffffe007}, + { 0xcd6, 0xffffe00f}, + { 0xcd7, 0xffffe01f}, + { 0xcd8, 0xffffe03f}, + { 0xcd9, 0xffffe07f}, + { 0xcda, 0xffffe0ff}, + { 0xcdb, 0xffffe1ff}, + { 0xcdc, 0xffffe3ff}, + { 0xcdd, 0xffffe7ff}, + { 0xcde, 0xffffefff}, + { 0xd13, 0xfffff000}, + { 0xd14, 0xfffff001}, + { 0xd15, 0xfffff003}, + { 0xd16, 0xfffff007}, + { 0xd17, 0xfffff00f}, + { 0xd18, 0xfffff01f}, + { 0xd19, 0xfffff03f}, + { 0xd1a, 0xfffff07f}, + { 0xd1b, 0xfffff0ff}, + { 0xd1c, 0xfffff1ff}, + { 0xd1d, 0xfffff3ff}, + { 0xd1e, 0xfffff7ff}, + { 0xd54, 0xfffff800}, + { 0xd55, 0xfffff801}, + { 0xd56, 0xfffff803}, + { 0xd57, 0xfffff807}, + { 0xd58, 0xfffff80f}, + { 0xd59, 0xfffff81f}, + { 0xd5a, 0xfffff83f}, + { 0xd5b, 0xfffff87f}, + { 0xd5c, 0xfffff8ff}, + { 0xd5d, 0xfffff9ff}, + { 0xd5e, 0xfffffbff}, + { 0xd95, 0xfffffc00}, + { 0xd96, 0xfffffc01}, + { 0xd97, 0xfffffc03}, + { 0xd98, 0xfffffc07}, + { 0xd99, 0xfffffc0f}, + { 0xd9a, 0xfffffc1f}, + { 0xd9b, 0xfffffc3f}, + { 0xd9c, 0xfffffc7f}, + { 0xd9d, 0xfffffcff}, + { 0xd9e, 0xfffffdff}, + { 0xdd6, 0xfffffe00}, + { 0xdd7, 0xfffffe01}, + { 0xdd8, 0xfffffe03}, + { 0xdd9, 0xfffffe07}, + { 0xdda, 0xfffffe0f}, + { 0xddb, 0xfffffe1f}, + { 0xddc, 0xfffffe3f}, + { 0xddd, 0xfffffe7f}, + { 0xdde, 0xfffffeff}, + { 0xe17, 0xffffff00}, + { 0xe18, 0xffffff01}, + { 0xe19, 0xffffff03}, + { 0xe1a, 0xffffff07}, + { 0xe1b, 0xffffff0f}, + { 0xe1c, 0xffffff1f}, + { 0xe1d, 0xffffff3f}, + { 0xe1e, 0xffffff7f}, + { 0xe58, 0xffffff80}, + { 0xe59, 0xffffff81}, + { 0xe5a, 0xffffff83}, + { 0xe5b, 0xffffff87}, + { 0xe5c, 0xffffff8f}, + { 0xe5d, 0xffffff9f}, + { 0xe5e, 0xffffffbf}, + { 0xe99, 0xffffffc0}, + { 0xe9a, 0xffffffc1}, + { 0xe9b, 0xffffffc3}, + { 0xe9c, 0xffffffc7}, + { 0xe9d, 0xffffffcf}, + { 0xe9e, 0xffffffdf}, + { 0xeda, 0xffffffe0}, + { 0xedb, 0xffffffe1}, + { 0xedc, 0xffffffe3}, + { 0xedd, 0xffffffe7}, + { 0xede, 0xffffffef}, + { 0xf1b, 0xfffffff0}, + { 0xf1c, 0xfffffff1}, + { 0xf1d, 0xfffffff3}, + { 0xf1e, 0xfffffff7}, + { 0xf5c, 0xfffffff8}, + { 0xf5d, 0xfffffff9}, + { 0xf5e, 0xfffffffb}, + { 0xf9d, 0xfffffffc}, + { 0xf9e, 0xfffffffd}, + { 0xfde, 0xfffffffe}, }; -uint32_t host_arm64_find_imm(uint32_t data) +uint32_t +host_arm64_find_imm(uint32_t data) { - int l = 0, r = IMM_NR - 1; + int l = 0, r = IMM_NR - 1; - while (l <= r) - { - int m = (l + r) >> 1; + while (l <= r) { + int m = (l + r) >> 1; - if (imm_table[m][1] < data) - l = m+1; - else if (imm_table[m][1] > data) - r = m-1; - else - return imm_table[m][0]; - } - return 0; + if (imm_table[m][1] < data) + l = m + 1; + else if (imm_table[m][1] > data) + r = m - 1; + else + return imm_table[m][0]; + } + return 0; } diff --git a/src/codegen_new/codegen_backend_arm64_ops.c b/src/codegen_new/codegen_backend_arm64_ops.c index 0cc20d788..aa5e5870a 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.c +++ b/src/codegen_new/codegen_backend_arm64_ops.c @@ -1,1380 +1,1516 @@ #if defined __aarch64__ || defined _M_ARM64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm64_defs.h" -#include "codegen_backend_arm64_ops.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm64_defs.h" +# include "codegen_backend_arm64_ops.h" +# define Rt(x) (x) +# define Rd(x) (x) +# define Rn(x) ((x) << 5) +# define Rt2(x) ((x) << 10) +# define Rm(x) ((x) << 16) -#define Rt(x) (x) -#define Rd(x) (x) -#define Rn(x) ((x) << 5) -#define Rt2(x) ((x) << 10) -#define Rm(x) ((x) << 16) +# define shift_imm6(x) ((x) << 10) -#define shift_imm6(x) ((x) << 10) +# define DATA_OFFSET_UP (1 << 23) +# define DATA_OFFSET_DOWN (0 << 23) -#define DATA_OFFSET_UP (1 << 23) -#define DATA_OFFSET_DOWN (0 << 23) +# define COND_EQ (0x0) +# define COND_NE (0x1) +# define COND_CS (0x2) +# define COND_CC (0x3) +# define COND_MI (0x4) +# define COND_PL (0x5) +# define COND_VS (0x6) +# define COND_VC (0x7) +# define COND_HI (0x8) +# define COND_LS (0x9) +# define COND_GE (0xa) +# define COND_LT (0xb) +# define COND_GT (0xc) +# define COND_LE (0xd) -#define COND_EQ (0x0) -#define COND_NE (0x1) -#define COND_CS (0x2) -#define COND_CC (0x3) -#define COND_MI (0x4) -#define COND_PL (0x5) -#define COND_VS (0x6) -#define COND_VC (0x7) -#define COND_HI (0x8) -#define COND_LS (0x9) -#define COND_GE (0xa) -#define COND_LT (0xb) -#define COND_GT (0xc) -#define COND_LE (0xd) +# define CSEL_COND(cond) ((cond) << 12) -#define CSEL_COND(cond) ((cond) << 12) +# define OPCODE_SHIFT 24 +# define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) +# define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) +# define OPCODE_ADR (0x10 << OPCODE_SHIFT) +# define OPCODE_B (0x14 << OPCODE_SHIFT) +# define OPCODE_BCOND (0x54 << OPCODE_SHIFT) +# define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) +# define OPCODE_CBZ (0xb4 << OPCODE_SHIFT) +# define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) +# define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) +# define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) +# define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) +# define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) +# define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) +# define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) +# define OPCODE_TBZ (0x36 << OPCODE_SHIFT) -#define OPCODE_SHIFT 24 -#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT) -#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT) -#define OPCODE_ADR (0x10 << OPCODE_SHIFT) -#define OPCODE_B (0x14 << OPCODE_SHIFT) -#define OPCODE_BCOND (0x54 << OPCODE_SHIFT) -#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT) -#define OPCODE_CBZ (0xb4 << OPCODE_SHIFT) -#define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT) -#define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT) -#define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT) -#define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT) -#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT) -#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT) -#define OPCODE_TBNZ (0x37 << OPCODE_SHIFT) -#define OPCODE_TBZ (0x36 << OPCODE_SHIFT) +# define OPCODE_AND_IMM (0x024 << 23) +# define OPCODE_ANDS_IMM (0x0e4 << 23) +# define OPCODE_EOR_IMM (0x0a4 << 23) +# define OPCODE_MOVK_W (0x0e5 << 23) +# define OPCODE_MOVK_X (0x1e5 << 23) +# define OPCODE_MOVZ_W (0x0a5 << 23) +# define OPCODE_MOVZ_X (0x1a5 << 23) +# define OPCODE_ORR_IMM (0x064 << 23) -#define OPCODE_AND_IMM (0x024 << 23) -#define OPCODE_ANDS_IMM (0x0e4 << 23) -#define OPCODE_EOR_IMM (0x0a4 << 23) -#define OPCODE_MOVK_W (0x0e5 << 23) -#define OPCODE_MOVK_X (0x1e5 << 23) -#define OPCODE_MOVZ_W (0x0a5 << 23) -#define OPCODE_MOVZ_X (0x1a5 << 23) -#define OPCODE_ORR_IMM (0x064 << 23) +# define OPCODE_BFI (0x0cc << 22) +# define OPCODE_LDR_IMM_W (0x2e5 << 22) +# define OPCODE_LDR_IMM_X (0x3e5 << 22) +# define OPCODE_LDR_IMM_F64 (0x3f5 << 22) +# define OPCODE_LDRB_IMM_W (0x0e5 << 22) +# define OPCODE_LDRH_IMM (0x1e5 << 22) +# define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) +# define OPCODE_SBFX (0x04c << 22) +# define OPCODE_STP_PREIDX_X (0x2a6 << 22) +# define OPCODE_STR_IMM_W (0x2e4 << 22) +# define OPCODE_STR_IMM_Q (0x3e4 << 22) +# define OPCODE_STR_IMM_F64 (0x3f4 << 22) +# define OPCODE_STRB_IMM (0x0e4 << 22) +# define OPCODE_STRH_IMM (0x1e4 << 22) +# define OPCODE_UBFX (0x14c << 22) -#define OPCODE_BFI (0x0cc << 22) -#define OPCODE_LDR_IMM_W (0x2e5 << 22) -#define OPCODE_LDR_IMM_X (0x3e5 << 22) -#define OPCODE_LDR_IMM_F64 (0x3f5 << 22) -#define OPCODE_LDRB_IMM_W (0x0e5 << 22) -#define OPCODE_LDRH_IMM (0x1e5 << 22) -#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22) -#define OPCODE_SBFX (0x04c << 22) -#define OPCODE_STP_PREIDX_X (0x2a6 << 22) -#define OPCODE_STR_IMM_W (0x2e4 << 22) -#define OPCODE_STR_IMM_Q (0x3e4 << 22) -#define OPCODE_STR_IMM_F64 (0x3f4 << 22) -#define OPCODE_STRB_IMM (0x0e4 << 22) -#define OPCODE_STRH_IMM (0x1e4 << 22) -#define OPCODE_UBFX (0x14c << 22) +# define OPCODE_ADD_LSL (0x058 << 21) +# define OPCODE_ADD_LSR (0x05a << 21) +# define OPCODE_ADDX_LSL (0x458 << 21) +# define OPCODE_AND_ASR (0x054 << 21) +# define OPCODE_AND_LSL (0x050 << 21) +# define OPCODE_AND_ROR (0x056 << 21) +# define OPCODE_ANDS_LSL (0x350 << 21) +# define OPCODE_CMP_LSL (0x358 << 21) +# define OPCODE_CSEL (0x0d4 << 21) +# define OPCODE_EOR_LSL (0x250 << 21) +# define OPCODE_ORR_ASR (0x154 << 21) +# define OPCODE_ORR_LSL (0x150 << 21) +# define OPCODE_ORR_LSR (0x152 << 21) +# define OPCODE_ORR_ROR (0x156 << 21) +# define OPCODE_ORRX_LSL (0x550 << 21) +# define OPCODE_SUB_LSL (0x258 << 21) +# define OPCODE_SUB_LSR (0x25a << 21) +# define OPCODE_SUBX_LSL (0x658 << 21) -#define OPCODE_ADD_LSL (0x058 << 21) -#define OPCODE_ADD_LSR (0x05a << 21) -#define OPCODE_ADDX_LSL (0x458 << 21) -#define OPCODE_AND_ASR (0x054 << 21) -#define OPCODE_AND_LSL (0x050 << 21) -#define OPCODE_AND_ROR (0x056 << 21) -#define OPCODE_ANDS_LSL (0x350 << 21) -#define OPCODE_CMP_LSL (0x358 << 21) -#define OPCODE_CSEL (0x0d4 << 21) -#define OPCODE_EOR_LSL (0x250 << 21) -#define OPCODE_ORR_ASR (0x154 << 21) -#define OPCODE_ORR_LSL (0x150 << 21) -#define OPCODE_ORR_LSR (0x152 << 21) -#define OPCODE_ORR_ROR (0x156 << 21) -#define OPCODE_ORRX_LSL (0x550 << 21) -#define OPCODE_SUB_LSL (0x258 << 21) -#define OPCODE_SUB_LSR (0x25a << 21) -#define OPCODE_SUBX_LSL (0x658 << 21) +# define OPCODE_ADD_V8B (0x0e208400) +# define OPCODE_ADD_V4H (0x0e608400) +# define OPCODE_ADD_V2S (0x0ea08400) +# define OPCODE_ADDP_V4S (0x4ea0bc00) +# define OPCODE_AND_V (0x0e201c00) +# define OPCODE_ASR (0x1ac02800) +# define OPCODE_BIC_V (0x0e601c00) +# define OPCODE_BLR (0xd63f0000) +# define OPCODE_BR (0xd61f0000) +# define OPCODE_CMEQ_V8B (0x2e208c00) +# define OPCODE_CMEQ_V4H (0x2e608c00) +# define OPCODE_CMEQ_V2S (0x2ea08c00) +# define OPCODE_CMGT_V8B (0x0e203400) +# define OPCODE_CMGT_V4H (0x0e603400) +# define OPCODE_CMGT_V2S (0x0ea03400) +# define OPCODE_DUP_V2S (0x0e040400) +# define OPCODE_EOR_V (0x2e201c00) +# define OPCODE_FABS_D (0x1e60c000) +# define OPCODE_FADD_D (0x1e602800) +# define OPCODE_FADD_V2S (0x0e20d400) +# define OPCODE_FCMEQ_V2S (0x0e20e400) +# define OPCODE_FCMGE_V2S (0x2e20e400) +# define OPCODE_FCMGT_V2S (0x2ea0e400) +# define OPCODE_FCMP_D (0x1e602000) +# define OPCODE_FCVT_D_S (0x1e22c000) +# define OPCODE_FCVT_S_D (0x1e624000) +# define OPCODE_FCVTMS_W_D (0x1e700000) +# define OPCODE_FCVTMS_X_D (0x9e700000) +# define OPCODE_FCVTNS_W_D (0x1e600000) +# define OPCODE_FCVTNS_X_D (0x9e600000) +# define OPCODE_FCVTPS_W_D (0x1e680000) +# define OPCODE_FCVTPS_X_D (0x9e680000) +# define OPCODE_FCVTZS_W_D (0x1e780000) +# define OPCODE_FCVTZS_X_D (0x9e780000) +# define OPCODE_FCVTZS_V2S (0x0ea1b800) +# define OPCODE_FDIV_D (0x1e601800) +# define OPCODE_FDIV_S (0x1e201800) +# define OPCODE_FMAX_V2S (0x0e20f400) +# define OPCODE_FMIN_V2S (0x0ea0f400) +# define OPCODE_FMOV_D_D (0x1e604000) +# define OPCODE_FMOV_D_Q (0x9e670000) +# define OPCODE_FMOV_Q_D (0x9e660000) +# define OPCODE_FMOV_S_W (0x1e270000) +# define OPCODE_FMOV_W_S (0x1e260000) +# define OPCODE_FMOV_S_ONE (0x1e2e1000) +# define OPCODE_FMUL_D (0x1e600800) +# define OPCODE_FMUL_V2S (0x2e20dc00) +# define OPCODE_FNEG_D (0x1e614000) +# define OPCODE_FRINTX_D (0x1e674000) +# define OPCODE_FSQRT_D (0x1e61c000) +# define OPCODE_FSQRT_S (0x1e21c000) +# define OPCODE_FSUB_D (0x1e603800) +# define OPCODE_FSUB_V2S (0x0ea0d400) +# define OPCODE_LDR_REG (0xb8606800) +# define OPCODE_LDRX_REG (0xf8606800) +# define OPCODE_LDRB_REG (0x38606800) +# define OPCODE_LDRH_REG (0x78606800) +# define OPCODE_LDRX_REG_LSL3 (0xf8607800) +# define OPCODE_LDR_REG_F32 (0xbc606800) +# define OPCODE_LDR_REG_F64 (0xfc606800) +# define OPCODE_LDR_REG_F64_S (0xfc607800) +# define OPCODE_LSL (0x1ac02000) +# define OPCODE_LSR (0x1ac02400) +# define OPCODE_MSR_FPCR (0xd51b4400) +# define OPCODE_MUL_V4H (0x0e609c00) +# define OPCODE_NOP (0xd503201f) +# define OPCODE_ORR_V (0x0ea01c00) +# define OPCODE_RET (0xd65f0000) +# define OPCODE_ROR (0x1ac02c00) +# define OPCODE_SADDLP_V2S_4H (0x0e602800) +# define OPCODE_SCVTF_D_Q (0x9e620000) +# define OPCODE_SCVTF_D_W (0x1e620000) +# define OPCODE_SCVTF_V2S (0x0e21d800) +# define OPCODE_SQADD_V8B (0x0e200c00) +# define OPCODE_SQADD_V4H (0x0e600c00) +# define OPCODE_SQSUB_V8B (0x0e202c00) +# define OPCODE_SQSUB_V4H (0x0e602c00) +# define OPCODE_SQXTN_V8B_8H (0x0e214800) +# define OPCODE_SQXTN_V4H_4S (0x0e614800) +# define OPCODE_SHL_VD (0x0f005400) +# define OPCODE_SHL_VQ (0x4f005400) +# define OPCODE_SHRN (0x0f008400) +# define OPCODE_SMULL_V4S_4H (0x0e60c000) +# define OPCODE_SSHR_VD (0x0f000400) +# define OPCODE_SSHR_VQ (0x4f000400) +# define OPCODE_STR_REG (0xb8206800) +# define OPCODE_STRB_REG (0x38206800) +# define OPCODE_STRH_REG (0x78206800) +# define OPCODE_STR_REG_F32 (0xbc206800) +# define OPCODE_STR_REG_F64 (0xfc206800) +# define OPCODE_STR_REG_F64_S (0xfc207800) +# define OPCODE_SUB_V8B (0x2e208400) +# define OPCODE_SUB_V4H (0x2e608400) +# define OPCODE_SUB_V2S (0x2ea08400) +# define OPCODE_UQADD_V8B (0x2e200c00) +# define OPCODE_UQADD_V4H (0x2e600c00) +# define OPCODE_UQSUB_V8B (0x2e202c00) +# define OPCODE_UQSUB_V4H (0x2e602c00) +# define OPCODE_UQXTN_V8B_8H (0x2e214800) +# define OPCODE_UQXTN_V4H_4S (0x2e614800) +# define OPCODE_USHR_VD (0x2f000400) +# define OPCODE_USHR_VQ (0x6f000400) +# define OPCODE_ZIP1_V8B (0x0e003800) +# define OPCODE_ZIP1_V4H (0x0e403800) +# define OPCODE_ZIP1_V2S (0x0e803800) +# define OPCODE_ZIP2_V8B (0x0e007800) +# define OPCODE_ZIP2_V4H (0x0e407800) +# define OPCODE_ZIP2_V2S (0x0e807800) -#define OPCODE_ADD_V8B (0x0e208400) -#define OPCODE_ADD_V4H (0x0e608400) -#define OPCODE_ADD_V2S (0x0ea08400) -#define OPCODE_ADDP_V4S (0x4ea0bc00) -#define OPCODE_AND_V (0x0e201c00) -#define OPCODE_ASR (0x1ac02800) -#define OPCODE_BIC_V (0x0e601c00) -#define OPCODE_BLR (0xd63f0000) -#define OPCODE_BR (0xd61f0000) -#define OPCODE_CMEQ_V8B (0x2e208c00) -#define OPCODE_CMEQ_V4H (0x2e608c00) -#define OPCODE_CMEQ_V2S (0x2ea08c00) -#define OPCODE_CMGT_V8B (0x0e203400) -#define OPCODE_CMGT_V4H (0x0e603400) -#define OPCODE_CMGT_V2S (0x0ea03400) -#define OPCODE_DUP_V2S (0x0e040400) -#define OPCODE_EOR_V (0x2e201c00) -#define OPCODE_FABS_D (0x1e60c000) -#define OPCODE_FADD_D (0x1e602800) -#define OPCODE_FADD_V2S (0x0e20d400) -#define OPCODE_FCMEQ_V2S (0x0e20e400) -#define OPCODE_FCMGE_V2S (0x2e20e400) -#define OPCODE_FCMGT_V2S (0x2ea0e400) -#define OPCODE_FCMP_D (0x1e602000) -#define OPCODE_FCVT_D_S (0x1e22c000) -#define OPCODE_FCVT_S_D (0x1e624000) -#define OPCODE_FCVTMS_W_D (0x1e700000) -#define OPCODE_FCVTMS_X_D (0x9e700000) -#define OPCODE_FCVTNS_W_D (0x1e600000) -#define OPCODE_FCVTNS_X_D (0x9e600000) -#define OPCODE_FCVTPS_W_D (0x1e680000) -#define OPCODE_FCVTPS_X_D (0x9e680000) -#define OPCODE_FCVTZS_W_D (0x1e780000) -#define OPCODE_FCVTZS_X_D (0x9e780000) -#define OPCODE_FCVTZS_V2S (0x0ea1b800) -#define OPCODE_FDIV_D (0x1e601800) -#define OPCODE_FDIV_S (0x1e201800) -#define OPCODE_FMAX_V2S (0x0e20f400) -#define OPCODE_FMIN_V2S (0x0ea0f400) -#define OPCODE_FMOV_D_D (0x1e604000) -#define OPCODE_FMOV_D_Q (0x9e670000) -#define OPCODE_FMOV_Q_D (0x9e660000) -#define OPCODE_FMOV_S_W (0x1e270000) -#define OPCODE_FMOV_W_S (0x1e260000) -#define OPCODE_FMOV_S_ONE (0x1e2e1000) -#define OPCODE_FMUL_D (0x1e600800) -#define OPCODE_FMUL_V2S (0x2e20dc00) -#define OPCODE_FNEG_D (0x1e614000) -#define OPCODE_FRINTX_D (0x1e674000) -#define OPCODE_FSQRT_D (0x1e61c000) -#define OPCODE_FSQRT_S (0x1e21c000) -#define OPCODE_FSUB_D (0x1e603800) -#define OPCODE_FSUB_V2S (0x0ea0d400) -#define OPCODE_LDR_REG (0xb8606800) -#define OPCODE_LDRX_REG (0xf8606800) -#define OPCODE_LDRB_REG (0x38606800) -#define OPCODE_LDRH_REG (0x78606800) -#define OPCODE_LDRX_REG_LSL3 (0xf8607800) -#define OPCODE_LDR_REG_F32 (0xbc606800) -#define OPCODE_LDR_REG_F64 (0xfc606800) -#define OPCODE_LDR_REG_F64_S (0xfc607800) -#define OPCODE_LSL (0x1ac02000) -#define OPCODE_LSR (0x1ac02400) -#define OPCODE_MSR_FPCR (0xd51b4400) -#define OPCODE_MUL_V4H (0x0e609c00) -#define OPCODE_NOP (0xd503201f) -#define OPCODE_ORR_V (0x0ea01c00) -#define OPCODE_RET (0xd65f0000) -#define OPCODE_ROR (0x1ac02c00) -#define OPCODE_SADDLP_V2S_4H (0x0e602800) -#define OPCODE_SCVTF_D_Q (0x9e620000) -#define OPCODE_SCVTF_D_W (0x1e620000) -#define OPCODE_SCVTF_V2S (0x0e21d800) -#define OPCODE_SQADD_V8B (0x0e200c00) -#define OPCODE_SQADD_V4H (0x0e600c00) -#define OPCODE_SQSUB_V8B (0x0e202c00) -#define OPCODE_SQSUB_V4H (0x0e602c00) -#define OPCODE_SQXTN_V8B_8H (0x0e214800) -#define OPCODE_SQXTN_V4H_4S (0x0e614800) -#define OPCODE_SHL_VD (0x0f005400) -#define OPCODE_SHL_VQ (0x4f005400) -#define OPCODE_SHRN (0x0f008400) -#define OPCODE_SMULL_V4S_4H (0x0e60c000) -#define OPCODE_SSHR_VD (0x0f000400) -#define OPCODE_SSHR_VQ (0x4f000400) -#define OPCODE_STR_REG (0xb8206800) -#define OPCODE_STRB_REG (0x38206800) -#define OPCODE_STRH_REG (0x78206800) -#define OPCODE_STR_REG_F32 (0xbc206800) -#define OPCODE_STR_REG_F64 (0xfc206800) -#define OPCODE_STR_REG_F64_S (0xfc207800) -#define OPCODE_SUB_V8B (0x2e208400) -#define OPCODE_SUB_V4H (0x2e608400) -#define OPCODE_SUB_V2S (0x2ea08400) -#define OPCODE_UQADD_V8B (0x2e200c00) -#define OPCODE_UQADD_V4H (0x2e600c00) -#define OPCODE_UQSUB_V8B (0x2e202c00) -#define OPCODE_UQSUB_V4H (0x2e602c00) -#define OPCODE_UQXTN_V8B_8H (0x2e214800) -#define OPCODE_UQXTN_V4H_4S (0x2e614800) -#define OPCODE_USHR_VD (0x2f000400) -#define OPCODE_USHR_VQ (0x6f000400) -#define OPCODE_ZIP1_V8B (0x0e003800) -#define OPCODE_ZIP1_V4H (0x0e403800) -#define OPCODE_ZIP1_V2S (0x0e803800) -#define OPCODE_ZIP2_V8B (0x0e007800) -#define OPCODE_ZIP2_V4H (0x0e407800) -#define OPCODE_ZIP2_V2S (0x0e807800) +# define DATPROC_SHIFT(sh) (sh << 10) +# define DATPROC_IMM_SHIFT(sh) (sh << 22) +# define MOV_WIDE_HW(hw) (hw << 21) -#define DATPROC_SHIFT(sh) (sh << 10) -#define DATPROC_IMM_SHIFT(sh) (sh << 22) -#define MOV_WIDE_HW(hw) (hw << 21) +# define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) +# define IMM12(imm_data) ((imm_data) << 10) +# define IMM16(imm_data) ((imm_data) << 5) -#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15) -#define IMM12(imm_data) ((imm_data) << 10) -#define IMM16(imm_data) ((imm_data) << 5) +# define IMMN(immn) ((immn) << 22) +# define IMMR(immr) ((immr) << 16) +# define IMMS(imms) ((imms) << 10) -#define IMMN(immn) ((immn) << 22) -#define IMMR(immr) ((immr) << 16) -#define IMMS(imms) ((imms) << 10) +# define IMM_LOGICAL(imm) ((imm) << 10) -#define IMM_LOGICAL(imm) ((imm) << 10) +# define BIT_TBxZ(bit) ((((bit) &0x1f) << 19) | (((bit) &0x20) ? (1 << 31) : 0)) -#define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) +# define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) +# define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) +# define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) &0x1fffff) >> 2) << 5)) +# define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) -#define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) -#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) -#define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5)) -#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) +# define OFFSET12_B(offset) (offset << 10) +# define OFFSET12_H(offset) ((offset >> 1) << 10) +# define OFFSET12_W(offset) ((offset >> 2) << 10) +# define OFFSET12_Q(offset) ((offset >> 3) << 10) -#define OFFSET12_B(offset) (offset << 10) -#define OFFSET12_H(offset) ((offset >> 1) << 10) -#define OFFSET12_W(offset) ((offset >> 2) << 10) -#define OFFSET12_Q(offset) ((offset >> 3) << 10) +# define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) +# define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) +# define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) -#define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) -#define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) -#define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) +# define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16) -#define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16) - -#define DUP_ELEMENT(element) ((element) << 19) +# define DUP_ELEMENT(element) ((element) << 19) /*Returns true if offset fits into 19 bits*/ -static int offset_is_19bit(int offset) +static int +offset_is_19bit(int offset) { - if (offset >= (1 << (18+2))) - return 0; - if (offset < -(1 << (18+2))) - return 0; - return 1; + if (offset >= (1 << (18 + 2))) + return 0; + if (offset < -(1 << (18 + 2))) + return 0; + return 1; } /*Returns true if offset fits into 26 bits*/ -static int offset_is_26bit(int offset) +static int +offset_is_26bit(int offset) { - if (offset >= (1 << (25+2))) - return 0; - if (offset < -(1 << (25+2))) - return 0; - return 1; + if (offset >= (1 << (25 + 2))) + return 0; + if (offset < -(1 << (25 + 2))) + return 0; + return 1; } -static inline int imm_is_imm16(uint32_t imm_data) +static inline int +imm_is_imm16(uint32_t imm_data) { - if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) - return 1; - return 0; + if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff)) + return 1; + return 0; } static void codegen_allocate_new_block(codeblock_t *block); -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(codeblock_t *block, uint32_t val) { - if (block_pos >= (BLOCK_MAX-4)) - codegen_allocate_new_block(block); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos >= (BLOCK_MAX - 4)) + codegen_allocate_new_block(block); + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static void codegen_allocate_new_block(codeblock_t *block) +static void +codegen_allocate_new_block(codeblock_t *block) { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - uint32_t offset = (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]; + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos]; - if (!offset_is_26bit(offset)) - fatal("codegen_allocate_new_block - offset out of range %x\n", offset); - /*Add a jump instruction to the new block*/ - *(uint32_t *)&block_write_data[block_pos] = OPCODE_B | OFFSET26(offset); + if (!offset_is_26bit(offset)) + fatal("codegen_allocate_new_block - offset out of range %x\n", offset); + /*Add a jump instruction to the new block*/ + *(uint32_t *) &block_write_data[block_pos] = OPCODE_B | OFFSET26(offset); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; } -void codegen_alloc(codeblock_t *block, int size) +void +codegen_alloc(codeblock_t *block, int size) { - if (block_pos >= (BLOCK_MAX-size)) - codegen_allocate_new_block(block); + if (block_pos >= (BLOCK_MAX - size)) + codegen_allocate_new_block(block); } -void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (!imm_data) - host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); - else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) - { - host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xff000000)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - { - host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); - codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t) imm_data < 0 && imm_data != 0x80000000) { + host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xff000000)) { + if (imm_data & 0xfff) { + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data) +void +host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data) { - if (!(imm_data & ~0xffffffull)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - fatal("ADD_IMM_X %016llx\n", imm_data); + if (!(imm_data & ~0xffffffull)) { + if (imm_data & 0xfff) { + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_ADDX_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else + fatal("ADD_IMM_X %016llx\n", imm_data); } -void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADDP_V4S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ADDP_V4S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) +void +host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) { - codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset)); + codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset)); } -void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_AND_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_AND_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_ANDS_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ANDS_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_B(codeblock_t *block, void *dest) +void +host_arm64_B(codeblock_t *block, void *dest) { - int offset; + int offset; - codegen_alloc(block, 4); - offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; + codegen_alloc(block, 4); + offset = (uintptr_t) dest - (uintptr_t) &block_write_data[block_pos]; - if (!offset_is_26bit(offset)) - fatal("host_arm64_B - offset out of range %x\n", offset); - codegen_addlong(block, OPCODE_B | OFFSET26(offset)); + if (!offset_is_26bit(offset)) + fatal("host_arm64_B - offset out of range %x\n", offset); + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); } -void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31)); + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width - 1) & 31)); } -void host_arm64_BLR(codeblock_t *block, int addr_reg) +void +host_arm64_BLR(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); + codegen_addlong(block, OPCODE_BLR | Rn(addr_reg)); } -uint32_t *host_arm64_BCC_(codeblock_t *block) +uint32_t * +host_arm64_BCC_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BCS_(codeblock_t *block) +uint32_t * +host_arm64_BCS_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BEQ_(codeblock_t *block) +uint32_t * +host_arm64_BEQ_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BGE_(codeblock_t *block) +uint32_t * +host_arm64_BGE_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BGT_(codeblock_t *block) +uint32_t * +host_arm64_BGT_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BHI_(codeblock_t *block) +uint32_t * +host_arm64_BHI_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BLE_(codeblock_t *block) +uint32_t * +host_arm64_BLE_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BLS_(codeblock_t *block) +uint32_t * +host_arm64_BLS_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BLT_(codeblock_t *block) +uint32_t * +host_arm64_BLT_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BMI_(codeblock_t *block) +uint32_t * +host_arm64_BMI_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BNE_(codeblock_t *block) +uint32_t * +host_arm64_BNE_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BPL_(codeblock_t *block) +uint32_t * +host_arm64_BPL_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BVC_(codeblock_t *block) +uint32_t * +host_arm64_BVC_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm64_BVS_(codeblock_t *block) +uint32_t * +host_arm64_BVS_(codeblock_t *block) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -void host_arm64_branch_set_offset(uint32_t *opcode, void *dest) +void +host_arm64_branch_set_offset(uint32_t *opcode, void *dest) { - int offset = (uintptr_t)dest - (uintptr_t)opcode; - *opcode |= OFFSET26(offset); + int offset = (uintptr_t) dest - (uintptr_t) opcode; + *opcode |= OFFSET26(offset); } -void host_arm64_BR(codeblock_t *block, int addr_reg) +void +host_arm64_BR(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BR | Rn(addr_reg)); + codegen_addlong(block, OPCODE_BR | Rn(addr_reg)); } -void host_arm64_BEQ(codeblock_t *block, void *dest) +void +host_arm64_BEQ(codeblock_t *block, void *dest) { - uint32_t *opcode = host_arm64_BEQ_(block); - host_arm64_branch_set_offset(opcode, dest); + uint32_t *opcode = host_arm64_BEQ_(block); + host_arm64_branch_set_offset(opcode, dest); } -void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_BIC_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_BIC_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) +void +host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) { - int offset; + int offset; - codegen_alloc(block, 4); - offset = dest - (uintptr_t)&block_write_data[block_pos]; - if (offset_is_19bit(offset)) - { - codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); - } - else - { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg)); - offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos]; - codegen_addlong(block, OPCODE_B | OFFSET26(offset)); - } + codegen_alloc(block, 4); + offset = dest - (uintptr_t) &block_write_data[block_pos]; + if (offset_is_19bit(offset)) { + codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); + } else { + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg)); + offset = (uintptr_t) dest - (uintptr_t) &block_write_data[block_pos]; + codegen_addlong(block, OPCODE_B | OFFSET26(offset)); + } } -void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMEQ_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMEQ_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMEQ_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMEQ_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMGT_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMGT_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMGT_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMGT_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) +void +host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) { - if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) - { - host_arm64_CMP_IMM(block, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xfffff000)) - { - codegen_addlong(block, OPCODE_CMN_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMN_IMM %08x\n", imm_data); + if ((int32_t) imm_data < 0 && imm_data != (1ull << 31)) { + host_arm64_CMP_IMM(block, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xfffff000)) { + codegen_addlong(block, OPCODE_CMN_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMN_IMM %08x\n", imm_data); } -void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) +void +host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) { - if ((int64_t)imm_data < 0 && imm_data != (1ull << 63)) - { - host_arm64_CMPX_IMM(block, src_n_reg, -(int64_t)imm_data); - } - else if (!(imm_data & 0xfffffffffffff000ull)) - { - codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMNX_IMM %08x\n", imm_data); + if ((int64_t) imm_data < 0 && imm_data != (1ull << 63)) { + host_arm64_CMPX_IMM(block, src_n_reg, -(int64_t) imm_data); + } else if (!(imm_data & 0xfffffffffffff000ull)) { + codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMNX_IMM %08x\n", imm_data); } -void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) +void +host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) { - if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) - { - host_arm64_CMN_IMM(block, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xfffff000)) - { - codegen_addlong(block, OPCODE_CMP_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMP_IMM %08x\n", imm_data); + if ((int32_t) imm_data < 0 && imm_data != (1ull << 31)) { + host_arm64_CMN_IMM(block, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xfffff000)) { + codegen_addlong(block, OPCODE_CMP_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMP_IMM %08x\n", imm_data); } -void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) +void +host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data) { - if ((int64_t)imm_data < 0 && imm_data != (1ull << 63)) - { - host_arm64_CMNX_IMM(block, src_n_reg, -(int64_t)imm_data); - } - else if (!(imm_data & 0xfffffffffffff000ull)) - { - codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - } - else - fatal("CMPX_IMM %08x\n", imm_data); + if ((int64_t) imm_data < 0 && imm_data != (1ull << 63)) { + host_arm64_CMNX_IMM(block, src_n_reg, -(int64_t) imm_data); + } else if (!(imm_data & 0xfffffffffffff000ull)) { + codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + } else + fatal("CMPX_IMM %08x\n", imm_data); } -void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_CC) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_CC) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_EQ) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_EQ) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element) +void +host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element) { - codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element)); + codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element)); } -void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_EOR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_EOR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FABS_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FABS_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMGE_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMGE_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg) +void +host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FCMP_D | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FCMP_D | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVT_D_S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVT_D_S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTMS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTMS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTMS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTMS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTNS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTNS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTNS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTNS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTPS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTPS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTPS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTPS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTZS_W_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTZS_W_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FCVTZS_V2S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FCVTZS_V2S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FDIV_S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FDIV_S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMAX_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMAX_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMIN_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMIN_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FMUL_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FMUL_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_FSUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_FSUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_D_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_D_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_D_Q | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_D_Q | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_Q_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_Q_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_S_W | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_S_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg) +void +host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg) { - codegen_addlong(block, OPCODE_FMOV_S_ONE | Rd(dst_reg)); + codegen_addlong(block, OPCODE_FMOV_S_ONE | Rd(dst_reg)); } -void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FNEG_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FNEG_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_FSQRT_S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_FSQRT_S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +void +host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { - if (!in_range7_x(offset)) - fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); - codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); + if (!in_range7_x(offset)) + fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); } -void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_w(offset)) - fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_w(offset)) + fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_q(offset)) - fatal("host_arm64_LDR_IMM_X out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_q(offset)) + fatal("host_arm64_LDR_IMM_X out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRX_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRX_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset) { - codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_b(offset)) - fatal("host_arm64_LDRB_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDRB_IMM_W | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_b(offset)) + fatal("host_arm64_LDRB_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDRB_IMM_W | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_h(offset)) - fatal("host_arm64_LDRH_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_LDRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_h(offset)) + fatal("host_arm64_LDRH_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_LDRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) +void +host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); + codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg)); } -void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_ASR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_ASR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - if (dst_reg != src_m_reg || shift) - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + if (dst_reg != src_m_reg || shift) + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_ROR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_ROR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) +void +host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data) { - codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg)); - if ((imm_data >> 16) & 0xffff) - codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg)); - if ((imm_data >> 32) & 0xffff) - codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg)); - if ((imm_data >> 48) & 0xffff) - codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg)); + codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg)); + if ((imm_data >> 16) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg)); + if ((imm_data >> 32) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg)); + if ((imm_data >> 48) & 0xffff) + codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg)); } -void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) +void +host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift) { - if (dst_reg != src_m_reg) - codegen_addlong(block, OPCODE_ORRX_LSL | Rd(dst_reg) | Rn(REG_XZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + if (dst_reg != src_m_reg) + codegen_addlong(block, OPCODE_ORRX_LSL | Rd(dst_reg) | Rn(REG_XZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) +void +host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data) { - int hw; + int hw; - if (!imm_is_imm16(imm_data)) - fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); + if (!imm_is_imm16(imm_data)) + fatal("MOVZ_IMM - imm not representable %08x\n", imm_data); - hw = (imm_data & 0xffff0000) ? 1 : 0; - if (hw) - imm_data >>= 16; + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; - codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); + codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); } -void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) +void +host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data) { - int hw; + int hw; - if (!imm_is_imm16(imm_data)) - fatal("MOVK_IMM - imm not representable %08x\n", imm_data); + if (!imm_is_imm16(imm_data)) + fatal("MOVK_IMM - imm not representable %08x\n", imm_data); - hw = (imm_data & 0xffff0000) ? 1 : 0; - if (hw) - imm_data >>= 16; + hw = (imm_data & 0xffff0000) ? 1 : 0; + if (hw) + imm_data >>= 16; - codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); + codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg)); } -void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg) +void +host_arm64_MSR_FPCR(codeblock_t *block, int src_reg) { - codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg)); + codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg)); } -void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_MUL_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_MUL_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_NOP(codeblock_t *block) +void +host_arm64_NOP(codeblock_t *block) { - codegen_addlong(block, OPCODE_NOP); + codegen_addlong(block, OPCODE_NOP); } -void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - uint32_t imm_encoding = host_arm64_find_imm(imm_data); + uint32_t imm_encoding = host_arm64_find_imm(imm_data); - if (imm_encoding) - { - codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); - } - else - { - host_arm64_mov_imm(block, REG_W16, imm_data); - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (imm_encoding) { + codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM_LOGICAL(imm_encoding)); + } else { + host_arm64_mov_imm(block, REG_W16, imm_data); + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ORR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ORR_V | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_RET(codeblock_t *block, int reg) +void +host_arm64_RET(codeblock_t *block, int reg) { - codegen_addlong(block, OPCODE_RET | Rn(reg)); + codegen_addlong(block, OPCODE_RET | Rn(reg)); } -void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) +void +host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg) { - codegen_addlong(block, OPCODE_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); + codegen_addlong(block, OPCODE_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg)); } -void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) +void +host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg) { - codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); + codegen_addlong(block, OPCODE_SADDLP_V2S_4H | Rd(dst_reg) | Rn(src_n_reg)); } -void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); + codegen_addlong(block, OPCODE_SBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb + width - 1) & 31)); } -void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SCVTF_D_Q | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SCVTF_D_Q | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SCVTF_V2S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SCVTF_V2S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 16) - fatal("host_arm64_SHRN_V4H_4S : shift > 16\n"); - codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | SHRN_SHIFT_IMM_V4S(16-shift)); + if (shift > 16) + fatal("host_arm64_SHRN_V4H_4S : shift > 16\n"); + codegen_addlong(block, OPCODE_SHRN | Rd(dst_reg) | Rn(src_n_reg) | SHRN_SHIFT_IMM_V4S(16 - shift)); } -void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SMULL_V4S_4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SMULL_V4S_4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_SQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_SQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); } -void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); } -void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); + codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } -void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 16) - fatal("host_arm_USHR_V4H : shift > 16\n"); - codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16-shift)); + if (shift > 16) + fatal("host_arm_USHR_V4H : shift > 16\n"); + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16 - shift)); } -void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 32) - fatal("host_arm_SSHR_V2S : shift > 32\n"); - codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32-shift)); + if (shift > 32) + fatal("host_arm_SSHR_V2S : shift > 32\n"); + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32 - shift)); } -void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 64) - fatal("host_arm_SSHR_V2D : shift > 64\n"); - codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64-shift)); + if (shift > 64) + fatal("host_arm_SSHR_V2D : shift > 64\n"); + codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64 - shift)); } -void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) +void +host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) { - if (!in_range7_x(offset)) - fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); - codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); + if (!in_range7_x(offset)) + fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset); + codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2)); } -void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_w(offset)) - fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_w(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_q(offset)) - fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_q(offset)) + fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG_F32 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset) +void +host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset) { - codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg)); } -void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG_F64 | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_b(offset)) - fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_b(offset)) + fatal("host_arm64_STRB_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if (!in_range12_h(offset)) - fatal("host_arm64_STRH_IMM out of range12 %i\n", offset); - codegen_addlong(block, OPCODE_STRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); + if (!in_range12_h(offset)) + fatal("host_arm64_STRH_IMM out of range12 %i\n", offset); + codegen_addlong(block, OPCODE_STRH_IMM | OFFSET12_H(offset) | Rn(base_reg) | Rt(dest_reg)); } -void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) +void +host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg) { - codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); + codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg)); } -void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) +void +host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { - if (!imm_data) - host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); - else if ((int32_t)imm_data < 0 && imm_data != 0x80000000) - { - host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data); - } - else if (!(imm_data & 0xff000000)) - { - if (imm_data & 0xfff) - { - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); - if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else if (imm_data & 0xfff000) - codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); - } - else - { - host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); - codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); - } + if (!imm_data) + host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0); + else if ((int32_t) imm_data < 0 && imm_data != 0x80000000) { + host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t) imm_data); + } else if (!(imm_data & 0xff000000)) { + if (imm_data & 0xfff) { + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0)); + if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else if (imm_data & 0xfff000) + codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1)); + } else { + host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000); + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0)); + } } -void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void +host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) { - codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) +uint32_t * +host_arm64_TBNZ(codeblock_t *block, int reg, int bit) { - codegen_alloc(block, 12); - codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8)); - codegen_addlong(block, OPCODE_B); - return (uint32_t *)&block_write_data[block_pos-4]; + codegen_alloc(block, 12); + codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8)); + codegen_addlong(block, OPCODE_B); + return (uint32_t *) &block_write_data[block_pos - 4]; } -void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); + codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb + width - 1) & 31)); } -void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_UQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_UQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_UQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); + codegen_addlong(block, OPCODE_UQXTN_V4H_4S | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 16) - fatal("host_arm_USHR_V4H : shift > 16\n"); - codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16-shift)); + if (shift > 16) + fatal("host_arm_USHR_V4H : shift > 16\n"); + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(16 - shift)); } -void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 32) - fatal("host_arm_USHR_V4S : shift > 32\n"); - codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32-shift)); + if (shift > 32) + fatal("host_arm_USHR_V4S : shift > 32\n"); + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(32 - shift)); } -void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) +void +host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int shift) { - if (shift > 64) - fatal("host_arm_USHR_V2D : shift > 64\n"); - codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64-shift)); + if (shift > 64) + fatal("host_arm_USHR_V2D : shift > 64\n"); + codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(64 - shift)); } -void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP1_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP1_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP1_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP1_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP1_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP1_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP2_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP2_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP2_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP2_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +void +host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ZIP2_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); + codegen_addlong(block, OPCODE_ZIP2_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_call(codeblock_t *block, void *dst_addr) +void +host_arm64_call(codeblock_t *block, void *dst_addr) { - host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); - host_arm64_BLR(block, REG_X16); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t) dst_addr); + host_arm64_BLR(block, REG_X16); } -void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) +void +host_arm64_jump(codeblock_t *block, uintptr_t dst_addr) { - host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr); - host_arm64_BR(block, REG_X16); + host_arm64_MOVX_IMM(block, REG_X16, (uint64_t) dst_addr); + host_arm64_BR(block, REG_X16); } -void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) +void +host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data) { - if (imm_is_imm16(imm_data)) - host_arm64_MOVZ_IMM(block, reg, imm_data); - else - { - host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); - host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); - } + if (imm_is_imm16(imm_data)) + host_arm64_MOVZ_IMM(block, reg, imm_data); + else { + host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff); + host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000); + } } #endif diff --git a/src/codegen_new/codegen_backend_arm64_ops.h b/src/codegen_new/codegen_backend_arm64_ops.h index c89a02311..df751b4aa 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.h +++ b/src/codegen_new/codegen_backend_arm64_ops.h @@ -251,13 +251,11 @@ void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); - -#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7)) +#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) &7)) #define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000)) -#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1)) -#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3)) -#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7)) - +#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) &1)) +#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) &3)) +#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) &7)) void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 10a07a4a2..91fb9c903 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -1,3372 +1,3251 @@ #if defined __aarch64__ || defined _M_ARM64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "x86.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_backend.h" -#include "codegen_backend_arm64_defs.h" -#include "codegen_backend_arm64_ops.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x87.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_backend.h" +# include "codegen_backend_arm64_defs.h" +# include "codegen_backend_arm64_ops.h" +# include "codegen_ir_defs.h" -#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) +# define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) -#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) +# define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f) -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) -static int codegen_ADD(codeblock_t *block, uop_t *uop) +static int +codegen_ADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_ADD_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_a, 0x0000ff00); - host_arm64_ADD_REG(block, REG_TEMP, REG_TEMP, src_reg_b, 0); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_ADD_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_ADD_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_a, 0x0000ff00); + host_arm64_ADD_REG(block, REG_TEMP, REG_TEMP, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ADD_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ADD_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); - return 0; + host_arm64_ADD_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + return 0; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_AND_REG_V(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_AND_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff0000); - host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); - host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); - host_arm64_AND_REG_ASR(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); - host_arm64_AND_REG_ROR(block, dest_reg, src_reg_a, REG_TEMP, 24); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); - host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); - host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_a, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_ORR_IMM(block, REG_TEMP, src_reg_a, 0xffff00ff); - host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_b, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_AND_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_AND_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff0000); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ASR(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffffff00); + host_arm64_AND_REG_ROR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_b, 0xffff00ff); + host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_a, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_ORR_IMM(block, REG_TEMP, src_reg_a, 0xffff00ff); + host_arm64_AND_REG_ROR(block, REG_TEMP, src_reg_b, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_AND_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); - } - else - fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } else + fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ANDN(codeblock_t *block, uop_t *uop) +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_BIC_REG_V(block, dest_reg, src_reg_b, src_reg_a); - } - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_BIC_REG_V(block, dest_reg, src_reg_b, src_reg_a); + } else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - host_arm64_call(block, uop->p); + host_arm64_call(block, uop->p); - return 0; + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); - host_arm64_call(block, uop->p); - host_arm64_MOV_REG(block, dest_reg, REG_W0, 0); + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_arm64_call(block, uop->p); + host_arm64_MOV_REG(block, dest_reg, REG_W0, 0); - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { - host_arm64_call(block, uop->p); - host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); + host_arm64_call(block, uop->p); + host_arm64_CBNZ(block, REG_X0, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_CMP_IMM(block, src_reg, uop->imm_data); - } - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); - host_arm64_BEQ(block, uop->p); + if (REG_IS_L(src_size)) { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_arm64_BEQ(block, uop->p); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BNE_(block); + uop->p = host_arm64_BNE_(block); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BEQ_(block); + uop->p = host_arm64_BEQ_(block); - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); - jump_p = host_arm64_BCC_(block); - host_arm64_branch_set_offset(jump_p, uop->p); + jump_p = host_arm64_BCC_(block); + host_arm64_branch_set_offset(jump_p, uop->p); - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); - jump_p = host_arm64_BHI_(block); - host_arm64_branch_set_offset(jump_p, uop->p); + jump_p = host_arm64_BHI_(block); + host_arm64_branch_set_offset(jump_p, uop->p); - return 0; + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BCS_(block); + uop->p = host_arm64_BCS_(block); - return 0; + return 0; } -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BHI_(block); + uop->p = host_arm64_BHI_(block); - return 0; + return 0; } -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BGE_(block); + uop->p = host_arm64_BGE_(block); - return 0; + return 0; } -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BGT_(block); + uop->p = host_arm64_BGT_(block); - return 0; + return 0; } -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BVC_(block); + uop->p = host_arm64_BVC_(block); - return 0; + return 0; } -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BNE_(block); + uop->p = host_arm64_BNE_(block); - return 0; + return 0; } -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BCC_(block); + uop->p = host_arm64_BCC_(block); - return 0; + return 0; } -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BLS_(block); + uop->p = host_arm64_BLS_(block); - return 0; + return 0; } -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BLT_(block); + uop->p = host_arm64_BLT_(block); - return 0; + return 0; } -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BLE_(block); + uop->p = host_arm64_BLE_(block); - return 0; + return 0; } -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BVS_(block); + uop->p = host_arm64_BVS_(block); - return 0; + return 0; } -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); - host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 16); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg_a, 24); + host_arm64_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BEQ_(block); + uop->p = host_arm64_BEQ_(block); - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_FABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FABS_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FABS_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FNEG_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FNEG_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FSQRT_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FSQRT_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FTST(codeblock_t *block, uop_t *uop) +static int +codegen_FTST(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); - host_arm64_MOVZ_IMM(block, dest_reg, 0); - host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); - host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0|C2|C3); - host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); - host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); - } - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); + host_arm64_MOVZ_IMM(block, dest_reg, 0); + host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); + host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); + } else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_FADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FADD_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FADD_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FCOM(codeblock_t *block, uop_t *uop) +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_MOVZ_IMM(block, dest_reg, 0); - host_arm64_FCMP_D(block, src_reg_a, src_reg_b); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); - host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0|C2|C3); - host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); - host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); - } - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_MOVZ_IMM(block, dest_reg, 0); + host_arm64_FCMP_D(block, src_reg_a, src_reg_b); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); + host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); + } else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FDIV(codeblock_t *block, uop_t *uop) +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FDIV_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FDIV_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FMUL(codeblock_t *block, uop_t *uop) +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FMUL_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FMUL_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FSUB(codeblock_t *block, uop_t *uop) +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm64_FSUB_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm64_FSUB_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - uint32_t *branch_ptr; + uint32_t *branch_ptr; - if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) - fatal("codegen_FP_ENTER - out of range\n"); + if (!in_range12_w((uintptr_t) &cr0 - (uintptr_t) &cpu_state)) + fatal("codegen_FP_ENTER - out of range\n"); - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm64_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm64_BEQ_(block); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); - host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm64_mov_imm(block, REG_ARG0, 7); - host_arm64_call(block, x86_int); - host_arm64_B(block, codegen_exit_rout); + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, codegen_exit_rout); - host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); + host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]); - return 0; + return 0; } -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint32_t *branch_ptr; + uint32_t *branch_ptr; - if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state)) - fatal("codegen_MMX_ENTER - out of range\n"); + if (!in_range12_w((uintptr_t) &cr0 - (uintptr_t) &cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm64_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm64_BEQ_(block); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm64_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm64_BEQ_(block); - host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm64_mov_imm(block, REG_ARG0, 7); - host_arm64_call(block, x86_int); - host_arm64_B(block, codegen_exit_rout); + host_arm64_mov_imm(block, REG_TEMP, uop->imm_data); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm64_mov_imm(block, REG_ARG0, 7); + host_arm64_call(block, x86_int); + host_arm64_B(block, codegen_exit_rout); - host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); + host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]); - host_arm64_mov_imm(block, REG_TEMP, 0x01010101); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); - host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); - host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); + host_arm64_mov_imm(block, REG_TEMP, 0x01010101); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[0] - (uintptr_t) &cpu_state); + host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[4] - (uintptr_t) &cpu_state); + host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t) &cpu_state.ismmx - (uintptr_t) &cpu_state); - return 0; + return 0; } -static int codegen_JMP(codeblock_t *block, uop_t *uop) +static int +codegen_JMP(codeblock_t *block, uop_t *uop) { - host_arm64_jump(block, (uintptr_t)uop->p); + host_arm64_jump(block, (uintptr_t) uop->p); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); - } - else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); + } else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); - return 0; + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; } -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); - return 0; + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; } -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); - return 0; + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; } -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG1, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG1, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG2, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG2, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG3, uop->imm_data); + host_arm64_mov_imm(block, REG_ARG3, uop->imm_data); - return 0; + return 0; } -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); - host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t)uop->p); - host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); - host_arm64_call(block, (void *)loadseg); - host_arm64_CBNZ(block, REG_X0, (uintptr_t)codegen_exit_rout); + host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t) uop->p); + host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff); + host_arm64_call(block, (void *) loadseg); + host_arm64_CBNZ(block, REG_X0, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - host_arm64_ADD_IMM(block, REG_X0, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm64_call(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_call(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_call(block, codegen_mem_load_long); - } - else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); - } + host_arm64_ADD_IMM(block, REG_X0, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm64_call(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm64_call(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm64_call(block, codegen_mem_load_long); + } else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); + } else if (REG_IS_L(dest_size)) { + host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); + } - return 0; + return 0; } -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm64_call(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_call(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_call(block, codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_arm64_call(block, codegen_mem_load_quad); - } - else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); - } - else if (REG_IS_Q(dest_size)) - { - host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); - } + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm64_call(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm64_call(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm64_call(block, codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_arm64_call(block, codegen_mem_load_quad); + } else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm64_BFI(block, dest_reg, REG_X0, 0, 16); + } else if (REG_IS_L(dest_size)) { + host_arm64_MOV_REG(block, dest_reg, REG_X0, 0); + } else if (REG_IS_Q(dest_size)) { + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + } - return 0; + return 0; } -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_call(block, codegen_mem_load_double); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_call(block, codegen_mem_load_double); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + host_arm64_FMOV_D_D(block, dest_reg, REG_V_TEMP); - return 0; + return 0; } -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_call(block, codegen_mem_load_single); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - host_arm64_FCVT_D_S(block, dest_reg, REG_V_TEMP); + host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_call(block, codegen_mem_load_single); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + host_arm64_FCVT_D_S(block, dest_reg, REG_V_TEMP); - return 0; + return 0; } -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - host_arm64_ADD_IMM(block, REG_W0, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); - host_arm64_call(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, REG_W1, src_reg, 0); - host_arm64_call(block, codegen_mem_store_long); - } - else - fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); - host_arm64_call(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); - host_arm64_call(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, REG_W1, src_reg, 0); - host_arm64_call(block, codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_mem_store_quad); - } - else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_ADD_IMM(block, REG_W0, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); host_arm64_call(block, codegen_mem_store_byte); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - host_arm64_mov_imm(block, REG_W1, uop->imm_data); + } else if (REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); + host_arm64_call(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); host_arm64_call(block, codegen_mem_store_word); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - host_arm64_mov_imm(block, REG_W1, uop->imm_data); + } else if (REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, REG_W1, src_reg, 0); host_arm64_call(block, codegen_mem_store_long); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); + } else + fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - return 0; + return 0; +} +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff); + host_arm64_call(block, codegen_mem_store_byte); + } else if (REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_W1, src_reg, 8, 8); + host_arm64_call(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff); + host_arm64_call(block, codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, REG_W1, src_reg, 0); + host_arm64_call(block, codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_quad); + } else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_byte); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_FCVT_S_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_mem_store_single); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); - - return 0; + return 0; } -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_word); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); - if (uop->imm_data) - host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_mem_store_double); - host_arm64_CBNZ(block, REG_X1, (uintptr_t)codegen_exit_rout); + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - return 0; + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + host_arm64_mov_imm(block, REG_W1, uop->imm_data); + host_arm64_call(block, codegen_mem_store_long); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_MOV(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_BFI(block, dest_reg, src_reg, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_BFI(block, dest_reg, src_reg, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) - { - host_arm64_BFI(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - } - else - fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - return 0; + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_FCVT_S_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_single); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (REG_IS_L(dest_size)) - { - host_arm64_mov_imm(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data & 0xffff); - } - else if (REG_IS_B(dest_size)) - { - host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("MOV_IMM %x\n", uop->dest_reg_a_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); + host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0); + if (uop->imm_data) + host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data); + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_mem_store_double); + host_arm64_CBNZ(block, REG_X1, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) +static int +codegen_MOV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm64_SBFX(block, dest_reg, src_reg, 0, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SBFX(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm64_SBFX(block, dest_reg, src_reg, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) { + host_arm64_BFI(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + } else + fatal("MOV %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_arm64_FMOV_D_Q(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_arm64_FMOV_W_S(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size)) { + host_arm64_mov_imm(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_arm64_MOVK_IMM(block, dest_reg, uop->imm_data & 0xffff); + } else if (REG_IS_B(dest_size)) { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm64_MOVZ_IMM(block, REG_TEMP, uop->imm_data & 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("MOV_IMM %x\n", uop->dest_reg_a_real); - return 0; + return 0; +} +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t) uop->p); + + return 0; } -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_arm64_SCVTF_D_W(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - host_arm64_FMOV_Q_D(block, REG_TEMP, src_reg); - host_arm64_SCVTF_D_Q(block, dest_reg, REG_TEMP); - } + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm64_SBFX(block, dest_reg, src_reg, 0, 8); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SBFX(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm64_SBFX(block, dest_reg, src_reg, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { + host_arm64_FMOV_D_Q(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_arm64_FMOV_W_S(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xff); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, dest_reg, src_reg, 0xffff); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_arm64_SCVTF_D_W(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_arm64_SBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SCVTF_D_W(block, dest_reg, REG_TEMP); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + host_arm64_FMOV_Q_D(block, REG_TEMP, src_reg); + host_arm64_SCVTF_D_Q(block, dest_reg, REG_TEMP); + } else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round); + host_arm64_MOV_REG(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_arm64_FMOV_D_D(block, dest_reg, src_64_reg); + branch_offset = host_arm64_TBNZ(block, tag_reg, 7); + + host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); + host_arm64_call(block, codegen_fp_round_quad); + host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); + + host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); + } else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm64_LDR_IMM_W(block, dest_reg, REG_TEMP, 0); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm64_LDRB_IMM_W(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size)) { + host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm64_LDRH_IMM(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm64_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ORR_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_ORR_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_arm64_SQXTN_V4H_4S(block, REG_V_TEMP, src_reg_b); + host_arm64_SQXTN_V4H_4S(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + } else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMEQ_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a); + } else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRECPE/VRECPS)*/ + host_arm64_FMOV_S_ONE(block, REG_V_TEMP); + host_arm64_FDIV_S(block, dest_reg, REG_V_TEMP, src_reg_a); + host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); + } else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ + host_arm64_FSQRT_S(block, REG_V_TEMP, src_reg_a); + host_arm64_FMOV_S_ONE(block, REG_V_TEMP); + host_arm64_FDIV_S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); + } else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a); + } else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SMULL_V4S_4H(block, REG_V_TEMP, src_reg_a, src_reg_b); + host_arm64_ADDP_V4S(block, dest_reg, REG_V_TEMP, REG_V_TEMP); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SMULL_V4S_4H(block, dest_reg, src_reg_a, src_reg_b); + host_arm64_SHRN_V4H_4S(block, dest_reg, dest_reg, 16); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_fp_round); - host_arm64_MOV_REG(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_fp_round); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_arm64_FMOV_D_D(block, dest_reg, src_64_reg); - branch_offset = host_arm64_TBNZ(block, tag_reg, 7); - - host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg); - host_arm64_call(block, codegen_fp_round_quad); - host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP); - - host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm64_LDR_IMM_W(block, dest_reg, REG_TEMP, 0); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm64_LDRB_IMM_W(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size)) - { - host_arm64_LDRB_IMM_W(block, REG_TEMP, REG_TEMP, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm64_MOVX_IMM(block, REG_TEMP, (uint64_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm64_LDRH_IMM(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm64_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_NOP(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) { - return 0; -} + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); -static int codegen_OR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ORR_REG_V(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_ORR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_ORR_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_ORR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm64_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_arm64_SQXTN_V4H_4S(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTN_V4H_4S(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm64_FMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PADDB(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ADD_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDW(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ADD_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDD(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ADD_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SUB_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_SQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQADD_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQADD_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_UQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMEQ_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_ZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) +static int +codegen_ROL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a); - } - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 32); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ROR(block, dest_reg, src_reg, REG_TEMP2); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 16); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_ROR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + cs = cs; + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_mov_imm(block, REG_TEMP2, 8); + host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PFADD(codeblock_t *block, uop_t *uop) +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } else { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); } - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 16); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16 - (uop->imm_data & 15)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + host_arm64_BFI(block, dest_reg, src_reg, 0, 8); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); } - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRECPE/VRECPS)*/ - host_arm64_FMOV_S_ONE(block, REG_V_TEMP); - host_arm64_FDIV_S(block, dest_reg, REG_V_TEMP, src_reg_a); - host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ - host_arm64_FSQRT_S(block, REG_V_TEMP, src_reg_a); - host_arm64_FMOV_S_ONE(block, REG_V_TEMP); - host_arm64_FDIV_S(block, dest_reg, dest_reg, REG_V_TEMP); - host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a); - } - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SMULL_V4S_4H(block, REG_V_TEMP, src_reg_a, src_reg_b); - host_arm64_ADDP_V4S(block, dest_reg, REG_V_TEMP, REG_V_TEMP); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SMULL_V4S_4H(block, dest_reg, src_reg_a, src_reg_b); - host_arm64_SHRN_V4H_4S(block, dest_reg, dest_reg, 16); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_MUL_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); - else - host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); - else - host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); - else - host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm64_FMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); - else - host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SUB_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SUB_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SUB_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_SQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQSUB_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_UQSUB_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP2_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP2_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP2_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP1_V8B(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP1_V4H(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_ZIP1_V2S(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 32); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_ROR(block, dest_reg, src_reg, REG_TEMP2); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 16); - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_ROR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - cs = cs; - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 8); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_mov_imm(block, REG_TEMP2, 8); - host_arm64_SUB_REG(block, REG_TEMP2, REG_TEMP2, shift_reg, 0); - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm64_MOV_REG(block, dest_reg, src_reg, 0); - } - else - { - host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); - } - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - host_arm64_BFI(block, dest_reg, src_reg, 0, 16); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - host_arm64_BFI(block, dest_reg, src_reg, 0, 8); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR(codeblock_t *block, uop_t *uop) +static int +codegen_ROR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ROR(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 15); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ROR(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm64_MOV_REG(block, dest_reg, src_reg, 0); - } - else - { - host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); - } + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm64_MOV_REG(block, dest_reg, src_reg, 0); + } else { + host_arm64_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 16); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 0, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_ORR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR(codeblock_t *block, uop_t *uop) +static int +codegen_SAR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_ASR(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); - host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_ASR(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_ASR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); - host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); - host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 16, 16); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 24); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, 16); + host_arm64_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_UBFX(block, REG_TEMP, REG_TEMP, 24, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL(codeblock_t *block, uop_t *uop) +static int +codegen_SHL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_LSL(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_LSL(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_LSL(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_LSL(block, REG_TEMP, src_reg, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_LSL(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_MOV_REG(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_MOV_REG(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_MOV_REG(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR(codeblock_t *block, uop_t *uop) +static int +codegen_SHR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_LSR(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_LSR(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_LSR(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xffff); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg, 0xff); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_UBFX(block, REG_TEMP, src_reg, 8, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_W16, uop->imm_data); + host_arm64_mov_imm(block, REG_W16, uop->imm_data); - if (in_range12_w((uintptr_t)uop->p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_W(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + if (in_range12_w((uintptr_t) uop->p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_W(block, REG_W16, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_W16, uop->imm_data); + host_arm64_mov_imm(block, REG_W16, uop->imm_data); - if (in_range12_b((uintptr_t)uop->p - (uintptr_t)&cpu_state)) - host_arm64_STRB_IMM(block, REG_W16, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + if (in_range12_b((uintptr_t) uop->p - (uintptr_t) &cpu_state)) + host_arm64_STRB_IMM(block, REG_W16, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_SUB(codeblock_t *block, uop_t *uop) +static int +codegen_SUB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_SUB_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); - host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); - host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_SUB_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm64_SUB_REG(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm64_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm64_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm64_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm64_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm64_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BEQ_(block); + uop->p = host_arm64_BEQ_(block); - return 0; + return 0; } -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm64_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm64_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm64_BNE_(block); + uop->p = host_arm64_BNE_(block); - return 0; + return 0; } -static int codegen_XOR(codeblock_t *block, uop_t *uop) +static int +codegen_XOR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm64_EOR_REG_V(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm64_EOR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); - host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm64_EOR_REG_V(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm64_EOR_REG(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xffff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm64_AND_IMM(block, REG_TEMP, src_reg_b, 0xff); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm64_UBFX(block, REG_TEMP, src_reg_b, 8, 8); + host_arm64_EOR_REG(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm64_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, - [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_JMP & + UOP_MASK] + = codegen_JMP, - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDRB_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_8 - not in range\n"); + if (in_range12_b((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDRB_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_8 - not in range\n"); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - if (in_range12_h((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_16 - not in range\n"); + if (in_range12_h((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_16 - not in range\n"); } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (in_range12_w((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_double - not in range\n"); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_X(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_pointer - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_X(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_pointer - not in range\n"); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_double - not in range\n"); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_LDRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_8 - not in range\n"); + if (in_range12_b((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_8 - not in range\n"); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - if (in_range12_h((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_16 - not in range\n"); + if (in_range12_h((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_16 - not in range\n"); } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_32 - not in range\n"); + if (in_range12_w((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_32 - not in range\n"); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_double - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_double - not in range\n"); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); - host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state); - host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); + host_arm64_LDR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset); + host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm64_ADDX_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t) base - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state)) - host_arm64_STR_IMM_Q(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_ptr - not in range\n"); + if (in_range12_q((uintptr_t) p - (uintptr_t) &cpu_state)) + host_arm64_STR_IMM_Q(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_ptr - not in range\n"); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (in_range12_h(stack_offset)) - host_arm64_LDRH_IMM(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_read_32_stack - not in range\n"); + if (in_range12_h(stack_offset)) + host_arm64_LDRH_IMM(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (in_range12_w(stack_offset)) - host_arm64_LDR_IMM_W(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_read_32_stack - not in range\n"); + if (in_range12_w(stack_offset)) + host_arm64_LDR_IMM_W(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_read_32_stack - not in range\n"); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (in_range12_q(stack_offset)) - host_arm64_LDR_IMM_X(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_read_pointer_stack - not in range\n"); + if (in_range12_q(stack_offset)) + host_arm64_LDR_IMM_X(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_read_pointer_stack - not in range\n"); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_LDR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - if (in_range12_w(stack_offset)) - host_arm64_STR_IMM_W(block, host_reg, REG_XSP, stack_offset); - else - fatal("codegen_direct_write_32_stack - not in range\n"); + if (in_range12_w(stack_offset)) + host_arm64_STR_IMM_W(block, host_reg, REG_XSP, stack_offset); + else + fatal("codegen_direct_write_32_stack - not in range\n"); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); + host_arm64_STR_IMM_F64(block, host_reg, REG_XSP, stack_offset); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(codeblock_t *block, void *p) { - host_arm64_branch_set_offset(p, &block_write_data[block_pos]); + host_arm64_branch_set_offset(p, &block_write_data[block_pos]); } #endif diff --git a/src/codegen_new/codegen_backend_arm_defs.h b/src/codegen_new/codegen_backend_arm_defs.h index 74567998a..745854429 100644 --- a/src/codegen_new/codegen_backend_arm_defs.h +++ b/src/codegen_new/codegen_backend_arm_defs.h @@ -1,72 +1,71 @@ -#define REG_R0 0 -#define REG_R1 1 -#define REG_R2 2 -#define REG_R3 3 -#define REG_R4 4 -#define REG_R5 5 -#define REG_R6 6 -#define REG_R7 7 -#define REG_R8 8 -#define REG_R9 9 -#define REG_R10 10 -#define REG_R11 11 -#define REG_R12 12 -#define REG_HOST_SP 13 -#define REG_LR 14 -#define REG_PC 15 +#define REG_R0 0 +#define REG_R1 1 +#define REG_R2 2 +#define REG_R3 3 +#define REG_R4 4 +#define REG_R5 5 +#define REG_R6 6 +#define REG_R7 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_HOST_SP 13 +#define REG_LR 14 +#define REG_PC 15 -#define REG_ARG0 REG_R0 -#define REG_ARG1 REG_R1 -#define REG_ARG2 REG_R2 -#define REG_ARG3 REG_R3 +#define REG_ARG0 REG_R0 +#define REG_ARG1 REG_R1 +#define REG_ARG2 REG_R2 +#define REG_ARG3 REG_R3 -#define REG_CPUSTATE REG_R10 +#define REG_CPUSTATE REG_R10 -#define REG_TEMP REG_R3 -#define REG_TEMP2 REG_R2 +#define REG_TEMP REG_R3 +#define REG_TEMP2 REG_R2 -#define REG_D0 0 -#define REG_D1 1 -#define REG_D2 2 -#define REG_D3 3 -#define REG_D4 4 -#define REG_D5 5 -#define REG_D6 6 -#define REG_D7 7 -#define REG_D8 8 -#define REG_D9 9 -#define REG_D10 10 -#define REG_D11 11 -#define REG_D12 12 -#define REG_D13 13 -#define REG_D14 14 -#define REG_D15 15 +#define REG_D0 0 +#define REG_D1 1 +#define REG_D2 2 +#define REG_D3 3 +#define REG_D4 4 +#define REG_D5 5 +#define REG_D6 6 +#define REG_D7 7 +#define REG_D8 8 +#define REG_D9 9 +#define REG_D10 10 +#define REG_D11 11 +#define REG_D12 12 +#define REG_D13 13 +#define REG_D14 14 +#define REG_D15 15 -#define REG_D_TEMP REG_D0 -#define REG_Q_TEMP REG_D0 -#define REG_Q_TEMP_2 REG_D2 +#define REG_D_TEMP REG_D0 +#define REG_Q_TEMP REG_D0 +#define REG_Q_TEMP_2 REG_D2 -#define REG_MASK_R0 (1 << REG_R0) -#define REG_MASK_R1 (1 << REG_R1) -#define REG_MASK_R2 (1 << REG_R2) -#define REG_MASK_R3 (1 << REG_R3) -#define REG_MASK_R4 (1 << REG_R4) -#define REG_MASK_R5 (1 << REG_R5) -#define REG_MASK_R6 (1 << REG_R6) -#define REG_MASK_R7 (1 << REG_R7) -#define REG_MASK_R8 (1 << REG_R8) -#define REG_MASK_R9 (1 << REG_R9) -#define REG_MASK_R10 (1 << REG_R10) -#define REG_MASK_R11 (1 << REG_R11) -#define REG_MASK_R12 (1 << REG_R12) -#define REG_MASK_SP (1 << REG_HOST_SP) -#define REG_MASK_LR (1 << REG_LR) -#define REG_MASK_PC (1 << REG_PC) +#define REG_MASK_R0 (1 << REG_R0) +#define REG_MASK_R1 (1 << REG_R1) +#define REG_MASK_R2 (1 << REG_R2) +#define REG_MASK_R3 (1 << REG_R3) +#define REG_MASK_R4 (1 << REG_R4) +#define REG_MASK_R5 (1 << REG_R5) +#define REG_MASK_R6 (1 << REG_R6) +#define REG_MASK_R7 (1 << REG_R7) +#define REG_MASK_R8 (1 << REG_R8) +#define REG_MASK_R9 (1 << REG_R9) +#define REG_MASK_R10 (1 << REG_R10) +#define REG_MASK_R11 (1 << REG_R11) +#define REG_MASK_R12 (1 << REG_R12) +#define REG_MASK_SP (1 << REG_HOST_SP) +#define REG_MASK_LR (1 << REG_LR) +#define REG_MASK_PC (1 << REG_PC) -#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \ - REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) +#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11) -#define CODEGEN_HOST_REGS 7 +#define CODEGEN_HOST_REGS 7 #define CODEGEN_HOST_FP_REGS 8 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_arm_ops.c b/src/codegen_new/codegen_backend_arm_ops.c index 43d1ea090..e56b2f6e5 100644 --- a/src/codegen_new/codegen_backend_arm_ops.c +++ b/src/codegen_new/codegen_backend_arm_ops.c @@ -1,1274 +1,1395 @@ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm_defs.h" -#include "codegen_backend_arm_ops.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm_defs.h" +# include "codegen_backend_arm_ops.h" -#define Rm(x) (x) -#define Rs(x) ((x) << 8) -#define Rd(x) ((x) << 12) -#define Rt(x) ((x) << 12) -#define Rn(x) ((x) << 16) -#define Rt2(x) ((x) << 16) +# define Rm(x) (x) +# define Rs(x) ((x) << 8) +# define Rd(x) ((x) << 12) +# define Rt(x) ((x) << 12) +# define Rn(x) ((x) << 16) +# define Rt2(x) ((x) << 16) -#define Vm(x) (x) -#define Vd(x) ((x) << 12) -#define Vn(x) ((x) << 16) +# define Vm(x) (x) +# define Vd(x) ((x) << 12) +# define Vn(x) ((x) << 16) -#define DATA_OFFSET_UP (1 << 23) -#define DATA_OFFSET_DOWN (0 << 23) +# define DATA_OFFSET_UP (1 << 23) +# define DATA_OFFSET_DOWN (0 << 23) -#define OPCODE_SHIFT 20 -#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) -#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) -#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) -#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) -#define OPCODE_B (0xa0 << OPCODE_SHIFT) -#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) -#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) -#define OPCODE_BL (0xb0 << OPCODE_SHIFT) -#define OPCODE_CMN_IMM (0x37 << OPCODE_SHIFT) -#define OPCODE_CMN_REG (0x17 << OPCODE_SHIFT) -#define OPCODE_CMP_IMM (0x35 << OPCODE_SHIFT) -#define OPCODE_CMP_REG (0x15 << OPCODE_SHIFT) -#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) -#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) -#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) -#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) -#define OPCODE_LDR_IMM_POST (0x41 << OPCODE_SHIFT) -#define OPCODE_LDR_REG (0x79 << OPCODE_SHIFT) -#define OPCODE_LDRB_IMM (0x55 << OPCODE_SHIFT) -#define OPCODE_LDRB_REG (0x7d << OPCODE_SHIFT) -#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) -#define OPCODE_MOVT_IMM (0x34 << OPCODE_SHIFT) -#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) -#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) -#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) -#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) -#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) -#define OPCODE_RSB_IMM (0x26 << OPCODE_SHIFT) -#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) -#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) -#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) -#define OPCODE_STR_IMM_WB (0x52 << OPCODE_SHIFT) -#define OPCODE_STR_REG (0x78 << OPCODE_SHIFT) -#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) -#define OPCODE_STRB_REG (0x7c << OPCODE_SHIFT) -#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) -#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) -#define OPCODE_TST_IMM (0x31 << OPCODE_SHIFT) -#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) +# define OPCODE_SHIFT 20 +# define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT) +# define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT) +# define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT) +# define OPCODE_AND_REG (0x00 << OPCODE_SHIFT) +# define OPCODE_B (0xa0 << OPCODE_SHIFT) +# define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT) +# define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT) +# define OPCODE_BL (0xb0 << OPCODE_SHIFT) +# define OPCODE_CMN_IMM (0x37 << OPCODE_SHIFT) +# define OPCODE_CMN_REG (0x17 << OPCODE_SHIFT) +# define OPCODE_CMP_IMM (0x35 << OPCODE_SHIFT) +# define OPCODE_CMP_REG (0x15 << OPCODE_SHIFT) +# define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT) +# define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT) +# define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT) +# define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT) +# define OPCODE_LDR_IMM_POST (0x41 << OPCODE_SHIFT) +# define OPCODE_LDR_REG (0x79 << OPCODE_SHIFT) +# define OPCODE_LDRB_IMM (0x55 << OPCODE_SHIFT) +# define OPCODE_LDRB_REG (0x7d << OPCODE_SHIFT) +# define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT) +# define OPCODE_MOVT_IMM (0x34 << OPCODE_SHIFT) +# define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT) +# define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT) +# define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT) +# define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT) +# define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT) +# define OPCODE_RSB_IMM (0x26 << OPCODE_SHIFT) +# define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT) +# define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT) +# define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT) +# define OPCODE_STR_IMM_WB (0x52 << OPCODE_SHIFT) +# define OPCODE_STR_REG (0x78 << OPCODE_SHIFT) +# define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT) +# define OPCODE_STRB_REG (0x7c << OPCODE_SHIFT) +# define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT) +# define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT) +# define OPCODE_TST_IMM (0x31 << OPCODE_SHIFT) +# define OPCODE_TST_REG (0x11 << OPCODE_SHIFT) -#define OPCODE_BFI 0xe7c00010 -#define OPCODE_BLX 0xe12fff30 -#define OPCODE_BX 0xe12fff10 -#define OPCODE_LDRH_IMM 0xe1d000b0 -#define OPCODE_LDRH_REG 0xe19000b0 -#define OPCODE_STRH_IMM 0xe1c000b0 -#define OPCODE_STRH_REG 0xe18000b0 -#define OPCODE_SXTB 0xe6af0070 -#define OPCODE_SXTH 0xe6bf0070 -#define OPCODE_UADD8 0xe6500f90 -#define OPCODE_UADD16 0xe6500f10 -#define OPCODE_USUB8 0xe6500ff0 -#define OPCODE_USUB16 0xe6500f70 -#define OPCODE_UXTB 0xe6ef0070 -#define OPCODE_UXTH 0xe6ff0070 -#define OPCODE_VABS_D 0xeeb00bc0 -#define OPCODE_VADD 0xee300b00 -#define OPCODE_VADD_I8 0xf2000800 -#define OPCODE_VADD_I16 0xf2100800 -#define OPCODE_VADD_I32 0xf2200800 -#define OPCODE_VADD_F32 0xf2000d00 -#define OPCODE_VAND_D 0xf2000110 -#define OPCODE_VBIC_D 0xf2100110 -#define OPCODE_VCEQ_F32 0xf2000e00 -#define OPCODE_VCEQ_I8 0xf3000810 -#define OPCODE_VCEQ_I16 0xf3100810 -#define OPCODE_VCEQ_I32 0xf3200810 -#define OPCODE_VCGE_F32 0xf3000e00 -#define OPCODE_VCGT_F32 0xf3200e00 -#define OPCODE_VCGT_S8 0xf2000300 -#define OPCODE_VCGT_S16 0xf2100300 -#define OPCODE_VCGT_S32 0xf2200300 -#define OPCODE_VCMP_D 0xeeb40b40 -#define OPCODE_VCVT_D_IS 0xeeb80bc0 -#define OPCODE_VCVT_D_S 0xeeb70ac0 -#define OPCODE_VCVT_F32_S32 0xf3bb0700 -#define OPCODE_VCVT_IS_D 0xeebd0bc0 -#define OPCODE_VCVT_S32_F32 0xf3bb0600 -#define OPCODE_VCVT_S_D 0xeeb70bc0 -#define OPCODE_VCVTR_IS_D 0xeebd0b40 -#define OPCODE_VDIV 0xee800b00 -#define OPCODE_VDIV_S 0xee800a00 -#define OPCODE_VDUP_32 0xf3b40c00 -#define OPCODE_VEOR_D 0xf3000110 -#define OPCODE_VLDR_D 0xed900b00 -#define OPCODE_VLDR_S 0xed900a00 -#define OPCODE_VMAX_F32 0xf200f00 -#define OPCODE_VMIN_F32 0xf220f00 -#define OPCODE_VMOV_32_S 0xee100a10 -#define OPCODE_VMOV_64_D 0xec500b10 -#define OPCODE_VMOV_D_64 0xec400b10 -#define OPCODE_VMOV_S_32 0xee000a10 -#define OPCODE_VMOV_D_D 0xeeb00b40 -#define OPCODE_VMOVN_I32 0xf3b60200 -#define OPCODE_VMOVN_I64 0xf3ba0200 -#define OPCODE_VMOV_F32_ONE 0xf2870f10 -#define OPCODE_VMRS_APSR 0xeef1fa10 -#define OPCODE_VMSR_FPSCR 0xeee10a10 -#define OPCODE_VMUL 0xee200b00 -#define OPCODE_VMUL_F32 0xf3000d10 -#define OPCODE_VMUL_S16 0xf2100910 -#define OPCODE_VMULL_S16 0xf2900c00 -#define OPCODE_VNEG_D 0xeeb10b40 -#define OPCODE_VORR_D 0xf2200110 -#define OPCODE_VPADDL_S16 0xf3b40200 -#define OPCODE_VPADDL_S32 0xf3b80200 -#define OPCODE_VPADDL_Q_S32 0xf3b80240 -#define OPCODE_VQADD_S8 0xf2000010 -#define OPCODE_VQADD_S16 0xf2100010 -#define OPCODE_VQADD_U8 0xf3000010 -#define OPCODE_VQADD_U16 0xf3100010 -#define OPCODE_VQMOVN_S16 0xf3b20280 -#define OPCODE_VQMOVN_S32 0xf3b60280 -#define OPCODE_VQMOVN_U16 0xf3b202c0 -#define OPCODE_VQSUB_S8 0xf2000210 -#define OPCODE_VQSUB_S16 0xf2100210 -#define OPCODE_VQSUB_U8 0xf3000210 -#define OPCODE_VQSUB_U16 0xf3100210 -#define OPCODE_VSHL_D_IMM_16 0xf2900510 -#define OPCODE_VSHL_D_IMM_32 0xf2a00510 -#define OPCODE_VSHL_D_IMM_64 0xf2800590 -#define OPCODE_VSHR_D_S16 0xf2900010 -#define OPCODE_VSHR_D_S32 0xf2a00010 -#define OPCODE_VSHR_D_S64 0xf2800090 -#define OPCODE_VSHR_D_U16 0xf3900010 -#define OPCODE_VSHR_D_U32 0xf3a00010 -#define OPCODE_VSHR_D_U64 0xf3800090 -#define OPCODE_VSHRN 0xf2800810 -#define OPCODE_VSQRT_D 0xeeb10bc0 -#define OPCODE_VSQRT_S 0xeeb10ac0 -#define OPCODE_VSTR_D 0xed800b00 -#define OPCODE_VSTR_S 0xed800a00 -#define OPCODE_VSUB 0xee300b40 -#define OPCODE_VSUB_I8 0xf3000800 -#define OPCODE_VSUB_I16 0xf3100800 -#define OPCODE_VSUB_I32 0xf3200800 -#define OPCODE_VSUB_F32 0xf3000d00 -#define OPCODE_VZIP_D8 0xf3b20180 -#define OPCODE_VZIP_D16 0xf3b60180 -#define OPCODE_VZIP_D32 0xf3ba0080 +# define OPCODE_BFI 0xe7c00010 +# define OPCODE_BLX 0xe12fff30 +# define OPCODE_BX 0xe12fff10 +# define OPCODE_LDRH_IMM 0xe1d000b0 +# define OPCODE_LDRH_REG 0xe19000b0 +# define OPCODE_STRH_IMM 0xe1c000b0 +# define OPCODE_STRH_REG 0xe18000b0 +# define OPCODE_SXTB 0xe6af0070 +# define OPCODE_SXTH 0xe6bf0070 +# define OPCODE_UADD8 0xe6500f90 +# define OPCODE_UADD16 0xe6500f10 +# define OPCODE_USUB8 0xe6500ff0 +# define OPCODE_USUB16 0xe6500f70 +# define OPCODE_UXTB 0xe6ef0070 +# define OPCODE_UXTH 0xe6ff0070 +# define OPCODE_VABS_D 0xeeb00bc0 +# define OPCODE_VADD 0xee300b00 +# define OPCODE_VADD_I8 0xf2000800 +# define OPCODE_VADD_I16 0xf2100800 +# define OPCODE_VADD_I32 0xf2200800 +# define OPCODE_VADD_F32 0xf2000d00 +# define OPCODE_VAND_D 0xf2000110 +# define OPCODE_VBIC_D 0xf2100110 +# define OPCODE_VCEQ_F32 0xf2000e00 +# define OPCODE_VCEQ_I8 0xf3000810 +# define OPCODE_VCEQ_I16 0xf3100810 +# define OPCODE_VCEQ_I32 0xf3200810 +# define OPCODE_VCGE_F32 0xf3000e00 +# define OPCODE_VCGT_F32 0xf3200e00 +# define OPCODE_VCGT_S8 0xf2000300 +# define OPCODE_VCGT_S16 0xf2100300 +# define OPCODE_VCGT_S32 0xf2200300 +# define OPCODE_VCMP_D 0xeeb40b40 +# define OPCODE_VCVT_D_IS 0xeeb80bc0 +# define OPCODE_VCVT_D_S 0xeeb70ac0 +# define OPCODE_VCVT_F32_S32 0xf3bb0700 +# define OPCODE_VCVT_IS_D 0xeebd0bc0 +# define OPCODE_VCVT_S32_F32 0xf3bb0600 +# define OPCODE_VCVT_S_D 0xeeb70bc0 +# define OPCODE_VCVTR_IS_D 0xeebd0b40 +# define OPCODE_VDIV 0xee800b00 +# define OPCODE_VDIV_S 0xee800a00 +# define OPCODE_VDUP_32 0xf3b40c00 +# define OPCODE_VEOR_D 0xf3000110 +# define OPCODE_VLDR_D 0xed900b00 +# define OPCODE_VLDR_S 0xed900a00 +# define OPCODE_VMAX_F32 0xf200f00 +# define OPCODE_VMIN_F32 0xf220f00 +# define OPCODE_VMOV_32_S 0xee100a10 +# define OPCODE_VMOV_64_D 0xec500b10 +# define OPCODE_VMOV_D_64 0xec400b10 +# define OPCODE_VMOV_S_32 0xee000a10 +# define OPCODE_VMOV_D_D 0xeeb00b40 +# define OPCODE_VMOVN_I32 0xf3b60200 +# define OPCODE_VMOVN_I64 0xf3ba0200 +# define OPCODE_VMOV_F32_ONE 0xf2870f10 +# define OPCODE_VMRS_APSR 0xeef1fa10 +# define OPCODE_VMSR_FPSCR 0xeee10a10 +# define OPCODE_VMUL 0xee200b00 +# define OPCODE_VMUL_F32 0xf3000d10 +# define OPCODE_VMUL_S16 0xf2100910 +# define OPCODE_VMULL_S16 0xf2900c00 +# define OPCODE_VNEG_D 0xeeb10b40 +# define OPCODE_VORR_D 0xf2200110 +# define OPCODE_VPADDL_S16 0xf3b40200 +# define OPCODE_VPADDL_S32 0xf3b80200 +# define OPCODE_VPADDL_Q_S32 0xf3b80240 +# define OPCODE_VQADD_S8 0xf2000010 +# define OPCODE_VQADD_S16 0xf2100010 +# define OPCODE_VQADD_U8 0xf3000010 +# define OPCODE_VQADD_U16 0xf3100010 +# define OPCODE_VQMOVN_S16 0xf3b20280 +# define OPCODE_VQMOVN_S32 0xf3b60280 +# define OPCODE_VQMOVN_U16 0xf3b202c0 +# define OPCODE_VQSUB_S8 0xf2000210 +# define OPCODE_VQSUB_S16 0xf2100210 +# define OPCODE_VQSUB_U8 0xf3000210 +# define OPCODE_VQSUB_U16 0xf3100210 +# define OPCODE_VSHL_D_IMM_16 0xf2900510 +# define OPCODE_VSHL_D_IMM_32 0xf2a00510 +# define OPCODE_VSHL_D_IMM_64 0xf2800590 +# define OPCODE_VSHR_D_S16 0xf2900010 +# define OPCODE_VSHR_D_S32 0xf2a00010 +# define OPCODE_VSHR_D_S64 0xf2800090 +# define OPCODE_VSHR_D_U16 0xf3900010 +# define OPCODE_VSHR_D_U32 0xf3a00010 +# define OPCODE_VSHR_D_U64 0xf3800090 +# define OPCODE_VSHRN 0xf2800810 +# define OPCODE_VSQRT_D 0xeeb10bc0 +# define OPCODE_VSQRT_S 0xeeb10ac0 +# define OPCODE_VSTR_D 0xed800b00 +# define OPCODE_VSTR_S 0xed800a00 +# define OPCODE_VSUB 0xee300b40 +# define OPCODE_VSUB_I8 0xf3000800 +# define OPCODE_VSUB_I16 0xf3100800 +# define OPCODE_VSUB_I32 0xf3200800 +# define OPCODE_VSUB_F32 0xf3000d00 +# define OPCODE_VZIP_D8 0xf3b20180 +# define OPCODE_VZIP_D16 0xf3b60180 +# define OPCODE_VZIP_D32 0xf3ba0080 -#define B_OFFSET(x) (((x) >> 2) & 0xffffff) +# define B_OFFSET(x) (((x) >> 2) & 0xffffff) -#define SHIFT_TYPE_SHIFT 5 -#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_SHIFT 5 +# define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT) +# define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT) -#define SHIFT_TYPE_IMM (0 << 4) -#define SHIFT_TYPE_REG (1 << 4) +# define SHIFT_TYPE_IMM (0 << 4) +# define SHIFT_TYPE_REG (1 << 4) -#define SHIFT_IMM_SHIFT 7 -#define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_ROR_IMM(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_IMM_SHIFT 7 +# define SHIFT_ASR_IMM(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) +# define SHIFT_ROR_IMM(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT)) -#define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) -#define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) -#define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) -#define SHIFT_ROR_REG(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_ASR_REG(x) (SHIFT_TYPE_ASR | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_LSL_REG(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_LSR_REG(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_REG | Rs(x)) +# define SHIFT_ROR_REG(x) (SHIFT_TYPE_ROR | SHIFT_TYPE_REG | Rs(x)) -#define BFI_lsb(lsb) ((lsb) << 7) -#define BFI_msb(msb) ((msb) << 16) +# define BFI_lsb(lsb) ((lsb) << 7) +# define BFI_msb(msb) ((msb) << 16) -#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) +# define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10) -#define MOVT_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) -#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4)) +# define MOVT_IMM(imm) (((imm) &0xfff) | (((imm) &0xf000) << 4)) +# define MOVW_IMM(imm) (((imm) &0xfff) | (((imm) &0xf000) << 4)) -#define LDRH_IMM(imm) (((imm) & 0xf) | (((imm) & 0xf0) << 4)) -#define STRH_IMM(imm) LDRH_IMM(imm) +# define LDRH_IMM(imm) (((imm) &0xf) | (((imm) &0xf0) << 4)) +# define STRH_IMM(imm) LDRH_IMM(imm) -#define VSHIFT_IMM(shift) ((shift) << 16) +# define VSHIFT_IMM(shift) ((shift) << 16) -#define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) +# define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) -#define VDUP_32_IMM(imm) ((imm) << 19) +# define VDUP_32_IMM(imm) ((imm) << 19) static void codegen_allocate_new_block(codeblock_t *block); -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(codeblock_t *block, uint32_t val) { - if (block_pos >= (BLOCK_MAX-4)) - codegen_allocate_new_block(block); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos >= (BLOCK_MAX - 4)) + codegen_allocate_new_block(block); + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static void codegen_allocate_new_block(codeblock_t *block) +static void +codegen_allocate_new_block(codeblock_t *block) { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - uint32_t offset = ((uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]) - 8; + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + uint32_t offset = ((uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos]) - 8; - /*Add a jump instruction to the new block*/ - *(uint32_t *)&block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset); + /*Add a jump instruction to the new block*/ + *(uint32_t *) &block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; } -static inline void codegen_alloc_4(codeblock_t *block) +static inline void +codegen_alloc_4(codeblock_t *block) { - if (block_pos >= (BLOCK_MAX-4)) - codegen_allocate_new_block(block); + if (block_pos >= (BLOCK_MAX - 4)) + codegen_allocate_new_block(block); } -void codegen_alloc(codeblock_t *block, int size) +void +codegen_alloc(codeblock_t *block, int size) { - if (block_pos >= (BLOCK_MAX-size)) - codegen_allocate_new_block(block); + if (block_pos >= (BLOCK_MAX - size)) + codegen_allocate_new_block(block); } -static inline uint32_t arm_data_offset(int offset) +static inline uint32_t +arm_data_offset(int offset) { - if (offset < -0xffc || offset > 0xffc) - fatal("arm_data_offset out of range - %i\n", offset); + if (offset < -0xffc || offset > 0xffc) + fatal("arm_data_offset out of range - %i\n", offset); - if (offset >= 0) - return offset | DATA_OFFSET_UP; - return (-offset) | DATA_OFFSET_DOWN; + if (offset >= 0) + return offset | DATA_OFFSET_UP; + return (-offset) | DATA_OFFSET_DOWN; } -static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) +static inline int +get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) { - int shift = 0; - if (!(imm_data & 0xffff)) - { - shift += 16; - imm_data >>= 16; - } - if (!(imm_data & 0xff)) - { - shift += 8; - imm_data >>= 8; - } - if (!(imm_data & 0xf)) - { - shift += 4; - imm_data >>= 4; - } - if (!(imm_data & 0x3)) - { - shift += 2; - imm_data >>= 2; - } - if (imm_data > 0xff) /*Note - should handle rotation round the word*/ - return 0; - *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); - return 1; + int shift = 0; + if (!(imm_data & 0xffff)) { + shift += 16; + imm_data >>= 16; + } + if (!(imm_data & 0xff)) { + shift += 8; + imm_data >>= 8; + } + if (!(imm_data & 0xf)) { + shift += 4; + imm_data >>= 4; + } + if (!(imm_data & 0x3)) { + shift += 2; + imm_data >>= 2; + } + if (imm_data > 0xff) /*Note - should handle rotation round the word*/ + return 0; + *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); + return 1; } -static inline int in_range(void *addr, void *base) +static inline int +in_range(void *addr, void *base) { - int diff = (uintptr_t)addr - (uintptr_t)base; + int diff = (uintptr_t) addr - (uintptr_t) base; - if (diff < -4095 || diff > 4095) - return 0; - return 1; + if (diff < -4095 || diff > 4095) + return 0; + return 1; } void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -//void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); +// void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); -void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else if (get_arm_imm(~imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else if (get_arm_imm(~imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_B(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_B(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - { - host_arm_MOV_IMM(block, REG_R3, dest_addr); - host_arm_BX(block, REG_R3); - } - else - codegen_addlong(block, COND_AL | OPCODE_B | B_OFFSET(offset)); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { + host_arm_MOV_IMM(block, REG_R3, dest_addr); + host_arm_BX(block, REG_R3); + } else + codegen_addlong(block, COND_AL | OPCODE_B | B_OFFSET(offset)); } -void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) +void +host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width) { - codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); + codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1)); } -void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else if (get_arm_imm(~imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_BIC_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else if (get_arm_imm(~imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_BIC_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_BL(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BL(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - { - host_arm_MOV_IMM(block, REG_R3, dest_addr); - host_arm_BLX(block, REG_R3); - } - else - codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { + host_arm_MOV_IMM(block, REG_R3, dest_addr); + host_arm_BLX(block, REG_R3); + } else + codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); } -void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - { - host_arm_MOV_IMM(block, REG_R1, dest_addr); - host_arm_BLX(block, REG_R1); - } - else - codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) { + host_arm_MOV_IMM(block, REG_R1, dest_addr); + host_arm_BLX(block, REG_R1); + } else + codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset)); } -void host_arm_BLX(codeblock_t *block, int addr_reg) +void +host_arm_BLX(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); } -uint32_t *host_arm_BCC_(codeblock_t *block) +uint32_t * +host_arm_BCC_(codeblock_t *block) { - codegen_addlong(block, COND_CC | OPCODE_B); + codegen_addlong(block, COND_CC | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BCS_(codeblock_t *block) +uint32_t * +host_arm_BCS_(codeblock_t *block) { - codegen_addlong(block, COND_CS | OPCODE_B); + codegen_addlong(block, COND_CS | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BEQ_(codeblock_t *block) +uint32_t * +host_arm_BEQ_(codeblock_t *block) { - codegen_addlong(block, COND_EQ | OPCODE_B); + codegen_addlong(block, COND_EQ | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BGE_(codeblock_t *block) +uint32_t * +host_arm_BGE_(codeblock_t *block) { - codegen_addlong(block, COND_GE | OPCODE_B); + codegen_addlong(block, COND_GE | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BGT_(codeblock_t *block) +uint32_t * +host_arm_BGT_(codeblock_t *block) { - codegen_addlong(block, COND_GT | OPCODE_B); + codegen_addlong(block, COND_GT | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BHI_(codeblock_t *block) +uint32_t * +host_arm_BHI_(codeblock_t *block) { - codegen_addlong(block, COND_HI | OPCODE_B); + codegen_addlong(block, COND_HI | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BLE_(codeblock_t *block) +uint32_t * +host_arm_BLE_(codeblock_t *block) { - codegen_addlong(block, COND_LE | OPCODE_B); + codegen_addlong(block, COND_LE | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BLS_(codeblock_t *block) +uint32_t * +host_arm_BLS_(codeblock_t *block) { - codegen_addlong(block, COND_LS | OPCODE_B); + codegen_addlong(block, COND_LS | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BLT_(codeblock_t *block) +uint32_t * +host_arm_BLT_(codeblock_t *block) { - codegen_addlong(block, COND_LT | OPCODE_B); + codegen_addlong(block, COND_LT | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BMI_(codeblock_t *block) +uint32_t * +host_arm_BMI_(codeblock_t *block) { - codegen_addlong(block, COND_MI | OPCODE_B); + codegen_addlong(block, COND_MI | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BNE_(codeblock_t *block) +uint32_t * +host_arm_BNE_(codeblock_t *block) { - codegen_addlong(block, COND_NE | OPCODE_B); + codegen_addlong(block, COND_NE | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BPL_(codeblock_t *block) +uint32_t * +host_arm_BPL_(codeblock_t *block) { - codegen_addlong(block, COND_PL | OPCODE_B); + codegen_addlong(block, COND_PL | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BVC_(codeblock_t *block) +uint32_t * +host_arm_BVC_(codeblock_t *block) { - codegen_addlong(block, COND_VC | OPCODE_B); + codegen_addlong(block, COND_VC | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -uint32_t *host_arm_BVS_(codeblock_t *block) +uint32_t * +host_arm_BVS_(codeblock_t *block) { - codegen_addlong(block, COND_VS | OPCODE_B); + codegen_addlong(block, COND_VS | OPCODE_B); - return (uint32_t *)&block_write_data[block_pos - 4]; + return (uint32_t *) &block_write_data[block_pos - 4]; } -void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset); - codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset)); + codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset)); } -void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) +void +host_arm_BNE(codeblock_t *block, uintptr_t dest_addr) { - uint32_t offset; + uint32_t offset; - codegen_alloc_4(block); - offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8; + codegen_alloc_4(block); + offset = (dest_addr - (uintptr_t) &block_write_data[block_pos]) - 8; - if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) - fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); + if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000) + fatal("host_arm_BNE - out of range %08x %i\n", offset, offset); - codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); + codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset)); } -void host_arm_BX(codeblock_t *block, int addr_reg) +void +host_arm_BX(codeblock_t *block, int addr_reg) { - codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); + codegen_addlong(block, OPCODE_BLX | Rm(addr_reg)); } -void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) +void +host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_CMP_IMM(block, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_CMN_IMM | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_CMP_IMM(block, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_CMN_IMM | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0); + } } -void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) +void +host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_CMN_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_CMN_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm) +void +host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_CMN_IMM(block, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_CMP_IMM | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_CMN_IMM(block, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_CMP_IMM | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0); + } } -void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) +void +host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_CMP_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_CMP_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +void +host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { - codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); + codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask); } -void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); } -void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDR_IMM_POST | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDR_IMM_POST | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); } -void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_LDR_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_LDR_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_LDRB_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_arm_LDRB_ABS(codeblock_t *block, int dst_reg, void *p) { - if (in_range(p, &cpu_state)) - host_arm_LDRB_IMM(block, dst_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("LDRB_ABS - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_LDRB_IMM(block, dst_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("LDRB_ABS - not in range\n"); } -void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDRB_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDRB_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset)); } -void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_LDRH_IMM | Rn(addr_reg) | Rd(dst_reg) | LDRH_IMM(offset)); + codegen_addlong(block, COND_AL | OPCODE_LDRH_IMM | Rn(addr_reg) | Rd(dst_reg) | LDRH_IMM(offset)); } -void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg) +void +host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg) { - codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg)); + codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg)); } -void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) +void +host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); - } - else - { - host_arm_MOVW_IMM(block, dst_reg, imm & 0xffff); - if (imm >> 16) - host_arm_MOVT_IMM(block, dst_reg, imm >> 16); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm); + } else { + host_arm_MOVW_IMM(block, dst_reg, imm & 0xffff); + if (imm >> 16) + host_arm_MOVT_IMM(block, dst_reg, imm >> 16); + } } -void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_IMM(shift)); } -void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ASR_REG(shift_reg)); } -void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_REG(shift_reg)); } -void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift)); } -void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_REG(shift_reg)); } -void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_IMM(shift)); } -void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) +void +host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg) { - codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_REG(shift_reg)); + codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_ROR_REG(shift_reg)); } -void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +void +host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { - codegen_addlong(block, COND_AL | OPCODE_MOVT_IMM | Rd(dst_reg) | MOVT_IMM(imm)); + codegen_addlong(block, COND_AL | OPCODE_MOVT_IMM | Rd(dst_reg) | MOVT_IMM(imm)); } -void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) +void +host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm) { - codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); + codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm)); } -void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, cond | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_ORR_REG_LSL_cond(block, cond, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, cond | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_ORR_REG_LSL_cond(block, cond, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, cond | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_RSB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_RSB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_RSB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_RSB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) +void +host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask) { - codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); + codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask); } -void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +void +host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); } -void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset) +void +host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STR_IMM_WB | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_STR_IMM_WB | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); } -void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_STR_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_STR_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) +void +host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); + codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset)); } -void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) +void +host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift) { - codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift)); } -void host_arm_STRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) +void +host_arm_STRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset) { - codegen_addlong(block, COND_AL | OPCODE_STRH_IMM | Rn(addr_reg) | Rd(dst_reg) | STRH_IMM(offset)); + codegen_addlong(block, COND_AL | OPCODE_STRH_IMM | Rn(addr_reg) | Rd(dst_reg) | STRH_IMM(offset)); } -void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg) +void +host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg) { - codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg)); + codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg)); } -void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) +void +host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if ((int32_t)imm < 0 && imm != 0x80000000) - { - host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm); - } - else if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); - } + if ((int32_t) imm < 0 && imm != 0x80000000) { + host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t) imm); + } else if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0); + } } -void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift)); } -void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) +void +host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift) { - codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); + codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift)); } -void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_SXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_SXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_SXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_SXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) +void +host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm) { - uint32_t arm_imm; + uint32_t arm_imm; - if (get_arm_imm(imm, &arm_imm)) - { - codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm); - } - else - { - host_arm_MOV_IMM(block, REG_TEMP, imm); - host_arm_TST_REG(block, src_reg, REG_TEMP); - } + if (get_arm_imm(imm, &arm_imm)) { + codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm); + } else { + host_arm_MOV_IMM(block, REG_TEMP, imm); + host_arm_TST_REG(block, src_reg, REG_TEMP); + } } -void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) +void +host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2) { - codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); + codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2)); } -void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +void +host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { - codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); + codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b)); } -void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) +void +host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate) { - codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); + codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate)); } -void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VABS_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VABS_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VADD_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VADD_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VADD_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VADD_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VADD_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VADD_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VAND_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VAND_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VBIC_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VBIC_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) +void +host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m)); } -void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGE_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGE_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VCGT_S32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VCGT_S32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_F32_S32 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_F32_S32 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_S32_F32 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_S32_F32 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VCVTR_IS_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VCVTR_IS_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VDIV_S | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VDIV_S | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm) +void +host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm) { - codegen_addlong(block, COND_AL | OPCODE_VDUP_32 | Rd(dst_reg) | Rm(src_reg_m) | VDUP_32_IMM(imm)); + codegen_addlong(block, COND_AL | OPCODE_VDUP_32 | Rd(dst_reg) | Rm(src_reg_m) | VDUP_32_IMM(imm)); } -void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VLDR_D bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VLDR_D | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VLDR_D bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR_D | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset) +void +host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VLDR_S bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VLDR_S | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VLDR_S bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VLDR_S | Rd(dest_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_32_S | Rt(dest_reg) | Vn(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_32_S | Rt(dest_reg) | Vn(src_reg)); } -void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg) +void +host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_64_D | Rt(dest_reg_low) | Rt2(dest_reg_high) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_64_D | Rt(dest_reg_low) | Rt2(dest_reg_high) | Vm(src_reg)); } -void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high) +void +host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_D_64 | Vm(dest_reg) | Rt(src_reg_low) | Rt2(src_reg_high)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_D_64 | Vm(dest_reg) | Rt(src_reg_low) | Rt2(src_reg_high)); } -void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_S_32 | Vn(dest_reg) | Rt(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_S_32 | Vn(dest_reg) | Rt(src_reg)); } -void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, OPCODE_VMOVN_I32 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VMOVN_I32 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg) +void +host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(dst_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(dst_reg)); } -void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) +void +host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); } -void host_arm_VMRS_APSR(codeblock_t *block) +void +host_arm_VMRS_APSR(codeblock_t *block) { - codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); + codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR); } -void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMAX_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMAX_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMIN_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMIN_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VMUL_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VMUL_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VMULL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VMULL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VMULL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VMULL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VNEG_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VNEG_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VPADDL_S32 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VPADDL_S32 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VPADDL_Q_S32 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VPADDL_Q_S32 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQADD_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQADD_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_U8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VQMOVN_S16 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VQMOVN_S16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VQMOVN_S32 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VQMOVN_S32 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) { - codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); + codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHL_D_IMM_16(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 15) - fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + if (shift > 15) + fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHL_D_IMM_32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 31) - fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + if (shift > 31) + fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHL_D_IMM_64(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 63) - fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); + if (shift > 63) + fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); } -void host_arm_VSHR_D_S16(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_S16(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 15) - fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHR_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); + if (shift > 15) + fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16 - shift)); } -void host_arm_VSHR_D_S32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_S32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 31) - fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHR_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); + if (shift > 31) + fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32 - shift)); } -void host_arm_VSHR_D_S64(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_S64(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 63) - fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHR_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); + if (shift > 63) + fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64 - shift)); } -void host_arm_VSHR_D_U16(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_U16(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 15) - fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); - codegen_addlong(block, OPCODE_VSHR_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); + if (shift > 15) + fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16 - shift)); } -void host_arm_VSHR_D_U32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_U32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 31) - fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); - codegen_addlong(block, OPCODE_VSHR_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); + if (shift > 31) + fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32 - shift)); } -void host_arm_VSHR_D_U64(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHR_D_U64(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 63) - fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); - codegen_addlong(block, OPCODE_VSHR_D_U64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); + if (shift > 63) + fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_D_U64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64 - shift)); } -void host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) +void +host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) { - if (shift > 16) - fatal("host_arm_VSHRN_32 : shift > 16\n"); - codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16-shift)); + if (shift > 16) + fatal("host_arm_VSHRN_32 : shift > 16\n"); + codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16 - shift)); } -void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg) +void +host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg) { - codegen_addlong(block, COND_AL | OPCODE_VSQRT_S | Vd(dest_reg) | Vm(src_reg)); + codegen_addlong(block, COND_AL | OPCODE_VSQRT_S | Vd(dest_reg) | Vm(src_reg)); } -void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) +void +host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VSTR_D bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VSTR_D | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VSTR_D bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR_D | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset) +void +host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset) { - if ((offset > 1020) || (offset & 3)) - fatal("VSTR_S bad offset %i\n", offset); - codegen_addlong(block, COND_AL | OPCODE_VSTR_S | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); + if ((offset > 1020) || (offset & 3)) + fatal("VSTR_S bad offset %i\n", offset); + codegen_addlong(block, COND_AL | OPCODE_VSTR_S | Rd(src_reg) | Rn(base_reg) | (offset >> 2)); } -void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, COND_AL | OPCODE_VSUB_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, COND_AL | OPCODE_VSUB_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VSUB_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VSUB_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VSUB_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VSUB_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +void +host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { - codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); + codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } -void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg) +void +host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg) { - codegen_addlong(block, OPCODE_VZIP_D8 | Vd(d_reg) | Vm(m_reg)); + codegen_addlong(block, OPCODE_VZIP_D8 | Vd(d_reg) | Vm(m_reg)); } -void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) +void +host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) { - codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); + codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); } -void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg) +void +host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg) { - codegen_addlong(block, OPCODE_VZIP_D32 | Vd(d_reg) | Vm(m_reg)); + codegen_addlong(block, OPCODE_VZIP_D32 | Vd(d_reg) | Vm(m_reg)); } #endif diff --git a/src/codegen_new/codegen_backend_arm_ops.h b/src/codegen_new/codegen_backend_arm_ops.h index 7627f51a7..271fbffbd 100644 --- a/src/codegen_new/codegen_backend_arm_ops.h +++ b/src/codegen_new/codegen_backend_arm_ops.h @@ -1,19 +1,19 @@ #define COND_SHIFT 28 -#define COND_EQ (0x0 << COND_SHIFT) -#define COND_NE (0x1 << COND_SHIFT) -#define COND_CS (0x2 << COND_SHIFT) -#define COND_CC (0x3 << COND_SHIFT) -#define COND_MI (0x4 << COND_SHIFT) -#define COND_PL (0x5 << COND_SHIFT) -#define COND_VS (0x6 << COND_SHIFT) -#define COND_VC (0x7 << COND_SHIFT) -#define COND_HI (0x8 << COND_SHIFT) -#define COND_LS (0x9 << COND_SHIFT) -#define COND_GE (0xa << COND_SHIFT) -#define COND_LT (0xb << COND_SHIFT) -#define COND_GT (0xc << COND_SHIFT) -#define COND_LE (0xd << COND_SHIFT) -#define COND_AL (0xe << COND_SHIFT) +#define COND_EQ (0x0 << COND_SHIFT) +#define COND_NE (0x1 << COND_SHIFT) +#define COND_CS (0x2 << COND_SHIFT) +#define COND_CC (0x3 << COND_SHIFT) +#define COND_MI (0x4 << COND_SHIFT) +#define COND_PL (0x5 << COND_SHIFT) +#define COND_VS (0x6 << COND_SHIFT) +#define COND_VC (0x7 << COND_SHIFT) +#define COND_HI (0x8 << COND_SHIFT) +#define COND_LS (0x9 << COND_SHIFT) +#define COND_GE (0xa << COND_SHIFT) +#define COND_LT (0xb << COND_SHIFT) +#define COND_GT (0xc << COND_SHIFT) +#define COND_LE (0xd << COND_SHIFT) +#define COND_AL (0xe << COND_SHIFT) void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); #define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0) @@ -101,12 +101,12 @@ void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm); void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift); -#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm) +#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm) #define host_arm_ORR_REG_LSL(block, dst_reg, src_reg_a, src_reg_b, shift) host_arm_ORR_REG_LSL_cond(block, COND_AL, dst_reg, src_reg_a, src_reg_b, shift) -#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm) -#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) -#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) +#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm) +#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm) +#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm) void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm); void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift); diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c index 8b0990016..4cc0ff38d 100644 --- a/src/codegen_new/codegen_backend_arm_uops.c +++ b/src/codegen_new/codegen_backend_arm_uops.c @@ -1,3502 +1,3375 @@ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "x86.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_arm_defs.h" -#include "codegen_backend_arm_ops.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x87.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_arm_defs.h" +# include "codegen_backend_arm_ops.h" +# include "codegen_ir_defs.h" -static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) +static inline int +get_arm_imm(uint32_t imm_data, uint32_t *arm_imm) { - int shift = 0; - if (!(imm_data & 0xffff)) - { - shift += 16; - imm_data >>= 16; - } - if (!(imm_data & 0xff)) - { - shift += 8; - imm_data >>= 8; - } - if (!(imm_data & 0xf)) - { - shift += 4; - imm_data >>= 4; - } - if (!(imm_data & 0x3)) - { - shift += 2; - imm_data >>= 2; - } - if (imm_data > 0xff) /*Note - should handle rotation round the word*/ - return 0; - *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); - return 1; -} - -static inline int in_range(void *addr, void *base) -{ - int diff = (uintptr_t)addr - (uintptr_t)base; - - if (diff < -4095 || diff > 4095) - return 0; - return 1; -} - -static inline int in_range_h(void *addr, void *base) -{ - int diff = (uintptr_t)addr - (uintptr_t)base; - - if (diff < 0 || diff > 255) - return 0; - return 1; -} - -void host_arm_call(codeblock_t *block, void *dst_addr) -{ - host_arm_MOV_IMM(block, REG_R3, (uintptr_t)dst_addr); - host_arm_BLX(block, REG_R3); -} - -void host_arm_nop(codeblock_t *block) -{ - host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); -} - -#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0xf) - -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) - -static int codegen_ADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, 8); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_AND_IMM(block, REG_TEMP, src_reg_b, 0x0000ff00); - host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); - } - else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - + int shift = 0; + if (!(imm_data & 0xffff)) { + shift += 16; + imm_data >>= 16; + } + if (!(imm_data & 0xff)) { + shift += 8; + imm_data >>= 8; + } + if (!(imm_data & 0xf)) { + shift += 4; + imm_data >>= 4; + } + if (!(imm_data & 0x3)) { + shift += 2; + imm_data >>= 2; + } + if (imm_data > 0xff) /*Note - should handle rotation round the word*/ return 0; + *arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8); + return 1; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) + +static inline int +in_range(void *addr, void *base) { -// host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); -// return 0; - - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) - { - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data << 8); - host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); - } - else - fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + int diff = (uintptr_t) addr - (uintptr_t) base; + if (diff < -4095 || diff > 4095) return 0; - + return 1; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) + +static inline int +in_range_h(void *addr, void *base) { - host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + int diff = (uintptr_t) addr - (uintptr_t) base; + + if (diff < 0 || diff > 255) return 0; + return 1; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +void +host_arm_call(codeblock_t *block, void *dst_addr) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VAND_D(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_AND_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); - host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 24); - host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); - host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 8); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); - host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 0); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); - host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_ANDN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VBIC_D(block, dest_reg, src_reg_b, src_reg_a); - } - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; + host_arm_MOV_IMM(block, REG_R3, (uintptr_t) dst_addr); + host_arm_BLX(block, REG_R3); } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +void +host_arm_nop(codeblock_t *block) { - host_arm_call(block, uop->p); - - return 0; + host_arm_MOV_REG_LSL(block, REG_R0, REG_R0, 0); } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); +# define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0xf) - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); - host_arm_call(block, uop->p); +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) + +static int +codegen_ADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_ADD_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_ADD_REG(block, REG_TEMP, src_reg_a, src_reg_b); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_ADD_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, 8); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_AND_IMM(block, REG_TEMP, src_reg_b, 0x0000ff00); + host_arm_UADD8(block, dest_reg, src_reg_a, REG_TEMP); + } else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +{ + // host_arm_ADD_IMM(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->imm_data); + // return 0; + + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_ADD_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_ADD_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && src_reg == dest_reg) { + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data << 8); + host_arm_UADD8(block, dest_reg, src_reg, REG_TEMP); + } else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +{ + host_arm_ADD_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); + return 0; +} + +static int +codegen_AND(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VAND_D(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_AND_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 24); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 16); + host_arm_BIC_REG_LSR(block, dest_reg, src_reg_a, REG_TEMP, 24); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_MVN_REG_LSL(block, REG_TEMP, src_reg_b, 0); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 0x0000ff00); + host_arm_BIC_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_AND_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_AND_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffff0000); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm_AND_IMM(block, dest_reg, src_reg, uop->imm_data | 0xffffff00); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm_AND_IMM(block, dest_reg, src_reg, (uop->imm_data << 8) | 0xffff00ff); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_AND_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VBIC_D(block, dest_reg, src_reg_b, src_reg_a); + } else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm_call(block, uop->p); + + return 0; +} + +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); + host_arm_call(block, uop->p); + host_arm_MOV_REG(block, dest_reg, REG_R0); + + return 0; +} + +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +{ + host_arm_call(block, uop->p); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} + +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); + host_arm_BEQ(block, (uintptr_t) uop->p); + + return 0; +} + +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_arm_CMP_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); + } else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} + +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); + + jump_p = host_arm_BCC_(block); + *jump_p |= ((((uintptr_t) uop->p - (uintptr_t) jump_p) - 8) & 0x3fffffc) >> 2; + + return 0; +} +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + + jump_p = host_arm_BHI_(block); + *jump_p |= ((((uintptr_t) uop->p - (uintptr_t) jump_p) - 8) & 0x3fffffc) >> 2; + + return 0; +} + +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BCS_(block); + + return 0; +} +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BHI_(block); + + return 0; +} +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BGE_(block); + + return 0; +} +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BGT_(block); + + return 0; +} +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BVC_(block); + + return 0; +} +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BNE_(block); + + return 0; +} +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BCC_(block); + + return 0; +} +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLS_(block); + + return 0; +} +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLT_(block); + + return 0; +} +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BLE_(block); + + return 0; +} +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BVS_(block); + + return 0; +} +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_CMP_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); + host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); + } else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); + + uop->p = host_arm_BEQ_(block); + + return 0; +} + +static int +codegen_FABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VABS_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VNEG_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VSQRT_D(block, dest_reg, src_reg_a); + } else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_arm_VSUB_D(block, REG_D_TEMP, REG_D_TEMP, REG_D_TEMP); + host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); + host_arm_MOV_IMM(block, dest_reg, 0); + host_arm_VMRS_APSR(block); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + } else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VADD_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VCMP_D(block, src_reg_a, src_reg_b); + host_arm_MOV_IMM(block, dest_reg, 0); + host_arm_VMRS_APSR(block); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + } else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VDIV_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VMUL_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_arm_VSUB_D(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_FP_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t) codegen_exit_rout); + + *branch_ptr |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_ptr) - 8) & 0x3fffffc) >> 2; + + return 0; +} +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_ptr; + + if (!in_range(&cr0, &cpu_state)) + fatal("codegen_MMX_ENTER - out of range\n"); + + host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cr0 - (uintptr_t) &cpu_state); + host_arm_TST_IMM(block, REG_TEMP, 0xc); + branch_ptr = host_arm_BEQ_(block); + + host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.oldpc - (uintptr_t) &cpu_state); + host_arm_MOV_IMM(block, REG_ARG0, 7); + host_arm_call(block, x86_int); + host_arm_B(block, (uintptr_t) codegen_exit_rout); + + *branch_ptr |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_ptr) - 8) & 0x3fffffc) >> 2; + + host_arm_MOV_IMM(block, REG_TEMP, 0x01010101); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[0] - (uintptr_t) &cpu_state); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[4] - (uintptr_t) &cpu_state); + host_arm_MOV_IMM(block, REG_TEMP, 0); + host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); + host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.ismmx - (uintptr_t) &cpu_state); + + return 0; +} + +static int +codegen_JMP(codeblock_t *block, uop_t *uop) +{ + host_arm_B(block, (uintptr_t) uop->p); + + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_ARG0, src_reg, 0); + } else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + + return 0; +} +static int +codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); + return 0; +} +static int +codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); + return 0; +} +static int +codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); + return 0; +} + +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); + host_arm_UXTH(block, REG_ARG0, src_reg, 0); + host_arm_MOV_IMM(block, REG_ARG1, (uint32_t) uop->p); + host_arm_call(block, loadseg); + host_arm_TST_REG(block, REG_R0, REG_R0); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_long); + } else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 16); + } else if (REG_IS_L(dest_size)) { host_arm_MOV_REG(block, dest_reg, REG_R0); + } - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) { - host_arm_call(block, uop->p); - host_arm_TST_REG(block, REG_R0, REG_R0); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - return 0; + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_arm_BL(block, (uintptr_t) codegen_mem_load_quad); + } else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 8); + } else if (REG_IS_BH(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 8, 8); + } else if (REG_IS_W(dest_size)) { + host_arm_BFI(block, dest_reg, REG_R0, 0, 16); + } else if (REG_IS_L(dest_size)) { + host_arm_MOV_REG(block, dest_reg, REG_R0); + } else if (REG_IS_Q(dest_size)) { + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } + + return 0; +} +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_load_single); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + host_arm_VCVT_D_S(block, dest_reg, REG_D_TEMP); + + return 0; +} +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_load_double); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size)) - { - host_arm_CMP_IMM(block, src_reg, uop->imm_data); - } - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); - host_arm_BEQ(block, (uintptr_t)uop->p); + host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_long); + } else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (REG_IS_L(src_size)) - { - host_arm_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + if (REG_IS_B(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + } else if (REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_arm_MOV_REG(block, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_quad); + } else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - uop->p = host_arm_BNE_(block); - - return 0; -} -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_arm_CMP_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_CMP_IMM(block, REG_TEMP, uop->imm_data); - } - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BEQ_(block); - - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_store_byte); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - jump_p = host_arm_BCC_(block); - *jump_p |= ((((uintptr_t)uop->p - (uintptr_t)jump_p) - 8) & 0x3fffffc) >> 2; - - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_store_word); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); - jump_p = host_arm_BHI_(block); - *jump_p |= ((((uintptr_t)uop->p - (uintptr_t)jump_p) - 8) & 0x3fffffc) >> 2; + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - return 0; + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + host_arm_MOV_IMM(block, REG_R1, uop->imm_data); + host_arm_BL(block, (uintptr_t) codegen_mem_store_long); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_VCVT_S_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_single); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); + + host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); + if (uop->imm_data) + host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_mem_store_double); + host_arm_TST_REG(block, REG_R1, REG_R1); + host_arm_BNE(block, (uintptr_t) codegen_exit_rout); + + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_MOV(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) { + host_arm_BFI(block, dest_reg, src_reg, 8, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_arm_VMOV_D_D(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_arm_VMOV_D_D(block, dest_reg, src_reg); + } else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - uop->p = host_arm_BCS_(block); - - return 0; -} -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BHI_(block); - - return 0; -} -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BGE_(block); - - return 0; -} -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BGT_(block); - - return 0; -} -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BVC_(block); - - return 0; -} -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BNE_(block); - - return 0; -} -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BCC_(block); - - return 0; -} -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BLS_(block); - - return 0; -} -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BLT_(block); - - return 0; -} -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BLE_(block); - - return 0; -} -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BVS_(block); - - return 0; -} -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_CMP_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 16); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 16); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg_a, 24); - host_arm_CMP_REG_LSL(block, REG_TEMP, src_reg_b, 24); - } - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); - - uop->p = host_arm_BEQ_(block); - - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VABS_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size)) { + host_arm_MOV_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_arm_MOVW_IMM(block, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size)) { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x000000ff); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size)) { + host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x0000ff00); + host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data << 8); + } else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); - return 0; + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + host_arm_MOV_IMM(block, uop->dest_reg_a_real, (uintptr_t) uop->p); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VNEG_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VSQRT_D(block, dest_reg, src_reg_a); - } - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_FTST(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_arm_VSUB_D(block, REG_D_TEMP, REG_D_TEMP, REG_D_TEMP); - host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); - host_arm_MOV_IMM(block, dest_reg, 0); - host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0|C2|C3); - } - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VADD_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm_SXTB(block, dest_reg, src_reg, 0); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm_SXTB(block, dest_reg, src_reg, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm_SXTH(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_arm_SXTB(block, REG_TEMP, src_reg, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm_SXTB(block, REG_TEMP, src_reg, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_FCOM(codeblock_t *block, uop_t *uop) +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VCMP_D(block, src_reg_a, src_reg_b); - host_arm_MOV_IMM(block, dest_reg, 0); - host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0|C2|C3); - } - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_FDIV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VDIV_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_FMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VMUL_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_FSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_arm_VSUB_D(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_ptr; - - if (!in_range(&cr0, &cpu_state)) - fatal("codegen_FP_ENTER - out of range\n"); - - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm_BEQ_(block); - - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm_MOV_IMM(block, REG_ARG0, 7); - host_arm_call(block, x86_int); - host_arm_B(block, (uintptr_t)codegen_exit_rout); - - *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; - - return 0; -} -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_ptr; - - if (!in_range(&cr0, &cpu_state)) - fatal("codegen_MMX_ENTER - out of range\n"); - - host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state); - host_arm_TST_IMM(block, REG_TEMP, 0xc); - branch_ptr = host_arm_BEQ_(block); - - host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state); - host_arm_MOV_IMM(block, REG_ARG0, 7); - host_arm_call(block, x86_int); - host_arm_B(block, (uintptr_t)codegen_exit_rout); - - *branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2; - - host_arm_MOV_IMM(block, REG_TEMP, 0x01010101); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state); + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { host_arm_MOV_IMM(block, REG_TEMP, 0); - host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state); - host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state); - - return 0; -} - -static int codegen_JMP(codeblock_t *block, uop_t *uop) -{ - host_arm_B(block, (uintptr_t)uop->p); - - return 0; -} - -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_ARG0, src_reg, 0); + host_arm_VMOV_D_64(block, dest_reg, src_reg, REG_TEMP); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_arm_VMOV_32_S(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, dest_reg, src_reg, 0); + } else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, dest_reg, src_reg, 8); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, dest_reg, src_reg, 0); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + if (src_reg == dest_reg) + host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); + else { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } + } else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); + host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static double +int64_to_double(int64_t a) +{ + return (double) a; +} +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_arm_VMOV_S_32(block, REG_D_TEMP, src_reg); + host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_arm_SXTH(block, REG_TEMP, src_reg, 0); + host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); + host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + /*ARMv7 has no instructions to convert a 64-bit integer to a double. + For simplicity, call a C function and let the compiler do it.*/ + host_arm_VMOV_64_D(block, REG_R0, REG_R1, src_reg); + host_arm_BL(block, (uintptr_t) int64_to_double); /*Input - R0/R1, Output - D0*/ + host_arm_VMOV_D_D(block, dest_reg, REG_D0); + } else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_fp_round); + host_arm_VMOV_32_S(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); + host_arm_BL(block, (uintptr_t) codegen_fp_round); + host_arm_VMOV_32_S(block, REG_TEMP, REG_D_TEMP); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int64_t +x87_fround64(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 int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_arm_VMOV_D_D(block, dest_reg, src_64_reg); + host_arm_TST_IMM(block, tag_reg, TAG_UINT64); + branch_offset = host_arm_BNE_(block); + + /*VFP/NEON has no instructions to convert a float to 64-bit integer, + so call out to C.*/ + host_arm_VMOV_D_D(block, REG_D0, src_reg); + host_arm_call(block, x87_fround64); + host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); + + *branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2; + } else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm_LDR_IMM(block, dest_reg, REG_TEMP, 0); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm_LDRB_IMM(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size)) { + host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t) uop->p); + if (REG_IS_L(dest_size)) { + host_arm_LDRH_IMM(block, dest_reg, REG_TEMP, 0); + } else if (REG_IS_W(dest_size)) { + host_arm_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VORR_D(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_ORR_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S16(block, REG_D_TEMP, REG_Q_TEMP_2); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S32(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S32(block, REG_D_TEMP, REG_Q_TEMP_2); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_U16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_U16(block, REG_D_TEMP, REG_Q_TEMP_2); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_I8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_I16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_I32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_S8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_U8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQADD_U16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_I8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_I16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_I32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_S8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_S32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm_VCVT_S32_F32(block, dest_reg, src_reg_a); + } else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VADD_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCEQ_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGE_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VCGT_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMAX_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMIN_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMUL_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRECPE/VRECPS)*/ + host_arm_VMOV_F32_ONE(block, REG_D_TEMP); + host_arm_VDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); + host_arm_VDUP_32(block, dest_reg, dest_reg, 0); + } else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ + host_arm_VSQRT_S(block, REG_D_TEMP, src_reg_a); + host_arm_VMOV_F32_ONE(block, REG_D_TEMP); + host_arm_VDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); + host_arm_VDUP_32(block, dest_reg, dest_reg, 0); + } else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_F32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_arm_VCVT_F32_S32(block, dest_reg, src_reg_a); + } else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); + + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VPADDL_Q_S32(block, REG_Q_TEMP, REG_Q_TEMP); + host_arm_VMOVN_I64(block, dest_reg, REG_Q_TEMP); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VSHRN_32(block, dest_reg, REG_Q_TEMP, 16); + } else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); + host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) { - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); - return 0; -} -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) -{ - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); - return 0; -} -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) -{ - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); - return 0; -} + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG1, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG2, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, REG_ARG3, uop->imm_data); - return 0; -} - -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); - host_arm_UXTH(block, REG_ARG0, src_reg, 0); - host_arm_MOV_IMM(block, REG_ARG1, (uint32_t)uop->p); - host_arm_call(block, loadseg); - host_arm_TST_REG(block, REG_R0, REG_R0); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_long); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm_MOV_REG(block, dest_reg, REG_R0); - } + host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_arm_BL(block, (uintptr_t)codegen_mem_load_quad); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 8); - } - else if (REG_IS_BH(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 8, 8); - } - else if (REG_IS_W(dest_size)) - { - host_arm_BFI(block, dest_reg, REG_R0, 0, 16); - } - else if (REG_IS_L(dest_size)) - { - host_arm_MOV_REG(block, dest_reg, REG_R0); - } - else if (REG_IS_Q(dest_size)) - { - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } + host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_load_single); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - host_arm_VCVT_D_S(block, dest_reg, REG_D_TEMP); - - return 0; -} -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_load_double); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - - return 0; -} - -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - - host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_long); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - } - else if (REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_arm_MOV_REG(block, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_quad); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); + host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } - -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_store_byte); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_store_word); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - host_arm_MOV_IMM(block, REG_R1, uop->imm_data); - host_arm_BL(block, (uintptr_t)codegen_mem_store_long); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_VCVT_S_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_single); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real); - - host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg); - if (uop->imm_data) - host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data); - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_mem_store_double); - host_arm_TST_REG(block, REG_R1, REG_R1); - host_arm_BNE(block, (uintptr_t)codegen_exit_rout); - - return 0; -} - -static int codegen_MOV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSL(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_BFI(block, dest_reg, src_reg, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_BFI(block, dest_reg, src_reg, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_B(src_size)) - { - host_arm_BFI(block, dest_reg, src_reg, 8, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_arm_VMOV_D_D(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_arm_VMOV_D_D(block, dest_reg, src_reg); - } - else - fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_arm_MOV_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_arm_MOVW_IMM(block, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size)) - { - host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x000000ff); - host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size)) - { - host_arm_AND_IMM(block, dest_reg, dest_reg, ~0x0000ff00); - host_arm_ORR_IMM(block, dest_reg, dest_reg, uop->imm_data << 8); - } - else - fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_arm_MOV_IMM(block, uop->dest_reg_a_real, (uintptr_t)uop->p); - - return 0; -} - -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm_SXTB(block, dest_reg, src_reg, 0); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SXTB(block, dest_reg, src_reg, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm_SXTH(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_arm_SXTB(block, REG_TEMP, src_reg, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SXTB(block, REG_TEMP, src_reg, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_IMM(block, REG_TEMP, 0); - host_arm_VMOV_D_64(block, dest_reg, src_reg, REG_TEMP); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_arm_VMOV_32_S(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, dest_reg, src_reg, 0); - } - else if (REG_IS_L(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, dest_reg, src_reg, 8); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, dest_reg, src_reg, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - if (src_reg == dest_reg) - host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_W(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg, 8); - host_arm_BIC_IMM(block, dest_reg, dest_reg, 0xff00); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static double int64_to_double(int64_t a) -{ - return (double)a; -} -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_arm_VMOV_S_32(block, REG_D_TEMP, src_reg); - host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_arm_SXTH(block, REG_TEMP, src_reg, 0); - host_arm_VMOV_S_32(block, REG_D_TEMP, REG_TEMP); - host_arm_VCVT_D_IS(block, dest_reg, REG_D_TEMP); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - /*ARMv7 has no instructions to convert a 64-bit integer to a double. - For simplicity, call a C function and let the compiler do it.*/ - host_arm_VMOV_64_D(block, REG_R0, REG_R1, src_reg); - host_arm_BL(block, (uintptr_t)int64_to_double); /*Input - R0/R1, Output - D0*/ - host_arm_VMOV_D_D(block, dest_reg, REG_D0); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_fp_round); - host_arm_VMOV_32_S(block, dest_reg, REG_D_TEMP); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg); - host_arm_BL(block, (uintptr_t)codegen_fp_round); - host_arm_VMOV_32_S(block, REG_TEMP, REG_D_TEMP); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int64_t x87_fround64(double b) +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) { - int64_t a, c; + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - 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 int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_arm_VMOV_D_D(block, dest_reg, src_64_reg); - host_arm_TST_IMM(block, tag_reg, TAG_UINT64); - branch_offset = host_arm_BNE_(block); - - /*VFP/NEON has no instructions to convert a float to 64-bit integer, - so call out to C.*/ - host_arm_VMOV_D_D(block, REG_D0, src_reg); - host_arm_call(block, x87_fround64); - host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1); - - *branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2; - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm_LDR_IMM(block, dest_reg, REG_TEMP, 0); - } + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); + } else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; -} -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm_LDRB_IMM(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size)) - { - host_arm_LDRB_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_arm_MOV_IMM(block, REG_TEMP, (uintptr_t)uop->p); - if (REG_IS_L(dest_size)) - { - host_arm_LDRH_IMM(block, dest_reg, REG_TEMP, 0); - } - else if (REG_IS_W(dest_size)) - { - host_arm_LDRH_IMM(block, REG_TEMP, REG_TEMP, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); - - return 0; + return 0; } -static int codegen_NOP(codeblock_t *block, uop_t *uop) +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) { - return 0; + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_I8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_I16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VSUB_I32(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_S8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_S16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_U8(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VQSUB_U16(block, dest_reg, src_reg_a, src_reg_b); + } else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; } -static int codegen_OR(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VORR_D(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_ORR_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_ORR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm_ORR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; +} +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); + if (dest_reg != src_reg_a) + host_arm_VMOV_D_D(block, dest_reg, src_reg_a); + host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; } -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +static int +codegen_ROL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); - host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); - host_arm_VQMOVN_S16(block, dest_reg, REG_Q_TEMP); - host_arm_VQMOVN_S16(block, REG_D_TEMP, REG_Q_TEMP_2); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); - } - else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 32); + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, REG_TEMP2); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 16); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_ROR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); - host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); - host_arm_VQMOVN_S32(block, dest_reg, REG_Q_TEMP); - host_arm_VQMOVN_S32(block, REG_D_TEMP, REG_Q_TEMP_2); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } else { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); } - else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); - host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); - host_arm_VQMOVN_U16(block, dest_reg, REG_Q_TEMP); - host_arm_VQMOVN_U16(block, REG_D_TEMP, REG_Q_TEMP_2); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 16); + } else { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16 - (uop->imm_data & 15)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); } - else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PADDB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_I8(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + host_arm_BFI(block, dest_reg, src_reg, 0, 8); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); } - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_I16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_I32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_S8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_U8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQADD_U16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_I8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_I16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_I32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_S8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_S32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm_VCVT_S32_F32(block, dest_reg, src_reg_a); - } - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VADD_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCEQ_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGE_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VCGT_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMAX_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMIN_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMUL_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRECPE/VRECPS)*/ - host_arm_VMOV_F32_ONE(block, REG_D_TEMP); - host_arm_VDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a); - host_arm_VDUP_32(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/ - host_arm_VSQRT_S(block, REG_D_TEMP, src_reg_a); - host_arm_VMOV_F32_ONE(block, REG_D_TEMP); - host_arm_VDIV_S(block, dest_reg, dest_reg, REG_D_TEMP); - host_arm_VDUP_32(block, dest_reg, dest_reg, 0); - } - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_F32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_arm_VCVT_F32_S32(block, dest_reg, src_reg_a); - } - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); - - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); - host_arm_VPADDL_Q_S32(block, REG_Q_TEMP, REG_Q_TEMP); - host_arm_VMOVN_I64(block, dest_reg, REG_Q_TEMP); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); - host_arm_VSHRN_32(block, dest_reg, REG_Q_TEMP, 16); - } - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); - else - host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); - else - host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); - else - host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 15) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 31) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - if (uop->imm_data == 0) - host_arm_VMOV_D_D(block, dest_reg, src_reg); - else if (uop->imm_data > 63) - host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); - else - host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); - } - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_I8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_I16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VSUB_I32(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_S8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_S16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_U8(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VQSUB_U16(block, dest_reg, src_reg_a, src_reg_b); - } - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); - host_arm_VMOV_D_D(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D8(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D16(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg_b); - if (dest_reg != src_reg_a) - host_arm_VMOV_D_D(block, dest_reg, src_reg_a); - host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); - } - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 32); - host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, REG_TEMP2); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 16); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_ROR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_RSB_IMM(block, REG_TEMP2, shift_reg, 8); - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_AND_IMM(block, REG_TEMP2, REG_TEMP2, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm_MOV_REG(block, dest_reg, src_reg); - } - else - { - host_arm_MOV_REG_ROR(block, dest_reg, src_reg, 32 - (uop->imm_data & 31)); - } - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - host_arm_BFI(block, dest_reg, src_reg, 0, 16); - } - else - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 16-(uop->imm_data & 15)); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - host_arm_BFI(block, dest_reg, src_reg, 0, 8); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8-(uop->imm_data & 7)); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8 - (uop->imm_data & 7)); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR(codeblock_t *block, uop_t *uop) +static int +codegen_ROR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 15); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_ROR_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 15); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_AND_IMM(block, REG_TEMP2, shift_reg, 7); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, REG_TEMP2); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (!(uop->imm_data & 31)) - { - if (src_reg != dest_reg) - host_arm_MOV_REG(block, dest_reg, src_reg); - } - else - { - host_arm_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); - } + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (!(uop->imm_data & 31)) { + if (src_reg != dest_reg) + host_arm_MOV_REG(block, dest_reg, src_reg); + } else { + host_arm_MOV_REG_ROR(block, dest_reg, src_reg, uop->imm_data & 31); } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if ((uop->imm_data & 15) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - if ((uop->imm_data & 7) == 0) - { - if (src_reg != dest_reg) - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - } - else - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - } - else + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if ((uop->imm_data & 15) == 0) { + if (src_reg != dest_reg) fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 16); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 15); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + if ((uop->imm_data & 7) == 0) { + if (src_reg != dest_reg) + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + } else { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_ORR_REG_LSL(block, REG_TEMP, REG_TEMP, REG_TEMP, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data & 7); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } + } else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR(codeblock_t *block, uop_t *uop) +static int +codegen_SAR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_ASR_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); - host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_ASR_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); - host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); - host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_ASR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTH(block, REG_TEMP, REG_TEMP, 16); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 24); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, 16); + host_arm_MOV_REG_ASR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_UXTB(block, REG_TEMP, REG_TEMP, 24); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL(codeblock_t *block, uop_t *uop) +static int +codegen_SHL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSL_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSL_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSL_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, src_reg, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSL_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSL(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSL(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_MOV_REG_LSL(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSL(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR(codeblock_t *block, uop_t *uop) +static int +codegen_SHR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSR_REG(block, dest_reg, src_reg, shift_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSR_REG(block, dest_reg, src_reg, shift_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSR_REG(block, REG_TEMP, REG_TEMP, shift_reg); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_UXTH(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_UXTB(block, REG_TEMP, src_reg, 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_MOV_REG_LSR(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_UXTH(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_UXTB(block, REG_TEMP, src_reg, 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) { - host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); - if (in_range(uop->p, &cpu_state)) - host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + if (in_range(uop->p, &cpu_state)) + host_arm_STR_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) { - host_arm_MOV_IMM(block, REG_R0, uop->imm_data); - if (in_range(uop->p, &cpu_state)) - host_arm_STRB_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t)uop->p - (uintptr_t)&cpu_state); - else - fatal("codegen_STORE_PTR_IMM - not in range\n"); + host_arm_MOV_IMM(block, REG_R0, uop->imm_data); + if (in_range(uop->p, &cpu_state)) + host_arm_STRB_IMM(block, REG_R0, REG_CPUSTATE, (uintptr_t) uop->p - (uintptr_t) &cpu_state); + else + fatal("codegen_STORE_PTR_IMM - not in range\n"); - return 0; + return 0; } -static int codegen_SUB(codeblock_t *block, uop_t *uop) +static int +codegen_SUB(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_SUB_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) - { - host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) - { - host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); - host_arm_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_SUB_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_SUB_REG_LSR(block, REG_TEMP, src_reg_a, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_SUB_REG_LSL(block, REG_TEMP, src_reg_a, src_reg_b, 0); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b)) { + host_arm_RSB_REG_LSR(block, REG_TEMP, src_reg_b, src_reg_a, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b)) { + host_arm_MOV_REG_LSR(block, REG_TEMP, src_reg_a, 8); + host_arm_SUB_REG_LSR(block, REG_TEMP, REG_TEMP, src_reg_b, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; -// host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); -// return 0; + // host_arm_SUB_REG_LSL(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, 0); + // return 0; } -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) - { - host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); - host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); - host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); - } - else - fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_SUB_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_B(dest_size) && REG_IS_BH(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 0, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size)) { + host_arm_SUB_IMM(block, REG_TEMP, src_reg, uop->imm_data << 8); + host_arm_MOV_REG_LSR(block, REG_TEMP, REG_TEMP, 8); + host_arm_BFI(block, dest_reg, REG_TEMP, 8, 8); + } else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm_BEQ_(block); + uop->p = host_arm_BEQ_(block); - return 0; + return 0; } -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 31); - } - else if (REG_IS_W(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 15); - } - else if (REG_IS_B(src_size)) - { - host_arm_TST_IMM(block, src_reg, 1 << 7); - } - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); + if (REG_IS_L(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 31); + } else if (REG_IS_W(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 15); + } else if (REG_IS_B(src_size)) { + host_arm_TST_IMM(block, src_reg, 1 << 7); + } else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); - uop->p = host_arm_BNE_(block); + uop->p = host_arm_BNE_(block); - return 0; + return 0; } -static int codegen_XOR(codeblock_t *block, uop_t *uop) +static int +codegen_XOR(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_arm_VEOR_D(block, dest_reg, src_reg_a, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) - { - host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); - host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); - } - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_arm_VEOR_D(block, dest_reg, src_reg_a, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, src_reg_b, 0); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTH(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 0); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_B(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 0); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size_a) && REG_IS_BH(src_size_b) && dest_reg == src_reg_a) { + host_arm_UXTB(block, REG_TEMP, src_reg_b, 8); + host_arm_EOR_REG_LSL(block, dest_reg, src_reg_a, REG_TEMP, 8); + } else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - return 0; + return 0; } -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); - } - else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) - { - host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); - } - else - fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && dest_reg == src_reg) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && dest_reg == src_reg) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data); + } else if (REG_IS_BH(dest_size) && REG_IS_BH(src_size) && dest_reg == src_reg) { + host_arm_EOR_IMM(block, dest_reg, src_reg, uop->imm_data << 8); + } else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); - return 0; + return 0; } -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, - [UOP_JMP & UOP_MASK] = codegen_JMP, + [UOP_JMP & + UOP_MASK] + = codegen_JMP, - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - if (in_range_h(p, &cpu_state)) - host_arm_LDRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_8 - not in range\n"); + if (in_range_h(p, &cpu_state)) + host_arm_LDRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_8 - not in range\n"); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - if (in_range_h(p, &cpu_state)) - host_arm_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - { - host_arm_MOV_IMM(block, REG_R3, (uintptr_t)p - (uintptr_t)&cpu_state); - host_arm_LDRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); - } + if (in_range_h(p, &cpu_state)) + host_arm_LDRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else { + host_arm_MOV_IMM(block, REG_R3, (uintptr_t) p - (uintptr_t) &cpu_state); + host_arm_LDRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); + } } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - if (in_range(p, &cpu_state)) - host_arm_LDR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_LDR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - codegen_direct_read_32(block, host_reg, p); + codegen_direct_read_32(block, host_reg, p); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_LDRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_LDRB_IMM(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - if (in_range(p, &cpu_state)) - host_arm_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_8 - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_STRB_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_8 - not in range\n"); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - if (in_range_h(p, &cpu_state)) - host_arm_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - { - host_arm_MOV_IMM(block, REG_R3, (uintptr_t)p - (uintptr_t)&cpu_state); - host_arm_STRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); - } + if (in_range_h(p, &cpu_state)) + host_arm_STRH_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else { + host_arm_MOV_IMM(block, REG_R3, (uintptr_t) p - (uintptr_t) &cpu_state); + host_arm_STRH_REG(block, host_reg, REG_CPUSTATE, REG_R3); + } } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - if (in_range(p, &cpu_state)) - host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_32 - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_32 - not in range\n"); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); + host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); - host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); - host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); - host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); - host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state); + host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset); + host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx); + host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7); + host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3); + host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t) base - (uintptr_t) &cpu_state); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - if (in_range(p, &cpu_state)) - host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state); - else - fatal("codegen_direct_write_ptr - not in range\n"); + if (in_range(p, &cpu_state)) + host_arm_STR_IMM(block, host_reg, REG_CPUSTATE, (uintptr_t) p - (uintptr_t) &cpu_state); + else + fatal("codegen_direct_write_ptr - not in range\n"); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (stack_offset >= 0 && stack_offset < 256) - host_arm_LDRH_IMM(block, host_reg, REG_HOST_SP, stack_offset); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (stack_offset >= 0 && stack_offset < 256) + host_arm_LDRH_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - if (stack_offset >= 0 && stack_offset < 4096) - host_arm_LDR_IMM(block, host_reg, REG_HOST_SP, stack_offset); - else - fatal("codegen_direct_read_32 - not in range\n"); + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_LDR_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_read_32 - not in range\n"); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - codegen_direct_read_32_stack(block, host_reg, stack_offset); + codegen_direct_read_32_stack(block, host_reg, stack_offset); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - if (stack_offset >= 0 && stack_offset < 4096) - host_arm_STR_IMM(block, host_reg, REG_HOST_SP, stack_offset); - else - fatal("codegen_direct_write_32 - not in range\n"); + if (stack_offset >= 0 && stack_offset < 4096) + host_arm_STR_IMM(block, host_reg, REG_HOST_SP, stack_offset); + else + fatal("codegen_direct_write_32 - not in range\n"); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2; + *(uint32_t *) p |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) p) - 8) & 0x3fffffc) >> 2; } #endif diff --git a/src/codegen_new/codegen_backend_x86-64.c b/src/codegen_new/codegen_backend_x86-64.c index eadf6b941..a57cb4282 100644 --- a/src/codegen_new/codegen_backend_x86-64.c +++ b/src/codegen_new/codegen_backend_x86-64.c @@ -1,28 +1,28 @@ #if defined __amd64__ || defined _M_X64 -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops.h" -#include "codegen_backend_x86-64_ops_sse.h" -#include "codegen_reg.h" -#include "x86.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops.h" +# include "codegen_backend_x86-64_ops_sse.h" +# include "codegen_reg.h" +# include "x86.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -41,346 +41,338 @@ void *codegen_mem_store_double; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - /*Note: while EAX and EDX are normally volatile registers under x86 - calling conventions, the recompiler will explicitly save and restore - them across funcion calls*/ - {REG_EAX, 0}, - {REG_EBX, 0}, - {REG_EDX, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + /*Note: while EAX and EDX are normally volatile registers under x86 + calling conventions, the recompiler will explicitly save and restore + them across funcion calls*/ + {REG_EAX, 0}, + { REG_EBX, 0}, + { REG_EDX, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ -#if _WIN64 - /*Windows x86-64 calling convention preserves XMM6-XMM15*/ - {REG_XMM6, 0}, - {REG_XMM7, 0}, -#else - /*System V AMD64 calling convention does not preserve any XMM registers*/ - {REG_XMM6, HOST_REG_FLAG_VOLATILE}, - {REG_XMM7, HOST_REG_FLAG_VOLATILE}, -#endif - {REG_XMM1, HOST_REG_FLAG_VOLATILE}, - {REG_XMM2, HOST_REG_FLAG_VOLATILE}, - {REG_XMM3, HOST_REG_FLAG_VOLATILE}, - {REG_XMM4, HOST_REG_FLAG_VOLATILE}, - {REG_XMM5, HOST_REG_FLAG_VOLATILE} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { +# if _WIN64 + /*Windows x86-64 calling convention preserves XMM6-XMM15*/ + {REG_XMM6, 0 }, + { REG_XMM7, 0 }, +# else + /*System V AMD64 calling convention does not preserve any XMM registers*/ + { REG_XMM6, HOST_REG_FLAG_VOLATILE }, + { REG_XMM7, HOST_REG_FLAG_VOLATILE }, +# endif + { REG_XMM1, HOST_REG_FLAG_VOLATILE}, + { REG_XMM2, HOST_REG_FLAG_VOLATILE}, + { REG_XMM3, HOST_REG_FLAG_VOLATILE}, + { REG_XMM4, HOST_REG_FLAG_VOLATILE}, + { REG_XMM5, HOST_REG_FLAG_VOLATILE} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *branch_offset; + uint8_t *misaligned_offset; - /*In - ESI = address - Out - ECX = data, ESI = abrt*/ - /*MOV ECX, ESI - SHR ESI, 12 - MOV RSI, [readlookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOVZX ECX, B[RSI+RCX] - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL readmembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2); - host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_ECX, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 2 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 4 && !is_float) - host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); - else if (size == 4 && is_float) - host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); - else if (size == 8) - host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); - else - fatal("build_load_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + /*In - ESI = address + Out - ECX = data, ESI = abrt*/ + /*MOV ECX, ESI + SHR ESI, 12 + MOV RSI, [readlookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOVZX ECX, B[RSI+RCX] + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL readmembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t) (uintptr_t) readlookup2); + host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_ECX, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 2 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 4 && !is_float) + host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX); + else if (size == 4 && is_float) + host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); + else if (size == 8) + host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX); + else + fatal("build_load_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - host_x86_PUSH(block, REG_RAX); - host_x86_PUSH(block, REG_RDX); -#if _WIN64 - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); - //host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data); -#else - host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); -#endif - if (size == 1 && !is_float) - { - host_x86_CALL(block, (void *)readmembl); - host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); - } - else if (size == 2 && !is_float) - { - host_x86_CALL(block, (void *)readmemwl); - host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); - } - else if (size == 4 && !is_float) - { - host_x86_CALL(block, (void *)readmemll); - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - } - else if (size == 4 && is_float) - { - host_x86_CALL(block, (void *)readmemll); - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); - host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - } - else if (size == 8) - { - host_x86_CALL(block, (void *)readmemql); - host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); - } -#if _WIN64 - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); -#endif - host_x86_POP(block, REG_RDX); - host_x86_POP(block, REG_RAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + host_x86_PUSH(block, REG_RAX); + host_x86_PUSH(block, REG_RDX); +# if _WIN64 + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20); + // host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data); +# else + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); +# endif + if (size == 1 && !is_float) { + host_x86_CALL(block, (void *) readmembl); + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + } else if (size == 2 && !is_float) { + host_x86_CALL(block, (void *) readmemwl); + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + } else if (size == 4 && !is_float) { + host_x86_CALL(block, (void *) readmemll); + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + } else if (size == 4 && is_float) { + host_x86_CALL(block, (void *) readmemll); + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + } else if (size == 8) { + host_x86_CALL(block, (void *) readmemql); + host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX); + } +# if _WIN64 + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20); +# endif + host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset; + uint8_t *branch_offset; + uint8_t *misaligned_offset; - /*In - ECX = data, ESI = address - Out - ESI = abrt - Corrupts EDI*/ - /*MOV EDI, ESI - SHR ESI, 12 - MOV ESI, [writelookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOV [RSI+RDI], ECX - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL writemembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2); - host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_EDI, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 2 && !is_float) - host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 4 && !is_float) - host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); - else if (size == 4 && is_float) - host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); - else if (size == 8) - host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); - else - fatal("build_store_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + /*In - ECX = data, ESI = address + Out - ESI = abrt + Corrupts EDI*/ + /*MOV EDI, ESI + SHR ESI, 12 + MOV ESI, [writelookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOV [RSI+RDI], ECX + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL writemembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t) (uintptr_t) writelookup2); + host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_EDI, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 4 && !is_float) + host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX); + else if (size == 4 && is_float) + host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); + else if (size == 8) + host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP); + else + fatal("build_store_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - host_x86_PUSH(block, REG_RAX); - host_x86_PUSH(block, REG_RDX); -#if _WIN64 - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28); - if (size == 4 && is_float) - host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data - else if (size == 8) - host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data - else - host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address -#else - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8); - //host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address - if (size == 4 && is_float) - host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); //data - else if (size == 8) - host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); //data - else - host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data -#endif - if (size == 1) - host_x86_CALL(block, (void *)writemembl); - else if (size == 2) - host_x86_CALL(block, (void *)writememwl); - else if (size == 4) - host_x86_CALL(block, (void *)writememll); - else if (size == 8) - host_x86_CALL(block, (void *)writememql); -#if _WIN64 - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28); -#else - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8); -#endif - host_x86_POP(block, REG_RDX); - host_x86_POP(block, REG_RAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + host_x86_PUSH(block, REG_RAX); + host_x86_PUSH(block, REG_RDX); +# if _WIN64 + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28); + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); // data + else if (size == 8) + host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); // data + else + host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); // data + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); // address +# else + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8); + // host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); // data + else if (size == 8) + host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); // data + else + host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); // data +# endif + if (size == 1) + host_x86_CALL(block, (void *) writemembl); + else if (size == 2) + host_x86_CALL(block, (void *) writememwl); + else if (size == 4) + host_x86_CALL(block, (void *) writememll); + else if (size == 8) + host_x86_CALL(block, (void *) writememql); +# if _WIN64 + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28); +# else + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8); +# endif + host_x86_POP(block, REG_RDX); + host_x86_POP(block, REG_RAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } -void codegen_backend_init(void) +void +codegen_backend_init(void) { - codeblock_t *block; - int c; + codeblock_t *block; + int c; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current); - codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); - block_write_data = codeblock[block_current].data; - build_loadstore_routines(&codeblock[block_current]); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current); + codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block); + block_write_data = codeblock[block_current].data; + build_loadstore_routines(&codeblock[block_current]); - codegen_gpf_rout = &codeblock[block_current].data[block_pos]; -#if _WIN64 - host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX); - host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX); -#else - host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); -#endif - host_x86_CALL(block, (void *)x86gpf); - codegen_exit_rout = &codeblock[block_current].data[block_pos]; - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); - host_x86_POP(block, REG_R15); - host_x86_POP(block, REG_R14); - host_x86_POP(block, REG_R13); - host_x86_POP(block, REG_R12); - host_x86_POP(block, REG_RDI); - host_x86_POP(block, REG_RSI); - host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); - host_x86_RET(block); + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; +# if _WIN64 + host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX); + host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX); +# else + host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); +# endif + host_x86_CALL(block, (void *) x86gpf); + codegen_exit_rout = &codeblock[block_current].data[block_pos]; + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); - block_write_data = NULL; + block_write_data = NULL; - asm( - "stmxcsr %0\n" - : "=m" (cpu_state.old_fp_control) - ); - cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; + asm( + "stmxcsr %0\n" + : "=m"(cpu_state.old_fp_control)); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); } -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; /*Entry code*/ - host_x86_PUSH(block, REG_RBX); - host_x86_PUSH(block, REG_RBP); - host_x86_PUSH(block, REG_RSI); - host_x86_PUSH(block, REG_RDI); - host_x86_PUSH(block, REG_R12); - host_x86_PUSH(block, REG_R13); - host_x86_PUSH(block, REG_R14); - host_x86_PUSH(block, REG_R15); - host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38); - host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); - host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); - host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX); - } - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t)ram); + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_RBX); + host_x86_PUSH(block, REG_RBP); + host_x86_PUSH(block, REG_RSI); + host_x86_PUSH(block, REG_RDI); + host_x86_PUSH(block, REG_R12); + host_x86_PUSH(block, REG_R13); + host_x86_PUSH(block, REG_R14); + host_x86_PUSH(block, REG_R15); + host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38); + host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t) &cpu_state) + 128); + if (block->flags & CODEBLOCK_HAS_FPU) { + host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX); + } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t) ram); } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); - host_x86_POP(block, REG_R15); - host_x86_POP(block, REG_R14); - host_x86_POP(block, REG_R13); - host_x86_POP(block, REG_R12); - host_x86_POP(block, REG_RDI); - host_x86_POP(block, REG_RSI); - host_x86_POP(block, REG_RBP); - host_x86_POP(block, REG_RDX); - host_x86_RET(block); + host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38); + host_x86_POP(block, REG_R15); + host_x86_POP(block, REG_R14); + host_x86_POP(block, REG_R13); + host_x86_POP(block, REG_R12); + host_x86_POP(block, REG_RDI); + host_x86_POP(block, REG_RSI); + host_x86_POP(block, REG_RBP); + host_x86_POP(block, REG_RDX); + host_x86_RET(block); } #endif diff --git a/src/codegen_new/codegen_backend_x86-64.h b/src/codegen_new/codegen_backend_x86-64.h index ccc526b30..5f476010d 100644 --- a/src/codegen_new/codegen_backend_x86-64.h +++ b/src/codegen_new/codegen_backend_x86-64.h @@ -1,14 +1,14 @@ #include "codegen_backend_x86-64_defs.h" -#define BLOCK_SIZE 0x4000 -#define BLOCK_MASK 0x3fff +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) -#define BLOCK_MAX 0x3c0 +#define BLOCK_MAX 0x3c0 #define CODEGEN_BACKEND_HAS_MOV_IMM diff --git a/src/codegen_new/codegen_backend_x86-64_defs.h b/src/codegen_new/codegen_backend_x86-64_defs.h index 8955773cd..12f05f01c 100644 --- a/src/codegen_new/codegen_backend_x86-64_defs.h +++ b/src/codegen_new/codegen_backend_x86-64_defs.h @@ -1,52 +1,52 @@ /*RBP = cpu_state + 128 R12 = ram (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/ -#define REG_AX 0 -#define REG_CX 1 -#define REG_DX 2 -#define REG_BX 3 -#define REG_SP 4 -#define REG_BP 5 -#define REG_SI 6 -#define REG_DI 7 +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 -#define REG_EAX 0 -#define REG_ECX 1 -#define REG_EDX 2 -#define REG_EBX 3 -#define REG_ESP 4 -#define REG_EBP 5 -#define REG_ESI 6 -#define REG_EDI 7 +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 +#define REG_ESP 4 +#define REG_EBP 5 +#define REG_ESI 6 +#define REG_EDI 7 -#define REG_RAX 0 -#define REG_RCX 1 -#define REG_RDX 2 -#define REG_RBX 3 -#define REG_RSP 4 -#define REG_RBP 5 -#define REG_RSI 6 -#define REG_RDI 7 -#define REG_R8 8 -#define REG_R9 9 -#define REG_R10 10 -#define REG_R11 11 -#define REG_R12 12 -#define REG_R13 13 -#define REG_R14 14 -#define REG_R15 15 +#define REG_RAX 0 +#define REG_RCX 1 +#define REG_RDX 2 +#define REG_RBX 3 +#define REG_RSP 4 +#define REG_RBP 5 +#define REG_RSI 6 +#define REG_RDI 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_R13 13 +#define REG_R14 14 +#define REG_R15 15 -#define REG_XMM0 0 -#define REG_XMM1 1 -#define REG_XMM2 2 -#define REG_XMM3 3 -#define REG_XMM4 4 -#define REG_XMM5 5 -#define REG_XMM6 6 -#define REG_XMM7 7 +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 -#define REG_XMM_TEMP REG_XMM0 +#define REG_XMM_TEMP REG_XMM0 -#define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_REGS 3 #define CODEGEN_HOST_FP_REGS 7 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index 2baa0f585..33fb500db 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -1,1831 +1,1766 @@ #if defined __amd64__ || defined _M_X64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops.h" -#include "codegen_backend_x86-64_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops.h" +# include "codegen_backend_x86-64_ops_helpers.h" -#define RM_OP_ADD 0x00 -#define RM_OP_OR 0x08 -#define RM_OP_AND 0x20 -#define RM_OP_SUB 0x28 -#define RM_OP_XOR 0x30 -#define RM_OP_CMP 0x38 +# define RM_OP_ADD 0x00 +# define RM_OP_OR 0x08 +# define RM_OP_AND 0x20 +# define RM_OP_SUB 0x28 +# define RM_OP_XOR 0x30 +# define RM_OP_CMP 0x38 -#define RM_OP_ROL 0x00 -#define RM_OP_ROR 0x08 -#define RM_OP_SHL 0x20 -#define RM_OP_SHR 0x28 -#define RM_OP_SAR 0x38 +# define RM_OP_ROL 0x00 +# define RM_OP_ROR 0x08 +# define RM_OP_SHL 0x20 +# define RM_OP_SHR 0x28 +# define RM_OP_SAR 0x38 -static inline void call(codeblock_t *block, uintptr_t func) +static inline void +call(codeblock_t *block, uintptr_t func) { - intptr_t diff; + intptr_t diff; - codegen_alloc_bytes(block, 5); - diff = (intptr_t)(func - (uintptr_t)&block_write_data[block_pos + 5]); + codegen_alloc_bytes(block, 5); + diff = (intptr_t) (func - (uintptr_t) &block_write_data[block_pos + 5]); - if (diff >= -0x80000000LL && diff < 0x7fffffffLL) - { - codegen_addbyte(block, 0xE8); /*CALL*/ - codegen_addlong(block, (uint32_t)diff); - } - else - { - codegen_alloc_bytes(block, 13); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ - codegen_addquad(block, func); - codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ - } + if (diff >= -0x80000000LL && diff < 0x7fffffffLL) { + codegen_addbyte(block, 0xE8); /*CALL*/ + codegen_addlong(block, (uint32_t) diff); + } else { + codegen_alloc_bytes(block, 13); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ + codegen_addquad(block, func); + codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/ + } } -static inline void jmp(codeblock_t *block, uintptr_t func) +static inline void +jmp(codeblock_t *block, uintptr_t func) { - intptr_t diff; + intptr_t diff; - codegen_alloc_bytes(block, 5); - diff = (intptr_t)(func - (uintptr_t)&block_write_data[block_pos + 5]); + codegen_alloc_bytes(block, 5); + diff = (intptr_t) (func - (uintptr_t) &block_write_data[block_pos + 5]); - if (diff >= -0x80000000LL && diff < 0x7fffffffLL) - { - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uint32_t)diff); - } - else - { - codegen_alloc_bytes(block, 13); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ - codegen_addquad(block, func); - codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ - } + if (diff >= -0x80000000LL && diff < 0x7fffffffLL) { + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uint32_t) diff); + } else { + codegen_alloc_bytes(block, 13); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/ + codegen_addquad(block, func); + codegen_addbyte3(block, 0x41, 0xff, 0xe1); /*JMP R9*/ + } } -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (dst_reg & 8) - fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\n"); - - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ - } -} -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else - fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); -} -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD8_REG_REG - dst_reg & 8\n"); + if (dst_reg & 8) + fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\n"); + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ -} -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD16_REG_REG - dst_reg & 8\n"); - + codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/ + } } -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_ADD32_REG_REG - dst_reg & 8\n"); + if (dst_reg & 8) + fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ -} - -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_AND8_REG_IMM - dst_reg & 8\n"); - - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ - } -} -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_AND16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_AND32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND8_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ -} -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND16_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ -} -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_AND32_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ -} - -void host_x86_CALL(codeblock_t *block, void *p) -{ - call(block, (uintptr_t)p); -} - -void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else - fatal("CMP64_REG_IMM not 8-bit imm\n"); -} - -void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} - -void host_x86_JMP(codeblock_t *block, void *p) -{ - jmp(block, (uintptr_t)p); -} - -void host_x86_JNZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} -void host_x86_JZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} - -uint8_t *host_x86_JNZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JS_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block_write_data[block_pos-1]; -} - -uint32_t *host_x86_JNB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} - -void host_x86_LAHF(codeblock_t *block) -{ - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x9f); /*LAHF*/ -} - -void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) -{ - if (offset) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ - codegen_addlong(block, offset); - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ - } -} -void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_LEA_REG_REG - bad reg\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ - ((src_reg_b & 7) << 3) | (src_reg_a & 7)); -} -void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ - (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); -} - -void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ - codegen_addbyte(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); - codegen_alloc_bytes(block, 8); - codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addbyte(block, imm_data); - } -} -void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ - codegen_addword(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); - codegen_alloc_bytes(block, 10); - codegen_addbyte4(block, 0x66, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addword(block, imm_data); - } -} -void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); - codegen_alloc_bytes(block, 11); - codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV8_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV16_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ - codegen_addlong(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); - } -} -void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV32_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ - codegen_addlong(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOV64_ABS_REG - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} - -void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} - -void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ -} -void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ -} -void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ -} - -void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOV8_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - fatal("host_x86_MOV8_REG_ABS - out of range\n"); - } -} -void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOV16_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3)); /*MOV dst_reg, ram_offset[R12]*/ - codegen_addbyte(block, 0x24); - codegen_addlong(block, ram_offset); - } - else - { - fatal("host_x86_MOV16_REG_ABS - out of range\n"); - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 1); - codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [r9]*/ - } -} -void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOV32_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - fatal("host_x86_MOV32_REG_ABS - out of range\n"); - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (dst_reg & 8) - fatal("host_x86_MOV64_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ - codegen_addlong(block, offset); - } - else - fatal("host_x86_MOV64_REG_ABS - out of range\n"); -} - -void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) -{ - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} - -void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) -{ - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ -} - -void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale) -{ - if ((dst_reg & 8) || (index_reg & 8)) - fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - if (base_reg & 8) - codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ - else - codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ -} - -void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if ((dst_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x48); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); -} -void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if ((src_reg & 8) || (base_reg & 8)) - fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x48); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); -} - -void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) -{ - if (base_reg & 8) - fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); - codegen_addlong(block, imm_data); - } - } - else - fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); -} - -void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) -{ - if (reg >= 8) - fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ -} -void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV16_REG_IMM reg & 8\n"); - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/ codegen_addword(block, imm_data); -} -void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) -{ - if (reg & 8) - fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + } else { codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else + fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data); +} +void +host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD8_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ +} +void +host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD16_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ +} +void +host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_ADD32_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) +void +host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { - if (reg & 8) - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ - codegen_addquad(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ - codegen_addquad(block, imm_data); - } -} - -void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV8_REG_REG - bad reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND8_REG_IMM - dst_reg & 8\n"); + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); -} -void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV16_REG_REG - bad reg\n"); - + codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/ + } } -void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOV32_REG_REG - bad reg\n"); + if (dst_reg & 8) + fatal("host_x86_AND16_REG_IMM - dst_reg & 8\n"); + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_AND32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND8_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ +} +void +host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND16_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ +} +void +host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_AND32_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ +} + +void +host_x86_CALL(codeblock_t *block, void *p) +{ + call(block, (uintptr_t) p); +} + +void +host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else + fatal("CMP64_REG_IMM not 8-bit imm\n"); +} + +void +host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} + +void +host_x86_JMP(codeblock_t *block, void *p) +{ + jmp(block, (uintptr_t) p); +} + +void +host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} +void +host_x86_JZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} + +uint8_t * +host_x86_JNZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x75, 0); /*JNZ*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JS_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x78, 0); /*JS*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x74, 0); /*JZ*/ + return &block_write_data[block_pos - 1]; +} + +uint32_t * +host_x86_JNB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} + +void +host_x86_LAHF(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + +void +host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + if (offset) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ + codegen_addlong(block, offset); + } else { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } +} +void +host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ + ((src_reg_b & 7) << 3) | (src_reg_a & 7)); +} +void +host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ + (shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7)); } -void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +void +host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { - if (!offset) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else if (offset >= -0x80 && offset < 0x80) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 11); - codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, offset); - codegen_addlong(block, imm_data); - } -} + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/ + codegen_addbyte(block, imm_data); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 8); + codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + codegen_addbyte(block, imm_data); + } } -void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ + codegen_addword(block, imm_data); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 10); + codegen_addbyte4(block, 0x66, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + codegen_addword(block, imm_data); + } } -void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p); + codegen_alloc_bytes(block, 11); + codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + codegen_addlong(block, imm_data); + } } -void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +void +host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV8_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/ + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } +} +void +host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (src_reg & 8) + fatal("host_x86_MOV16_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); + codegen_addbyte4(block, 0x66, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + } } -void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +void +host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) - fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); -} - -void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); - - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + if (src_reg & 8) + fatal("host_x86_MOV32_ABS_REG - bad reg\n"); + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ + codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/ + codegen_addlong(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3)); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } -void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + if (src_reg & 8) + fatal("host_x86_MOV64_ABS_REG - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/ + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p); + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } +} + +void +host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + +void +host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ +} +void +host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ +} +void +host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ +} + +void +host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + if (dst_reg & 8) + fatal("host_x86_MOV8_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ + codegen_addbyte3(block, 0x8a, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + fatal("host_x86_MOV8_REG_ABS - out of range\n"); + } } - -void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) +void +host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); + if (dst_reg & 8) + fatal("host_x86_MOV16_REG_ABS reg & 8\n"); - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x66, 0x41); - codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ - } -} -void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - -// if (dst_reg & 8) -// fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - if (dst_reg & 8) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x44); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); - - codegen_alloc_bytes(block, 9); - codegen_addbyte(block, 0x41); - codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); - - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ - } -} -void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) -{ - int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram; - - if (dst_reg & 8) - fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ - } - else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) - { - codegen_alloc_bytes(block, 9); - codegen_addbyte(block, 0x41); - codegen_addbyte4(block, 0x0f, 0xb7, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ - codegen_addlong(block, ram_offset); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ - codegen_addquad(block, (uintptr_t)p); - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x41, 0x0f, 0xb7, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ - } -} - -void host_x86_NOP(codeblock_t *block) -{ + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3)); /*MOV dst_reg, ram_offset[R12]*/ + codegen_addbyte(block, 0x24); + codegen_addlong(block, ram_offset); + } else { + fatal("host_x86_MOV16_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x90); /*NOP*/ + codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [r9]*/ + } } - -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - if (dst_reg & 8) - fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ - } -} -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ -} -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); + if (dst_reg & 8) + fatal("host_x86_MOV32_REG_ABS reg & 8\n"); + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ + codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + fatal("host_x86_MOV32_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3)); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ + if (dst_reg & 8) + fatal("host_x86_MOV64_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x48, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/ + codegen_addlong(block, offset); + } else + fatal("host_x86_MOV64_REG_ABS - out of range\n"); } -void host_x86_POP(codeblock_t *block, int dst_reg) +void +host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) { + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } +} + +void +host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ +} + +void +host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale) +{ + if ((dst_reg & 8) || (index_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); + codegen_alloc_bytes(block, 4); + if (base_reg & 8) + codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ + else + codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ +} + +void +host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if ((dst_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x48); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void +host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} +void +host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if ((src_reg & 8) || (base_reg & 8)) + fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x48); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x48, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset); +} + +void +host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) +{ + if (base_reg & 8) + fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n"); + + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); + codegen_addlong(block, imm_data); + } + } else + fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); +} + +void +host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg >= 8) + fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ +} +void +host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV16_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); +} +void +host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) +{ + if (reg & 8) + fatal("host_x86_MOV32_REG_IMM reg & 8\n"); + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); +} + +void +host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) +{ + if (reg & 8) { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/ + codegen_addquad(block, imm_data); + } +} + +void +host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV8_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +void +host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV16_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} +void +host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOV32_REG_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); +} + +void +host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) +{ + if (!offset) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else if (offset >= -0x80 && offset < 0x80) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 11); + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } +} + +void +host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} + +void +host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); +} +void +host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) +{ + if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) + fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); +} + +void +host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +void +host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x66, 0x41); + codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } +} +void +host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + // if (dst_reg & 8) + // fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + if (offset >= -128 && offset < 127) { + if (dst_reg & 8) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x44); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } + } else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { if (dst_reg & 8) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x41, 0x58 | (dst_reg & 7)); /*POP reg*/ - } - else - { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ - } + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 9); + codegen_addbyte(block, 0x41); + codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); + + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x41, 0x0f, 0xb6, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } +} +void +host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) +{ + int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + int64_t ram_offset = (uintptr_t) p - (uintptr_t) ram; + + if (dst_reg & 8) + fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/ + } else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES)) { + codegen_alloc_bytes(block, 9); + codegen_addbyte(block, 0x41); + codegen_addbyte4(block, 0x0f, 0xb7, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/ + codegen_addlong(block, ram_offset); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x41, 0x0f, 0xb7, 0x01 | ((dst_reg & 7) << 3)); /*MOVZX dst_reg, [r9]*/ + } } -void host_x86_PUSH(codeblock_t *block, int src_reg) +void +host_x86_NOP(codeblock_t *block) { - if (src_reg & 8) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x41, 0x50 | (src_reg & 7)); /*PUSH reg*/ - } - else - { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ - } + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x90); /*NOP*/ } -void host_x86_RET(codeblock_t *block) +void +host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + if (dst_reg & 8) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); + + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/ + } +} +void +host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} +void +host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ +} +void +host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ +} +void +host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ +} + +void +host_x86_POP(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x41, 0x58 | (dst_reg & 7)); /*POP reg*/ + } else { codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0xc3); /*RET*/ + codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/ + } } -void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) +void +host_x86_PUSH(codeblock_t *block, int src_reg) { - if (dst_reg & 8) - fatal("ROL8 CL & 8\n"); + if (src_reg & 8) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROL16 CL & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROL32 CL & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ + codegen_addbyte2(block, 0x41, 0x50 | (src_reg & 7)); /*PUSH reg*/ + } else { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + } } -void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_RET(codeblock_t *block) { - if (dst_reg & 8) - fatal("ROL8 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0xc3); /*RET*/ } -void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) + +void +host_x86_ROL8_CL(codeblock_t *block, int dst_reg) { - if (dst_reg & 8) - fatal("ROL16 imm & 8\n"); + if (dst_reg & 8) + fatal("ROL8 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL16 CL & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROL32 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL8 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL16 imm & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROL32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_ROR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR8 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR16 CL & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("ROR32 CL & 8\n"); + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR8 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR16 imm & 8\n"); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("ROR32 im & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void +host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SAR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} + +void +host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SAR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} + +void +host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHL32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHL32 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_SHR8_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR8 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR16_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR16 CL & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR32_CL(codeblock_t *block, int dst_reg) +{ + if (dst_reg & 8) + fatal("SHR32 CL & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR8 imm & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR16 imm & 8\n"); + + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + if (dst_reg & 8) + fatal("SHR32 imm & 8\n"); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void +host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\n"); + + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ + } +} +void +host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("ROL32 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} - -void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROR8 CL & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROR16 CL & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("ROR32 CL & 8\n"); - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("ROR8 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("ROR16 imm & 8\n"); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg & 8) - fatal("ROR32 im & 8\n"); + if (dst_reg & 8) + fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } - -void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +void +host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) { - if (dst_reg & 8) - fatal("SAR8 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} -void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SAR16 CL & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} -void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SAR32 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} - -void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SAR8 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ -} -void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SAR16 imm & 8\n"); + if (dst_reg & 8) + fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else + fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); } -void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("SAR32 imm & 8\n"); - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB8_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ +} +void +host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB16_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ +} +void +host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_SUB32_REG_REG - dst_reg & 8\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHL8 CL & 8\n"); +# define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) +void +host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) +{ + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_TEST32_REG - bad reg\n"); + + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg & 8) + fatal("TEST32_REG_IMM reg & 8\n"); + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg & 8) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); + + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHL16 CL & 8\n"); - + codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ + } } -void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +void +host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - if (dst_reg & 8) - fatal("SHL32 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} - -void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHL8 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHL16 imm & 8\n"); + if (dst_reg & 8) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHL32 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} - -void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHR8 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHR16 CL & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) -{ - if (dst_reg & 8) - fatal("SHR32 CL & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHR8 imm & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ - if (dst_reg & 8) - fatal("SHR16 imm & 8\n"); - + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { - if (dst_reg & 8) - fatal("SHR32 imm & 8\n"); + if (dst_reg & 8) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); + + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } - -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/ - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +void +host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +void +host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg & 8) - fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\n"); + if ((dst_reg & 8) || (src_reg & 8)) + fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else - fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data); -} -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB8_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ -} -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB16_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ -} -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_SUB32_REG_REG - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ -} - -#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) - -void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_TEST32_REG - bad reg\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("TEST32_REG_IMM reg & 8\n"); - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); - - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/ - } -} -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg & 8) - fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); - - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - if ((dst_reg & 8) || (src_reg & 8)) - fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); - - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ } #endif diff --git a/src/codegen_new/codegen_backend_x86-64_ops_helpers.h b/src/codegen_new/codegen_backend_x86-64_ops_helpers.h index a7755d1a8..42c2d5259 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops_helpers.h +++ b/src/codegen_new/codegen_backend_x86-64_ops_helpers.h @@ -1,102 +1,103 @@ #define JMP_LEN_BYTES 5 -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +static inline void +codegen_addbyte(codeblock_t *block, uint8_t val) { - if (block_pos >= BLOCK_MAX) - { - fatal("codegen_addbyte over! %i\n", block_pos); -// CPU_BLOCK_END(); - } - block_write_data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) { + fatal("codegen_addbyte over! %i\n", block_pos); + // CPU_BLOCK_END(); + } + block_write_data[block_pos++] = val; } -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +static inline void +codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) { - if (block_pos > (BLOCK_MAX-2)) - { - fatal("codegen_addbyte2 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; + if (block_pos > (BLOCK_MAX - 2)) { + fatal("codegen_addbyte2 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +static inline void +codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) { - if (block_pos > (BLOCK_MAX-3)) - { - fatal("codegen_addbyte3 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; + if (block_pos > (BLOCK_MAX - 3)) { + fatal("codegen_addbyte3 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +static inline void +codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - if (block_pos > (BLOCK_MAX-4)) - { - fatal("codegen_addbyte4 over! %i\n", block_pos); - CPU_BLOCK_END(); - } - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; - block_write_data[block_pos++] = vald; + if (block_pos > (BLOCK_MAX - 4)) { + fatal("codegen_addbyte4 over! %i\n", block_pos); + CPU_BLOCK_END(); + } + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } -static inline void codegen_addword(codeblock_t *block, uint16_t val) +static inline void +codegen_addword(codeblock_t *block, uint16_t val) { - if (block_pos > (BLOCK_MAX-2)) - { - fatal("codegen_addword over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint16_t *)&block_write_data[block_pos] = val; - block_pos += 2; + if (block_pos > (BLOCK_MAX - 2)) { + fatal("codegen_addword over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint16_t *) &block_write_data[block_pos] = val; + block_pos += 2; } -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(codeblock_t *block, uint32_t val) { - if (block_pos > (BLOCK_MAX-4)) - { - fatal("codegen_addlong over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos > (BLOCK_MAX - 4)) { + fatal("codegen_addlong over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static inline void codegen_addquad(codeblock_t *block, uint64_t val) +static inline void +codegen_addquad(codeblock_t *block, uint64_t val) { - if (block_pos > (BLOCK_MAX-8)) - { - fatal("codegen_addquad over! %i\n", block_pos); - CPU_BLOCK_END(); - } - *(uint64_t *)&block_write_data[block_pos] = val; - block_pos += 8; + if (block_pos > (BLOCK_MAX - 8)) { + fatal("codegen_addquad over! %i\n", block_pos); + CPU_BLOCK_END(); + } + *(uint64_t *) &block_write_data[block_pos] = val; + block_pos += 8; } -static inline void codegen_alloc_bytes(codeblock_t *block, int size) +static inline void +codegen_alloc_bytes(codeblock_t *block, int size) { - if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) - { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) { + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - /*Add a jump instruction to the new block*/ - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos + 4]); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; - } + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; + } } -static inline int is_imm8(uint32_t imm_data) +static inline int +is_imm8(uint32_t imm_data) { - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; } diff --git a/src/codegen_new/codegen_backend_x86-64_ops_sse.c b/src/codegen_new/codegen_backend_x86-64_ops_sse.c index e2a4e7044..f15b1aee4 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops_sse.c +++ b/src/codegen_new/codegen_backend_x86-64_ops_sse.c @@ -1,618 +1,678 @@ #if defined __amd64__ || defined _M_X64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops_sse.h" -#include "codegen_backend_x86-64_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops_sse.h" +# include "codegen_backend_x86-64_ops_helpers.h" -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ +} + +void +host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); +} + +void +host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ +} +void +host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ +} + +void +host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ +} +void +host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} +void +host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void +host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ +} +void +host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); +} +void +host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void +host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); +} +void +host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} + +void +host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } else if (offset < (1ull << 32)) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ + codegen_addlong(block, offset); + } else { + fatal("host_x86_LDMXCSR - out of range %p\n", p); + } } -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +void +host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ } -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +void +host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void +host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ -} -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ -} -void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ + if (src_reg & 8) + fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ -} -void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); -} -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ -} - -void host_x86_LDMXCSR(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ - } - else if (offset < (1ull << 32)) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/ - codegen_addlong(block, offset); - } - else - { - fatal("host_x86_LDMXCSR - out of range %p\n", p); - } -} - -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ -} - -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (src_reg & 8) - fatal("host_x86_MOVQ_ABS_REG reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addbyte(block, 0x25); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) -{ - if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); - - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} - -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_RSP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); -} - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (dst_reg & 8) - fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - if ((uintptr_t)p >> 32) - fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addbyte(block, 0x25); - codegen_addlong(block, (uint32_t)(uintptr_t)p); - } -} -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) -{ - if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) - fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); - - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ -} - -void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ - codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ -} -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ -} - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ -} -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p); codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { + if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n"); + + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } } -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_RSP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} + +void +host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (dst_reg & 8) + fatal("host_x86_MOVQ_REG_ABS reg & 8\n"); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + if ((uintptr_t) p >> 32) + fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p); codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addbyte(block, 0x25); + codegen_addlong(block, (uint32_t) (uintptr_t) p); + } } +void +host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) + fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n"); -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ -} -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ -} -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ -} -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ -} - -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ -} -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ -} -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ -} -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ -} -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ -} -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ -} -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ -} -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ -} -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ -} - -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ -} - -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} - -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ -} -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ -} -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ -} -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ -} -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ -} - -void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } } -void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); } -void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, 0xee); -} -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ -} -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ -} -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); } -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ -} -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/ + codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ +} +void +host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ +} + +void +host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ +} +void +host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void +host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} +void +host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); +} + +void +host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void +host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void +host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void +host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void +host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void +host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ +} + +void +host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void +host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void +host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void +host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void +host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void +host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void +host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void +host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void +host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void +host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} + +void +host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void +host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} +void +host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ +} + +void +host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + +void +host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ +} +void +host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void +host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void +host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void +host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void +host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ +} + +void +host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void +host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void +host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, 0xee); +} +void +host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + +void +host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} +void +host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} + +void +host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} +void +host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } #endif diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 9997ea738..e9c08cbc8 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -1,3165 +1,3280 @@ #if defined __amd64__ || defined _M_X64 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "x86.h" -#include "x87.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_backend.h" -#include "codegen_backend_x86-64_defs.h" -#include "codegen_backend_x86-64_ops.h" -#include "codegen_backend_x86-64_ops_sse.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x87.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_backend.h" +# include "codegen_backend_x86-64_defs.h" +# include "codegen_backend_x86-64_ops.h" +# include "codegen_backend_x86-64_ops_sse.h" +# include "codegen_ir_defs.h" -#define STACK_ARG0 (0) -#define STACK_ARG1 (4) -#define STACK_ARG2 (8) -#define STACK_ARG3 (12) +# define STACK_ARG0 (0) +# define STACK_ARG1 (4) +# define STACK_ARG2 (8) +# define STACK_ARG3 (12) -#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) +# define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) &3) | 4) : (IREG_GET_REG(reg) & 7)) -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) -static int codegen_ADD(codeblock_t *block, uop_t *uop) +static int +codegen_ADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); - else - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); - else - host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); else - fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - if (!uop->imm_data) - { - if (uop->dest_reg_a_real == uop->src_reg_a_real) - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); - else - host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - } - else if (uop->imm_data < 4) - host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); -#ifdef RECOMPILER_DEBUG + if (!uop->imm_data) { + if (uop->dest_reg_a_real == uop->src_reg_a_real) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); else - fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); -#endif - return 0; + host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + } else if (uop->imm_data < 4) + host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); +# endif + return 0; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ANDN(codeblock_t *block, uop_t *uop) +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */ src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); + host_x86_CALL(block, uop->p); - return 0; + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); -#endif - host_x86_CALL(block, uop->p); - host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); +# endif + host_x86_CALL(block, uop->p); + host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); + host_x86_CALL(block, uop->p); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); -#endif - host_x86_JZ(block, uop->p); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +# endif + host_x86_JZ(block, uop->p); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JB_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JB_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JNBE_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JNBE_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNB_long(block); - return 0; + return 0; } -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNL_long(block); - return 0; + return 0; } -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNO_long(block); - return 0; + return 0; } -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JB_long(block); - return 0; + return 0; } -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JL_long(block); - return 0; + return 0; } -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JO_long(block); - return 0; + return 0; } -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_FABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); - host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); + host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); - host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); + host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_FTST(codeblock_t *block, uop_t *uop) +static int +codegen_FTST(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_FADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FCOM(codeblock_t *block, uop_t *uop) +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FDIV(codeblock_t *block, uop_t *uop) +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_offset; - - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, 7); -#else - host_x86_MOV32_REG_IMM(block, REG_EDI, 7); -#endif - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - - return 0; -} -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) -{ - uint32_t *branch_offset; - - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, 7); -#else - host_x86_MOV32_REG_IMM(block, REG_EDI, 7); -#endif - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); - host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); - - return 0; -} - -static int codegen_JMP(codeblock_t *block, uop_t *uop) -{ - host_x86_JMP(block, uop->p); - - return 0; -} - -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(src_size)) - { -#if _WIN64 - host_x86_MOVZX_REG_32_16(block, REG_ECX, src_reg); -#else - host_x86_MOVZX_REG_32_16(block, REG_EDI, src_reg); -#endif - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) -{ -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); -#else - host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) -{ -#if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data); -#else - host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG2_IMM\n"); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG3_IMM\n"); -#endif - return 0; -} - -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); -#endif -#if _WIN64 - host_x86_MOV16_REG_REG(block, REG_CX, src_reg); - host_x86_MOV64_REG_IMM(block, REG_EDX, (uint64_t)uop->p); -#else - host_x86_MOV16_REG_REG(block, REG_DI, src_reg); - host_x86_MOV64_REG_IMM(block, REG_ESI, (uint64_t)uop->p); -#endif - host_x86_CALL(block, (void *)loadseg); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - - return 0; -} -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } - - return 0; -} -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *branch_offset; - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +# endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; - return 0; + return 0; +} +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +{ + uint32_t *branch_offset; + + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, 7); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, 7); +# endif + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + + return 0; } -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +static int +codegen_JMP(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + host_x86_JMP(block, uop->p); - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(src_size)) { +# if _WIN64 + host_x86_MOVZX_REG_32_16(block, REG_ECX, src_reg); +# else + host_x86_MOVZX_REG_32_16(block, REG_EDI, src_reg); +# endif + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) +{ +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) +{ +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data); +# else + host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG2_IMM\n"); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG3_IMM\n"); +# endif + return 0; +} + +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +# endif +# if _WIN64 + host_x86_MOV16_REG_REG(block, REG_CX, src_reg); + host_x86_MOV64_REG_IMM(block, REG_EDX, (uint64_t) uop->p); +# else + host_x86_MOV16_REG_REG(block, REG_DI, src_reg); + host_x86_MOV64_REG_IMM(block, REG_ESI, (uint64_t) uop->p); +# endif + host_x86_CALL(block, (void *) loadseg); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_x86_CALL(block, codegen_mem_load_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_Q(dest_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } + + return 0; +} +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; +} + +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_byte); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_word); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; } -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_byte); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; +} +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_word); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_long); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; } -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MOV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p); - return 0; -} -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); - host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); - host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_long(block); - - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); - - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_NOP(codeblock_t *block, uop_t *uop) -{ - return 0; -} - -static int codegen_OR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PADDB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); - host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RCPSS + iteration)*/ - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RSQRTSS + iteration)*/ - host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_SAR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - if (((uintptr_t)uop->p) >> 32) - fatal("STORE_PTR_IMM 64-bit addr\n"); -#endif - host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - if (((uintptr_t)uop->p) >> 32) - fatal("STORE_PTR_IMM_8 64-bit addr\n"); -#endif - host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} - -static int codegen_SUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (dest_reg != src_reg_a) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNS_long(block); - - return 0; -} -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JS_long(block); - - return 0; -} - -static int codegen_XOR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, - - [UOP_JMP & UOP_MASK] = codegen_JMP, - - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, - - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, - - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, - - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, - - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, - - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, - - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, - - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, - - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, - - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, - - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, - - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, - - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, - - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, - - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, - - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, - - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, - - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, - - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, - - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, - - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, - - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, - - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, - - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, - - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, - - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP + host_x86_CALL(block, codegen_mem_store_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MOV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV64_REG_IMM(block, uop->dest_reg_a_real, (uint64_t) uop->p); + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVQ_REG_XREG(block, REG_RCX, src_reg); + host_x86_CVTSI2SD_XREG_REG64(block, dest_reg, REG_RCX); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + branch_offset = host_x86_JS_long(block); + + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX); + + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); + host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RCPSS + iteration)*/ + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RSQRTSS + iteration)*/ + host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + if (((uintptr_t) uop->p) >> 32) + fatal("STORE_PTR_IMM 64-bit addr\n"); +# endif + host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + if (((uintptr_t) uop->p) >> 32) + fatal("STORE_PTR_IMM_8 64-bit addr\n"); +# endif + host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} + +static int +codegen_SUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (dest_reg != src_reg_a) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNS_long(block); + + return 0; +} +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JS_long(block); + + return 0; +} + +static int +codegen_XOR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_JMP & + UOP_MASK] + = codegen_JMP, + + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, + + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, + + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, + + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, + + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, + + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, + + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, + + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, + + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, + + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, + + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, + + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, + + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, + + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, + + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, + + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, + + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, + + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, + + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, + + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV8_REG_ABS(block, host_reg, p); + host_x86_MOV8_REG_ABS(block, host_reg, p); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV16_REG_ABS(block, host_reg, p); + host_x86_MOV16_REG_ABS(block, host_reg, p); } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV32_REG_ABS(block, host_reg, p); + host_x86_MOV32_REG_ABS(block, host_reg, p); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV64_REG_ABS(block, host_reg, p); + host_x86_MOV64_REG_ABS(block, host_reg, p); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 0); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 0); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV8_ABS_REG(block, p, host_reg); + host_x86_MOV8_ABS_REG(block, p, host_reg); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV16_ABS_REG(block, p, host_reg); + host_x86_MOV16_ABS_REG(block, p, host_reg); } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV32_ABS_REG(block, p, host_reg); + host_x86_MOV32_ABS_REG(block, p, host_reg); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV64_ABS_REG(block, p, host_reg); + host_x86_MOV64_ABS_REG(block, p, host_reg); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_RBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV64_ABS_REG(block, p, host_reg); + host_x86_MOV64_ABS_REG(block, p, host_reg); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV64_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOV64_REG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_RSP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); } -void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOV64_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOV64_BASE_OFFSET_REG(block, REG_RSP, stack_offset, host_reg); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_RSP, stack_offset, host_reg); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *) p = (uintptr_t) &block_write_data[block_pos] - ((uintptr_t) p + 4); } -void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) +void +codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) { - host_x86_MOV8_ABS_IMM(block, p, imm_data); + host_x86_MOV8_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) +void +codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) { - host_x86_MOV16_ABS_IMM(block, p, imm_data); + host_x86_MOV16_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) +void +codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) { - host_x86_MOV32_ABS_IMM(block, p, imm_data); + host_x86_MOV32_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) +void +codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) { - host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); + host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); } #endif diff --git a/src/codegen_new/codegen_backend_x86.c b/src/codegen_new/codegen_backend_x86.c index 03c9b2a34..2de794ad1 100644 --- a/src/codegen_new/codegen_backend_x86.c +++ b/src/codegen_new/codegen_backend_x86.c @@ -1,29 +1,29 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops.h" -#include "codegen_backend_x86_ops_sse.h" -#include "codegen_reg.h" -#include "x86.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops.h" +# include "codegen_backend_x86_ops_sse.h" +# include "codegen_reg.h" +# include "x86.h" -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif -#if defined WIN32 || defined _WIN32 || defined _WIN32 -#include -#endif -#include +# if defined(__linux__) || defined(__APPLE__) +# include +# include +# endif +# if defined WIN32 || defined _WIN32 || defined _WIN32 +# include +# endif +# include void *codegen_mem_load_byte; void *codegen_mem_load_word; @@ -42,306 +42,303 @@ void *codegen_mem_store_double; void *codegen_gpf_rout; void *codegen_exit_rout; -host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = -{ - /*Note: while EAX and EDX are normally volatile registers under x86 - calling conventions, the recompiler will explicitly save and restore - them across funcion calls*/ - {REG_EAX, 0}, - {REG_EBX, 0}, - {REG_EDX, 0} +host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = { + /*Note: while EAX and EDX are normally volatile registers under x86 + calling conventions, the recompiler will explicitly save and restore + them across funcion calls*/ + {REG_EAX, 0}, + { REG_EBX, 0}, + { REG_EDX, 0} }; -host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = -{ - {REG_XMM0, HOST_REG_FLAG_VOLATILE}, - {REG_XMM1, HOST_REG_FLAG_VOLATILE}, - {REG_XMM2, HOST_REG_FLAG_VOLATILE}, - {REG_XMM3, HOST_REG_FLAG_VOLATILE}, - {REG_XMM4, HOST_REG_FLAG_VOLATILE}, - {REG_XMM5, HOST_REG_FLAG_VOLATILE} +host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = { + {REG_XMM0, HOST_REG_FLAG_VOLATILE}, + { REG_XMM1, HOST_REG_FLAG_VOLATILE}, + { REG_XMM2, HOST_REG_FLAG_VOLATILE}, + { REG_XMM3, HOST_REG_FLAG_VOLATILE}, + { REG_XMM4, HOST_REG_FLAG_VOLATILE}, + { REG_XMM5, HOST_REG_FLAG_VOLATILE} }; -static void build_load_routine(codeblock_t *block, int size, int is_float) +static void +build_load_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset = NULL; + uint8_t *branch_offset; + uint8_t *misaligned_offset = NULL; - /*In - ESI = address - Out - ECX = data, ESI = abrt*/ - /*MOV ECX, ESI - SHR ESI, 12 - MOV ESI, [readlookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOVZX ECX, B[ESI+ECX] - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL readmembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_ECX, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 2 && !is_float) - host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 4 && !is_float) - host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); - else if (size == 4 && is_float) - host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else if (size == 8) - host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); - else - fatal("build_load_routine: size=%i\n", size); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + /*In - ESI = address + Out - ECX = data, ESI = abrt*/ + /*MOV ECX, ESI + SHR ESI, 12 + MOV ESI, [readlookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOVZX ECX, B[ESI+ECX] + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL readmembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_ECX, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 4 && !is_float) + host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX); + else if (size == 4 && is_float) + host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); + else if (size == 8) + host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX); + else + fatal("build_load_routine: size=%i\n", size); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - host_x86_PUSH(block, REG_EAX); - host_x86_PUSH(block, REG_EDX); - host_x86_PUSH(block, REG_ECX); - if (size == 1) - host_x86_CALL(block, (void *)readmembl); - else if (size == 2) - host_x86_CALL(block, (void *)readmemwl); - else if (size == 4) - host_x86_CALL(block, (void *)readmemll); - else if (size == 8) - host_x86_CALL(block, (void *)readmemql); - host_x86_POP(block, REG_ECX); - if (size == 1 && !is_float) - host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); - else if (size == 2 && !is_float) - host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); - else if (size == 4 && !is_float) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - else if (size == 4 && is_float) - { - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); - host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - } - else if (size == 8) - { - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); - host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); - host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2); - } - host_x86_POP(block, REG_EDX); - host_x86_POP(block, REG_EAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + host_x86_PUSH(block, REG_EAX); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + if (size == 1) + host_x86_CALL(block, (void *) readmembl); + else if (size == 2) + host_x86_CALL(block, (void *) readmemwl); + else if (size == 4) + host_x86_CALL(block, (void *) readmemll); + else if (size == 8) + host_x86_CALL(block, (void *) readmemql); + host_x86_POP(block, REG_ECX); + if (size == 1 && !is_float) + host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX); + else if (size == 2 && !is_float) + host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX); + else if (size == 4 && !is_float) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + else if (size == 4 && is_float) { + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + } else if (size == 8) { + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX); + host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX); + host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2); + } + host_x86_POP(block, REG_EDX); + host_x86_POP(block, REG_EAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; } -static void build_store_routine(codeblock_t *block, int size, int is_float) +static void +build_store_routine(codeblock_t *block, int size, int is_float) { - uint8_t *branch_offset; - uint8_t *misaligned_offset = NULL; + uint8_t *branch_offset; + uint8_t *misaligned_offset = NULL; - /*In - ECX = data, ESI = address - Out - ESI = abrt - Corrupts EDI*/ - /*MOV EDI, ESI - SHR ESI, 12 - MOV ESI, [writelookup2+ESI*4] - CMP ESI, -1 - JNZ + - MOV [ESI+EDI], ECX - XOR ESI,ESI - RET - * PUSH EAX - PUSH EDX - PUSH ECX - CALL writemembl - POP ECX - POP EDX - POP EAX - MOVZX ECX, AL - RET - */ - host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); - host_x86_SHR32_IMM(block, REG_ESI, 12); - host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2); - if (size != 1) - { - host_x86_TEST32_REG_IMM(block, REG_EDI, size-1); - misaligned_offset = host_x86_JNZ_short(block); - } - host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1); - branch_offset = host_x86_JZ_short(block); - if (size == 1 && !is_float) - host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 2 && !is_float) - host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 4 && !is_float) - host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); - else if (size == 4 && is_float) - host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); - else if (size == 8) - host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); - else - fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); - host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); - host_x86_RET(block); + /*In - ECX = data, ESI = address + Out - ESI = abrt + Corrupts EDI*/ + /*MOV EDI, ESI + SHR ESI, 12 + MOV ESI, [writelookup2+ESI*4] + CMP ESI, -1 + JNZ + + MOV [ESI+EDI], ECX + XOR ESI,ESI + RET + * PUSH EAX + PUSH EDX + PUSH ECX + CALL writemembl + POP ECX + POP EDX + POP EAX + MOVZX ECX, AL + RET + */ + host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI); + host_x86_SHR32_IMM(block, REG_ESI, 12); + host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2); + if (size != 1) { + host_x86_TEST32_REG_IMM(block, REG_EDI, size - 1); + misaligned_offset = host_x86_JNZ_short(block); + } + host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t) -1); + branch_offset = host_x86_JZ_short(block); + if (size == 1 && !is_float) + host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 2 && !is_float) + host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 4 && !is_float) + host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX); + else if (size == 4 && is_float) + host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); + else if (size == 8) + host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP); + else + fatal("build_store_routine: size=%i is_float=%i\n", size, is_float); + host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI); + host_x86_RET(block); - *branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1; - if (size != 1) - *misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1; - if (size == 4 && is_float) - host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); - host_x86_PUSH(block, REG_EAX); - host_x86_PUSH(block, REG_EDX); - host_x86_PUSH(block, REG_ECX); - if (size == 8) - { - host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); - host_x86_SUB32_REG_IMM(block, REG_ESP, 8); - } - host_x86_PUSH(block, REG_EDI); - if (size == 1) - host_x86_CALL(block, (void *)writemembl); - else if (size == 2) - host_x86_CALL(block, (void *)writememwl); - else if (size == 4) - host_x86_CALL(block, (void *)writememll); - else if (size == 8) - host_x86_CALL(block, (void *)writememql); - host_x86_POP(block, REG_EDI); - if (size == 8) - host_x86_ADD32_REG_IMM(block, REG_ESP, 8); - host_x86_POP(block, REG_ECX); - host_x86_POP(block, REG_EDX); - host_x86_POP(block, REG_EAX); - host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); - host_x86_RET(block); - block_pos = (block_pos + 63) & ~63; + *branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1; + if (size != 1) + *misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1; + if (size == 4 && is_float) + host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP); + host_x86_PUSH(block, REG_EAX); + host_x86_PUSH(block, REG_EDX); + host_x86_PUSH(block, REG_ECX); + if (size == 8) { + host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP); + host_x86_SUB32_REG_IMM(block, REG_ESP, 8); + } + host_x86_PUSH(block, REG_EDI); + if (size == 1) + host_x86_CALL(block, (void *) writemembl); + else if (size == 2) + host_x86_CALL(block, (void *) writememwl); + else if (size == 4) + host_x86_CALL(block, (void *) writememll); + else if (size == 8) + host_x86_CALL(block, (void *) writememql); + host_x86_POP(block, REG_EDI); + if (size == 8) + host_x86_ADD32_REG_IMM(block, REG_ESP, 8); + host_x86_POP(block, REG_ECX); + host_x86_POP(block, REG_EDX); + host_x86_POP(block, REG_EAX); + host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt); + host_x86_RET(block); + block_pos = (block_pos + 63) & ~63; } -static void build_loadstore_routines(codeblock_t *block) +static void +build_loadstore_routines(codeblock_t *block) { - codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 1, 0); - codegen_mem_load_word = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 2, 0); - codegen_mem_load_long = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 0); - codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 0); - codegen_mem_load_single = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 4, 1); - codegen_mem_load_double = &codeblock[block_current].data[block_pos]; - build_load_routine(block, 8, 1); + codegen_mem_load_byte = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 1, 0); + codegen_mem_load_word = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 2, 0); + codegen_mem_load_long = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 0); + codegen_mem_load_quad = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 0); + codegen_mem_load_single = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 4, 1); + codegen_mem_load_double = &codeblock[block_current].data[block_pos]; + build_load_routine(block, 8, 1); - codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 1, 0); - codegen_mem_store_word = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 2, 0); - codegen_mem_store_long = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 0); - codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 0); - codegen_mem_store_single = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 4, 1); - codegen_mem_store_double = &codeblock[block_current].data[block_pos]; - build_store_routine(block, 8, 1); + codegen_mem_store_byte = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 1, 0); + codegen_mem_store_word = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 2, 0); + codegen_mem_store_long = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 0); + codegen_mem_store_quad = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 0); + codegen_mem_store_single = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 4, 1); + codegen_mem_store_double = &codeblock[block_current].data[block_pos]; + build_store_routine(block, 8, 1); } -void codegen_backend_init(void) +void +codegen_backend_init(void) { - codeblock_t *block; - int c; + codeblock_t *block; + int c; - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); - for (c = 0; c < BLOCK_SIZE; c++) - codeblock[c].pc = BLOCK_PC_INVALID; + for (c = 0; c < BLOCK_SIZE; c++) + codeblock[c].pc = BLOCK_PC_INVALID; - block_current = 0; - block_pos = 0; - block = &codeblock[block_current]; - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block_write_data = block->data; - build_loadstore_routines(block); + block_current = 0; + block_pos = 0; + block = &codeblock[block_current]; + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block_write_data = block->data; + build_loadstore_routines(block); - codegen_gpf_rout = &codeblock[block_current].data[block_pos]; - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); - host_x86_CALL(block, (void *)x86gpf); - codegen_exit_rout = &codeblock[block_current].data[block_pos]; - host_x86_ADD32_REG_IMM(block, REG_ESP, 64); - host_x86_POP(block, REG_EDI); - host_x86_POP(block, REG_ESI); - host_x86_POP(block, REG_EBP); - host_x86_POP(block, REG_EDX); - host_x86_RET(block); - block_write_data = NULL; + codegen_gpf_rout = &codeblock[block_current].data[block_pos]; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0); + host_x86_CALL(block, (void *) x86gpf); + codegen_exit_rout = &codeblock[block_current].data[block_pos]; + host_x86_ADD32_REG_IMM(block, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); + block_write_data = NULL; - cpu_state.old_fp_control = 0; - asm( - "fstcw %0\n" - "stmxcsr %1\n" - : "=m" (cpu_state.old_fp_control2), - "=m" (cpu_state.old_fp_control) - ); - cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; + cpu_state.old_fp_control = 0; + asm( + "fstcw %0\n" + "stmxcsr %1\n" + : "=m"(cpu_state.old_fp_control2), + "=m"(cpu_state.old_fp_control)); + cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000; } -void codegen_set_rounding_mode(int mode) +void +codegen_set_rounding_mode(int mode) { - /*SSE*/ - cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); - /*x87 - used for double -> i64 conversions*/ - cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10); + /*SSE*/ + cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13); + /*x87 - used for double -> i64 conversions*/ + cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10); } -void codegen_backend_prologue(codeblock_t *block) +void +codegen_backend_prologue(codeblock_t *block) { - block_pos = BLOCK_START; /*Entry code*/ - host_x86_PUSH(block, REG_EBX); - host_x86_PUSH(block, REG_EBP); - host_x86_PUSH(block, REG_ESI); - host_x86_PUSH(block, REG_EDI); - host_x86_SUB32_REG_IMM(block, REG_ESP, 64); - host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128); - if (block->flags & CODEBLOCK_HAS_FPU) - { - host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); - host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); - host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); - } + block_pos = BLOCK_START; /*Entry code*/ + host_x86_PUSH(block, REG_EBX); + host_x86_PUSH(block, REG_EBP); + host_x86_PUSH(block, REG_ESI); + host_x86_PUSH(block, REG_EDI); + host_x86_SUB32_REG_IMM(block, REG_ESP, 64); + host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t) &cpu_state) + 128); + if (block->flags & CODEBLOCK_HAS_FPU) { + host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP); + host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX); + } } -void codegen_backend_epilogue(codeblock_t *block) +void +codegen_backend_epilogue(codeblock_t *block) { - host_x86_ADD32_REG_IMM(block, REG_ESP, 64); - host_x86_POP(block, REG_EDI); - host_x86_POP(block, REG_ESI); - host_x86_POP(block, REG_EBP); - host_x86_POP(block, REG_EDX); - host_x86_RET(block); + host_x86_ADD32_REG_IMM(block, REG_ESP, 64); + host_x86_POP(block, REG_EDI); + host_x86_POP(block, REG_ESI); + host_x86_POP(block, REG_EBP); + host_x86_POP(block, REG_EDX); + host_x86_RET(block); } #endif diff --git a/src/codegen_new/codegen_backend_x86.h b/src/codegen_new/codegen_backend_x86.h index 582e46430..646289fab 100644 --- a/src/codegen_new/codegen_backend_x86.h +++ b/src/codegen_new/codegen_backend_x86.h @@ -1,14 +1,14 @@ #include "codegen_backend_x86_defs.h" -#define BLOCK_SIZE 0x10000 -#define BLOCK_MASK 0xffff +#define BLOCK_SIZE 0x10000 +#define BLOCK_MASK 0xffff #define BLOCK_START 0 -#define HASH_SIZE 0x20000 -#define HASH_MASK 0x1ffff +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff -#define HASH(l) ((l) & 0x1ffff) +#define HASH(l) ((l) &0x1ffff) -#define BLOCK_MAX 0x3c0 +#define BLOCK_MAX 0x3c0 #define CODEGEN_BACKEND_HAS_MOV_IMM diff --git a/src/codegen_new/codegen_backend_x86_defs.h b/src/codegen_new/codegen_backend_x86_defs.h index 25964ba3c..a86d6f309 100644 --- a/src/codegen_new/codegen_backend_x86_defs.h +++ b/src/codegen_new/codegen_backend_x86_defs.h @@ -1,28 +1,28 @@ #ifndef _CODEGEN_BACKEND_X86_DEFS_H_ #define _CODEGEN_BACKEND_X86_DEFS_H_ -#define REG_EAX 0 -#define REG_ECX 1 -#define REG_EDX 2 -#define REG_EBX 3 -#define REG_ESP 4 -#define REG_EBP 5 -#define REG_ESI 6 -#define REG_EDI 7 +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 +#define REG_ESP 4 +#define REG_EBP 5 +#define REG_ESI 6 +#define REG_EDI 7 -#define REG_XMM0 0 -#define REG_XMM1 1 -#define REG_XMM2 2 -#define REG_XMM3 3 -#define REG_XMM4 4 -#define REG_XMM5 5 -#define REG_XMM6 6 -#define REG_XMM7 7 +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 -#define REG_XMM_TEMP REG_XMM7 -#define REG_XMM_TEMP2 REG_XMM6 +#define REG_XMM_TEMP REG_XMM7 +#define REG_XMM_TEMP2 REG_XMM6 -#define CODEGEN_HOST_REGS 3 +#define CODEGEN_HOST_REGS 3 #define CODEGEN_HOST_FP_REGS 6 extern void *codegen_mem_load_byte; diff --git a/src/codegen_new/codegen_backend_x86_ops.c b/src/codegen_new/codegen_backend_x86_ops.c index 5e89ffbc8..4807caacf 100644 --- a/src/codegen_new/codegen_backend_x86_ops.c +++ b/src/codegen_new/codegen_backend_x86_ops.c @@ -1,1334 +1,1311 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops.h" -#include "codegen_backend_x86_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops.h" +# include "codegen_backend_x86_ops_helpers.h" -#define RM_OP_ADD 0x00 -#define RM_OP_OR 0x08 -#define RM_OP_AND 0x20 -#define RM_OP_SUB 0x28 -#define RM_OP_XOR 0x30 -#define RM_OP_CMP 0x38 +# define RM_OP_ADD 0x00 +# define RM_OP_OR 0x08 +# define RM_OP_AND 0x20 +# define RM_OP_SUB 0x28 +# define RM_OP_XOR 0x30 +# define RM_OP_CMP 0x38 -#define RM_OP_ROL 0x00 -#define RM_OP_ROR 0x08 -#define RM_OP_SHL 0x20 -#define RM_OP_SHR 0x28 -#define RM_OP_SAR 0x38 +# define RM_OP_ROL 0x00 +# define RM_OP_ROR 0x08 +# define RM_OP_SHL 0x20 +# define RM_OP_SHR 0x28 +# define RM_OP_SAR 0x38 -void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ - } -} -void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ -} -void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ + codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/ + } } - -void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ - } -} -void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ -} -void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ -} -void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ -} - -void host_x86_CALL(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xe8); /*CALL*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} - -void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} -void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ -} - -void host_x86_INC32_ABS(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ - codegen_addlong(block, (uint32_t)p); -} - -void host_x86_JMP(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} -uint32_t *host_x86_JMP_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} - -void host_x86_JNZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} -void host_x86_JZ(codeblock_t *block, void *p) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block_write_data[block_pos + 4]); -} - -uint8_t *host_x86_JNZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x75, 0); /*JNZ*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JS_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x78, 0); /*JS*/ - return &block_write_data[block_pos-1]; -} -uint8_t *host_x86_JZ_short(codeblock_t *block) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x74, 0); /*JZ*/ - return &block_write_data[block_pos-1]; -} - -uint32_t *host_x86_JNB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JNZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JB_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JBE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JL_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JLE_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JO_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JS_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} -uint32_t *host_x86_JZ_long(codeblock_t *block) -{ - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ - codegen_addlong(block, 0); - return (uint32_t *)&block_write_data[block_pos-4]; -} - -void host_x86_LAHF(codeblock_t *block) -{ - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x9f); /*LAHF*/ -} - -void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) -{ - if (offset) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ - codegen_addlong(block, offset); - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ - } -} - -void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ -} -void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ -} - -void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ - codegen_addbyte(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addbyte(block, imm_data); - } -} -void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0xc7, 0x05); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addword(block, imm_data); - } -} -void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 10); - codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ - codegen_addlong(block, (uint32_t)p); - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (src_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} - -void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ -} -void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +void +host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +void +host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) +void +host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ - codegen_addbyte(block, 0x05 | (dst_reg << 3)); - codegen_addlong(block, (uint32_t)p); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg << 3)); /*ADD dst_reg, src_reg*/ } -void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) +void +host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/ + } +} +void +host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ +} +void +host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ +} +void +host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg << 3)); /*AND dst_reg, src_reg_b*/ +} + +void +host_x86_CALL(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe8); /*CALL*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} + +void +host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x3d); /*CMP AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } +} +void +host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x38, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} +void +host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/ +} + +void +host_x86_INC32_ABS(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xff, 0x05); /*INC p*/ + codegen_addlong(block, (uint32_t) p); +} + +void +host_x86_JMP(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} +uint32_t * +host_x86_JMP_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} + +void +host_x86_JNZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} +void +host_x86_JZ(codeblock_t *block, void *p) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, (uintptr_t) p - (uintptr_t) &block_write_data[block_pos + 4]); +} + +uint8_t * +host_x86_JNZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x75, 0); /*JNZ*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JS_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x78, 0); /*JS*/ + return &block_write_data[block_pos - 1]; +} +uint8_t * +host_x86_JZ_short(codeblock_t *block) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x74, 0); /*JZ*/ + return &block_write_data[block_pos - 1]; +} + +uint32_t * +host_x86_JNB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x83); /*JNB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x87); /*JNBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8d); /*JNL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8f); /*JNLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x81); /*JNO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x89); /*JNS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JNZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JB_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x82); /*JB*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JBE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x86); /*JBE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JL_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8c); /*JL*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JLE_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x8e); /*JLE*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JO_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x80); /*JO*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JS_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x88); /*JS*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} +uint32_t * +host_x86_JZ_long(codeblock_t *block) +{ + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/ + codegen_addlong(block, 0); + return (uint32_t *) &block_write_data[block_pos - 4]; +} + +void +host_x86_LAHF(codeblock_t *block) +{ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x9f); /*LAHF*/ +} + +void +host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset) +{ + if (offset) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/ + codegen_addlong(block, offset); + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/ + } +} + +void +host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b]*/ +} +void +host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/ +} + +void +host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/ + codegen_addbyte(block, imm_data); + } else { codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ - codegen_addlong(block, (uint32_t)p); + codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/ + codegen_addlong(block, (uint32_t) p); + codegen_addbyte(block, imm_data); + } +} +void +host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 9); + codegen_addbyte3(block, 0x66, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) p); + codegen_addword(block, imm_data); + } +} +void +host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/ + codegen_addlong(block, (uint32_t) p); + codegen_addlong(block, imm_data); + } } -void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int idx_reg, int shift) +void +host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) { - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ - codegen_addlong(block, addr); - } -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ + codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } } +void +host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); - } - } - else - fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); -} - -void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); -} -void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); - } - } - else - fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); -} - -void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); - codegen_addlong(block, imm_data); - } - } - else - fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); -} - -void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ -} -void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (!imm_data) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (!imm_data) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); -} - -void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) -{ - if (!offset) - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else if (offset >= -0x80 && offset < 0x80) - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 11); - codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ - codegen_addlong(block, offset); - codegen_addlong(block, imm_data); - } -} - -void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x89, 0x05 | (src_reg << 3)); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ -} -void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ + codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (src_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x66); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg) { + if (addr < 0x80 || addr >= 0xffffff80) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ -} -void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ + codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } } -void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +void +host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/ +} +void +host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/ +} +void +host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/ +} + +void +host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8a, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x8a); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } +} +void +host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ + codegen_addbyte4(block, 0x66, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x8b, 0x05 | (dst_reg << 3)); /*MOV [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +void +host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p) { + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/ + codegen_addbyte(block, 0x05 | (dst_reg << 3)); + codegen_addlong(block, (uint32_t) p); + } +} + +void +host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift) +{ + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/ + codegen_addlong(block, (uint32_t) p); +} + +void +host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int idx_reg, int shift) +{ + if (addr < 0x80 || addr >= 0xffffff80) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ + codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x8a, 0x84 | (dst_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ + codegen_addlong(block, addr); + } } -void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/ } -void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV16_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x8b, 0x40 | base_reg | (dst_reg << 3), offset); + } + } else + fatal("MOV32_REG_BASE_OFFSET - offset %i\n", offset); +} + +void +host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV16_BASE_OFFSET_REG - offset %i\n", offset); +} +void +host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x89, 0x40 | base_reg | (src_reg << 3), 0x24, offset); + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x89, 0x40 | base_reg | (src_reg << 3), offset); + } + } else + fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset); +} + +void +host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset); + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset); + codegen_addlong(block, imm_data); + } + } else + fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset); +} + +void +host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/ +} +void +host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (!imm_data) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (!imm_data) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/ + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +void +host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +void +host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3)); } -void host_x86_POP(codeblock_t *block, int src_reg) +void +host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data) { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ + if (!offset) { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else if (offset >= -0x80 && offset < 0x80) { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 11); + codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/ + codegen_addlong(block, offset); + codegen_addlong(block, imm_data); + } } -void host_x86_PUSH(codeblock_t *block, int src_reg) +void +host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ +} +void +host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xbf, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/ } -void host_x86_RET(codeblock_t *block) +void +host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p) { - codegen_alloc_bytes(block, 1); - codegen_addbyte(block, 0xc3); /*RET*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x66); + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } else { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +void +host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ + codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ -} + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); -void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) - -void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +void +host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} +void +host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ +} + +void +host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/ +} +void +host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/ +} + +void +host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ +} +void +host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ +} +void +host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg << 3)); /*OR dst_reg, src_reg_b*/ +} + +void +host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} -void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) -{ + codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/ + } } -void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ -} - -void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ -} -void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +void +host_x86_POP(codeblock_t *block, int src_reg) { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ -} -void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ } -void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PUSH(codeblock_t *block, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/ } -void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) + +void +host_x86_RET(codeblock_t *block) { + codegen_alloc_bytes(block, 1); + codegen_addbyte(block, 0xc3); /*RET*/ +} + +void +host_x86_ROL8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_ROL32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_ROR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_ROR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +# define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3)) + +void +host_x86_SAR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} +void +host_x86_SAR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ +} + +void +host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} +void +host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ +} + +void +host_x86_SHL8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} +void +host_x86_SHL32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ +} + +void +host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} +void +host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ +} + +void +host_x86_SHR8_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR16_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} +void +host_x86_SHR32_CL(codeblock_t *block, int dst_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ +} + +void +host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} +void +host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ +} + +void +host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ + } else { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ + } +} +void +host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +{ + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} -void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ -} - -void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} -void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ -} - -void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ -} -void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) -{ + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } -void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } -void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +void +host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/ - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) +void +host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +void +host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ } -void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ +} +void +host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) +{ + if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } +} + +void +host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ +} +void +host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ +} +void +host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ +} + +void +host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) +{ + if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ -} -void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ + codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ + } else { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ + codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ + } } -void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg << 3)); /*SUB dst_reg, src_reg*/ + if (is_imm8(imm_data)) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 4); + codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ + codegen_addword(block, imm_data); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addword(block, imm_data); + } } - -void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) +void +host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { + if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/ -} -void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } -} - -void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ -} -void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg << 3)); /*XOR dst_reg, src_reg*/ -} - -void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) -{ - if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/ - } - else - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/ - } -} -void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/ - codegen_addword(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addword(block, imm_data); - } -} -void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) -{ - if (is_imm8(imm_data)) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ - } - else if (dst_reg == REG_EAX) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ - codegen_addlong(block, imm_data); - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ - codegen_addlong(block, imm_data); - } + codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/ + } else if (dst_reg == REG_EAX) { + codegen_alloc_bytes(block, 5); + codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/ + codegen_addlong(block, imm_data); + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/ + codegen_addlong(block, imm_data); + } } #endif diff --git a/src/codegen_new/codegen_backend_x86_ops.h b/src/codegen_new/codegen_backend_x86_ops.h index 53b6e0e73..0890286ef 100644 --- a/src/codegen_new/codegen_backend_x86_ops.h +++ b/src/codegen_new/codegen_backend_x86_ops.h @@ -27,7 +27,7 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b); void host_x86_INC32_ABS(codeblock_t *block, void *p); -void host_x86_JMP(codeblock_t *block, void *p); +void host_x86_JMP(codeblock_t *block, void *p); uint32_t *host_x86_JMP_short(codeblock_t *block); uint32_t *host_x86_JMP_long(codeblock_t *block); diff --git a/src/codegen_new/codegen_backend_x86_ops_fpu.c b/src/codegen_new/codegen_backend_x86_ops_fpu.c index cb8f36ac6..13f90743a 100644 --- a/src/codegen_new/codegen_backend_x86_ops_fpu.c +++ b/src/codegen_new/codegen_backend_x86_ops_fpu.c @@ -1,84 +1,74 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops_fpu.h" -#include "codegen_backend_x86_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops_fpu.h" +# include "codegen_backend_x86_ops_helpers.h" -void host_x87_FILDq_BASE(codeblock_t *block, int base_reg) +void +host_x87_FILDq_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/ + } } -void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) +void +host_x87_FISTPq_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/ + } } -void host_x87_FLDCW(codeblock_t *block, void *p) +void +host_x87_FLDCW(codeblock_t *block, void *p) { - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ - } - else - { - codegen_alloc_bytes(block, 6); - codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ - codegen_addlong(block, (uint32_t)p); - } + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/ + } else { + codegen_alloc_bytes(block, 6); + codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/ + codegen_addlong(block, (uint32_t) p); + } } -void host_x87_FLDd_BASE(codeblock_t *block, int base_reg) +void +host_x87_FLDd_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/ + } } -void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) +void +host_x87_FSTPd_BASE(codeblock_t *block, int base_reg) { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ - } - else - { - codegen_alloc_bytes(block, 2); - codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ - } + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/ + } else { + codegen_alloc_bytes(block, 2); + codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/ + } } #endif diff --git a/src/codegen_new/codegen_backend_x86_ops_helpers.h b/src/codegen_new/codegen_backend_x86_ops_helpers.h index 3fca4f4d2..0a6469a89 100644 --- a/src/codegen_new/codegen_backend_x86_ops_helpers.h +++ b/src/codegen_new/codegen_backend_x86_ops_helpers.h @@ -1,84 +1,94 @@ #define JMP_LEN_BYTES 5 -static inline void codegen_addbyte(codeblock_t *block, uint8_t val) +static inline void +codegen_addbyte(codeblock_t *block, uint8_t val) { - if (block_pos >= BLOCK_MAX) - fatal("codegen_addbyte over! %i\n", block_pos); - block_write_data[block_pos++] = val; + if (block_pos >= BLOCK_MAX) + fatal("codegen_addbyte over! %i\n", block_pos); + block_write_data[block_pos++] = val; } -static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) +static inline void +codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb) { - if (block_pos > (BLOCK_MAX-2)) - fatal("codegen_addbyte2 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; + if (block_pos > (BLOCK_MAX - 2)) + fatal("codegen_addbyte2 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; } -static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) +static inline void +codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc) { - if (block_pos > (BLOCK_MAX-3)) - fatal("codegen_addbyte3 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; + if (block_pos > (BLOCK_MAX - 3)) + fatal("codegen_addbyte3 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; } -static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) +static inline void +codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald) { - if (block_pos > (BLOCK_MAX-4)) - fatal("codegen_addbyte4 over! %i\n", block_pos); - block_write_data[block_pos++] = vala; - block_write_data[block_pos++] = valb; - block_write_data[block_pos++] = valc; - block_write_data[block_pos++] = vald; + if (block_pos > (BLOCK_MAX - 4)) + fatal("codegen_addbyte4 over! %i\n", block_pos); + block_write_data[block_pos++] = vala; + block_write_data[block_pos++] = valb; + block_write_data[block_pos++] = valc; + block_write_data[block_pos++] = vald; } -static inline void codegen_addword(codeblock_t *block, uint16_t val) +static inline void +codegen_addword(codeblock_t *block, uint16_t val) { - if (block_pos > (BLOCK_MAX-2)) - fatal("codegen_addword over! %i\n", block_pos); - *(uint16_t *)&block_write_data[block_pos] = val; - block_pos += 2; + if (block_pos > (BLOCK_MAX - 2)) + fatal("codegen_addword over! %i\n", block_pos); + *(uint16_t *) &block_write_data[block_pos] = val; + block_pos += 2; } -static inline void codegen_addlong(codeblock_t *block, uint32_t val) +static inline void +codegen_addlong(codeblock_t *block, uint32_t val) { - if (block_pos > (BLOCK_MAX-4)) - fatal("codegen_addlong over! %i\n", block_pos); - *(uint32_t *)&block_write_data[block_pos] = val; - block_pos += 4; + if (block_pos > (BLOCK_MAX - 4)) + fatal("codegen_addlong over! %i\n", block_pos); + *(uint32_t *) &block_write_data[block_pos] = val; + block_pos += 4; } -static inline void codegen_addquad(codeblock_t *block, uint64_t val) +static inline void +codegen_addquad(codeblock_t *block, uint64_t val) { - if (block_pos > (BLOCK_MAX-8)) - fatal("codegen_addquad over! %i\n", block_pos); - *(uint64_t *)&block_write_data[block_pos] = val; - block_pos += 8; + if (block_pos > (BLOCK_MAX - 8)) + fatal("codegen_addquad over! %i\n", block_pos); + *(uint64_t *) &block_write_data[block_pos] = val; + block_pos += 8; } -static void codegen_allocate_new_block(codeblock_t *block) +static void +codegen_allocate_new_block(codeblock_t *block) { - /*Current block is full. Allocate a new block*/ - struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); - uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); + /*Current block is full. Allocate a new block*/ + struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block)); + uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block); - /*Add a jump instruction to the new block*/ - codegen_addbyte(block, 0xe9); /*JMP*/ - codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]); + /*Add a jump instruction to the new block*/ + codegen_addbyte(block, 0xe9); /*JMP*/ + codegen_addlong(block, (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos + 4]); - /*Set write address to start of new block*/ - block_pos = 0; - block_write_data = new_ptr; + /*Set write address to start of new block*/ + block_pos = 0; + block_write_data = new_ptr; } -static inline void codegen_alloc_bytes(codeblock_t *block, int size) +static inline void +codegen_alloc_bytes(codeblock_t *block, int size) { - if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) - codegen_allocate_new_block(block); + if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) + codegen_allocate_new_block(block); } -static inline int is_imm8(uint32_t imm_data) +static inline int +is_imm8(uint32_t imm_data) { - if (imm_data <= 0x7f || imm_data >= 0xffffff80) - return 1; - return 0; + if (imm_data <= 0x7f || imm_data >= 0xffffff80) + return 1; + return 0; } diff --git a/src/codegen_new/codegen_backend_x86_ops_sse.c b/src/codegen_new/codegen_backend_x86_ops_sse.c index 0ab461e74..a1e04db30 100644 --- a/src/codegen_new/codegen_backend_x86_ops_sse.c +++ b/src/codegen_new/codegen_backend_x86_ops_sse.c @@ -1,578 +1,629 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops_sse.h" -#include "codegen_backend_x86_ops_helpers.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops_sse.h" +# include "codegen_backend_x86_ops_helpers.h" -void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/ } -void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) +void +host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/ } -void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) +void +host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3)); } -void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/ } -void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/ } -void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/ } -void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/ } -void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } -void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/ } -void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +void +host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} + +void +host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ +} +void +host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ +} + +void +host_x86_LDMXCSR(codeblock_t *block, void *p) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ + } else { + codegen_alloc_bytes(block, 7); + codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ + codegen_addlong(block, (uint32_t) p); + } +} + +void +host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ +} + +void +host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); +} +void +host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) +{ + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } } - -void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/ -} -void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/ -} - -void host_x86_LDMXCSR(codeblock_t *block, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/ - } - else - { - codegen_alloc_bytes(block, 7); - codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/ - codegen_addlong(block, (uint32_t)p); - } -} - -void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/ -} - -void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3)); -} -void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ - codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); -} -void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) -{ - if (!offset) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ - codegen_addbyte(block, 0x24); - } - else if (offset >= -0x80 && offset < 0x80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ - codegen_addbyte2(block, 0x24, offset & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ - codegen_addbyte(block, 0x24); - codegen_addlong(block, offset); - } - -} - -void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) -{ - int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128); - - if (offset >= -128 && offset < 127) - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ - codegen_addbyte(block, offset); - } - else - { - codegen_alloc_bytes(block, 8); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ - codegen_addlong(block, (uint32_t)p); - } -} -void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) -{ - if (addr < 0x80 || addr >= 0xffffff80) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); - } - else - { - codegen_alloc_bytes(block, 9); - codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ - codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); - codegen_addlong(block, addr); - } -} -void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ - codegen_addbyte(block, base_reg | (idx_reg << 3)); -} -void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) -{ - if (offset >= -128 && offset < 127) - { - if (base_reg == REG_ESP) - { - codegen_alloc_bytes(block, 6); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ - codegen_addbyte2(block, 0x24, offset); - } - else - { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ - codegen_addbyte(block, offset); - } - } - else - fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); -} -void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ -} - -void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ -} -void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ -} - -void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ -} -void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); -} - -void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg) { + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/ + codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } } -void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset); +} +void +host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg) +{ + if (!offset) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ + codegen_addbyte(block, 0x24); + } else if (offset >= -0x80 && offset < 0x80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte2(block, 0x24, offset & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ + codegen_addbyte(block, 0x24); + codegen_addlong(block, offset); + } } -void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) + +void +host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p) { + int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); + + if (offset >= -128 && offset < 127) { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/ + codegen_addbyte(block, offset); + } else { + codegen_alloc_bytes(block, 8); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/ + codegen_addlong(block, (uint32_t) p); + } +} +void +host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift) +{ + if (addr < 0x80 || addr >= 0xffffff80) { + codegen_alloc_bytes(block, 6); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff); + } else { codegen_alloc_bytes(block, 9); - codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ - codegen_addbyte(block, 0x88); + codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/ + codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6)); + codegen_addlong(block, addr); + } +} +void +host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/ + codegen_addbyte(block, base_reg | (idx_reg << 3)); +} +void +host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) +{ + if (offset >= -128 && offset < 127) { + if (base_reg == REG_ESP) { + codegen_alloc_bytes(block, 6); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/ + codegen_addbyte2(block, 0x24, offset); + } else { + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/ + codegen_addbyte(block, offset); + } + } else + fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset); +} +void +host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/ } -void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/ } -void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ -} -void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ -} -void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ -} -void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ -} -void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/ } -void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/ } -void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ -} -void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ -} -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); } -void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); } -void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); } -void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ -} -void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ -} -void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ -} -void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 9); + codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/ + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/ + codegen_addbyte(block, 0x88); } -void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } -void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ } -void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/ +} +void +host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/ +} +void +host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/ +} +void +host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } -void host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle) +void +host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | src_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ - codegen_addbyte(block, shuffle); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ +} +void +host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/ +} +void +host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ +} +void +host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ } -void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ } -void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ } -void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ } -void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ } -void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ } -void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +void +host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); -} -void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) -{ - codegen_alloc_bytes(block, 5); - codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ - codegen_addbyte(block, shift); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ } -void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } -void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } -void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ -} -void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ -} -void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ -} -void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ -} -void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/ } -void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ -} -void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ -} -void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | src_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/ + codegen_addbyte(block, shuffle); } -void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); } -void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void +host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_alloc_bytes(block, 5); + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); } -void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ } -void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 4); - codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/ +} +void +host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/ +} +void +host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/ +} +void +host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/ +} +void +host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/ +} +void +host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } -void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +void +host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { - codegen_alloc_bytes(block, 3); - codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/ +} +void +host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/ +} + +void +host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/ +} +void +host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/ +} + +void +host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/ +} +void +host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 4); + codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); +} + +void +host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3)); } #endif diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index 3f7e2dd9a..83844b3cd 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -1,3164 +1,3286 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/mem.h> +# include +# include <86box/86box.h> +# include "cpu.h" +# include <86box/mem.h> -#include "x86.h" -#include "x86_ops.h" -#include "386_common.h" -#include "codegen.h" -#include "codegen_allocator.h" -#include "codegen_backend.h" -#include "codegen_backend_x86_defs.h" -#include "codegen_backend_x86_ops.h" -#include "codegen_backend_x86_ops_fpu.h" -#include "codegen_backend_x86_ops_sse.h" -#include "codegen_ir_defs.h" +# include "x86.h" +# include "x86_ops.h" +# include "386_common.h" +# include "codegen.h" +# include "codegen_allocator.h" +# include "codegen_backend.h" +# include "codegen_backend_x86_defs.h" +# include "codegen_backend_x86_ops.h" +# include "codegen_backend_x86_ops_fpu.h" +# include "codegen_backend_x86_ops_sse.h" +# include "codegen_ir_defs.h" -#define HOST_REG_IS_L(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_L) -#define HOST_REG_IS_W(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_W) -#define HOST_REG_IS_B(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_B && IREG_GET_REG(reg) < 4) -#define HOST_REG_IS_BH(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_BH && IREG_GET_REG(reg) < 4) +# define HOST_REG_IS_L(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_L) +# define HOST_REG_IS_W(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_W) +# define HOST_REG_IS_B(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_B && IREG_GET_REG(reg) < 4) +# define HOST_REG_IS_BH(reg) (IREG_GET_SIZE(reg) == IREG_SIZE_BH && IREG_GET_REG(reg) < 4) -#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7)) +# define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) &3) | 4) : (IREG_GET_REG(reg) & 7)) -#define REG_IS_L(size) (size == IREG_SIZE_L) -#define REG_IS_W(size) (size == IREG_SIZE_W) -#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) -#define REG_IS_BH(size) (size == IREG_SIZE_BH) -#define REG_IS_D(size) (size == IREG_SIZE_D) -#define REG_IS_Q(size) (size == IREG_SIZE_Q) +# define REG_IS_L(size) (size == IREG_SIZE_L) +# define REG_IS_W(size) (size == IREG_SIZE_W) +# define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH) +# define REG_IS_BH(size) (size == IREG_SIZE_BH) +# define REG_IS_D(size) (size == IREG_SIZE_D) +# define REG_IS_Q(size) (size == IREG_SIZE_Q) -static int codegen_ADD(codeblock_t *block, uop_t *uop) +static int +codegen_ADD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); - else - host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_REG(block, dest_reg, src_reg_a, src_reg_b); else - fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + host_x86_ADD32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_ADD8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_ADD_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); - else - host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_LEA_REG_IMM(block, dest_reg, src_reg, uop->imm_data); else - fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + host_x86_ADD32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ADD16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ADD8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ADD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) +static int +codegen_ADD_LSHIFT(codeblock_t *block, uop_t *uop) { - if (!uop->imm_data) - { - if (uop->dest_reg_a_real == uop->src_reg_a_real) - host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); - else - host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); - } - else if (uop->imm_data < 4) - host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); -#ifdef RECOMPILER_DEBUG + if (!uop->imm_data) { + if (uop->dest_reg_a_real == uop->src_reg_a_real) + host_x86_ADD32_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_b_real); else - fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); -#endif - return 0; + host_x86_LEA_REG_REG(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + } else if (uop->imm_data < 4) + host_x86_LEA_REG_REG_SHIFT(block, uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real, uop->imm_data); +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_ADD_LSHIFT - shift out of range %i\n", uop->imm_data); +# endif + return 0; } -static int codegen_AND(codeblock_t *block, uop_t *uop) +static int +codegen_AND(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PAND_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_AND8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_AND_IMM(codeblock_t *block, uop_t *uop) +static int +codegen_AND_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_AND32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_AND16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_AND8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("AND_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; } -static int codegen_ANDN(codeblock_t *block, uop_t *uop) +static int +codegen_ANDN(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), /*src_reg_a = HOST_REG_GET(uop->src_reg_a_real), */ src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PANDN_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ANDN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); + host_x86_CALL(block, uop->p); - return 0; + return 0; } -static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_L(dest_size)) - fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); -#endif - host_x86_CALL(block, uop->p); - host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); + if (!REG_IS_L(dest_size)) + fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real); +# endif + host_x86_CALL(block, uop->p); + host_x86_MOV32_REG_REG(block, dest_reg, REG_EAX); - return 0; + return 0; } -static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) +static int +codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { - host_x86_CALL(block, uop->p); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); -// host_x86_CALL(block, codegen_debug); + host_x86_CALL(block, uop->p); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); + // host_x86_CALL(block, codegen_debug); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); -#endif - host_x86_JZ(block, uop->p); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real); +# endif + host_x86_JZ(block, uop->p); - return 0; + return 0; } -static int codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_IMM_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_L(src_size)) - { - host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); - } - else if (REG_IS_W(src_size)) - { - host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size)) { + host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_CMP16_REG_IMM(block, src_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_IMM_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JB_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JB_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - uint32_t *jump_p; + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *jump_p; - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); -#endif - jump_p = host_x86_JNBE_long(block); - *jump_p = (uintptr_t)uop->p - ((uintptr_t)jump_p + 4); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE %02x\n", uop->src_reg_a_real); +# endif + jump_p = host_x86_JNBE_long(block); + *jump_p = (uintptr_t) uop->p - ((uintptr_t) jump_p + 4); - return 0; + return 0; } -static int codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNB_long(block); - return 0; + return 0; } -static int codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNL_long(block); - return 0; + return 0; } -static int codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNO_long(block); - return 0; + return 0; } -static int codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JNZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JNZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNZ_long(block); - return 0; + return 0; } -static int codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JB_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JB_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JB_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JB_long(block); - return 0; + return 0; } -static int codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JBE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JBE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JBE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JBE_long(block); - return 0; + return 0; } -static int codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JL_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JL_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JL_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JL_long(block); - return 0; + return 0; } -static int codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JLE_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JLE_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JLE_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JLE_long(block); - return 0; + return 0; } -static int codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JO_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JO_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JO_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JO_long(block); - return 0; + return 0; } -static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) +static int +codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop) { - int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); - } - else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JZ_long(block); + if (REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + host_x86_CMP32_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + host_x86_CMP16_REG_REG(block, src_reg_a, src_reg_b); + } else if (REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + host_x86_CMP8_REG_REG(block, src_reg_a, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("CMP_JZ_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JZ_long(block); - return 0; + return 0; } -static int codegen_FABS(codeblock_t *block, uop_t *uop) +static int +codegen_FABS(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); - host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && dest_reg == src_reg_a) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, dest_reg); + host_x86_MAXSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_FCHS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); + host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_FSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { + host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_FTST(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) { + host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FCHS(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); - host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); +static int +codegen_FADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_FCOM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + if (dest_reg != REG_EAX) + host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); + host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); + host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); + host_x86_LAHF(block); + host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + if (dest_reg != REG_EAX) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); + host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FSQRT(codeblock_t *block, uop_t *uop) +static int +codegen_FDIV(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_SQRTSD_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FTST(codeblock_t *block, uop_t *uop) +static int +codegen_FMUL(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a)) - { - host_x86_PXOR_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP); - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_FSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) { + host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; } -static int codegen_FADD(codeblock_t *block, uop_t *uop) +static int +codegen_FP_ENTER(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + uint32_t *branch_offset; - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_ADDSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FCOM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; - if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - if (dest_reg != REG_EAX) - host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX); - host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); - host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); - host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0|C2|C3); - if (dest_reg != REG_EAX) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); - host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); - } - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FDIV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_DIVSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_DIVSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_MULSD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_FSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a) - { - host_x86_SUBSD_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBSD_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; + return 0; } -static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) { - uint32_t *branch_offset; + uint32_t *branch_offset; - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; + host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); + host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); + branch_offset = host_x86_JZ_long(block); + host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); + host_x86_CALL(block, x86_int); + host_x86_JMP(block, codegen_exit_rout); + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); + host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); + host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); - return 0; + return 0; } -static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) +static int +codegen_JMP(codeblock_t *block, uop_t *uop) { - uint32_t *branch_offset; + host_x86_JMP(block, uop->p); - host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0); - host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc); - branch_offset = host_x86_JZ_long(block); - host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data); - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7); - host_x86_CALL(block, x86_int); - host_x86_JMP(block, codegen_exit_rout); - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101); - host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0); - host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1); + return 0; +} +static int +codegen_JMP_DEST(codeblock_t *block, uop_t *uop) +{ + uop->p = host_x86_JMP_long(block); - return 0; + return 0; } -static int codegen_JMP(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) { - host_x86_JMP(block, uop->p); + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - return 0; -} -static int codegen_JMP_DEST(codeblock_t *block, uop_t *uop) -{ - uop->p = host_x86_JMP_long(block); - - return 0; -} - -static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_W(src_size)) - { - host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) -{ -#ifdef RECOMPILER_DEBUG - fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG2, uop->imm_data); - return 0; -} -static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_STACK_IMM(block, STACK_ARG3, uop->imm_data); - return 0; -} - -static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (!REG_IS_W(src_size)) - fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); -#endif + if (REG_IS_W(src_size)) { host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); - host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t)uop->p); - host_x86_CALL(block, loadseg); - host_x86_TEST32_REG(block, REG_EAX, REG_EAX); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; + } +# ifdef RECOMPILER_DEBUG + else + fatal("codegen_LOAD_FUNC_ARG0 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG1(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG1 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG2(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG2 %02x\n", uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) +{ +# ifdef RECOMPILER_DEBUG + fatal("codegen_LOAD_FUNC_ARG3 %02x\n", uop->src_reg_a_real); +# endif + return 0; } -static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - - return 0; + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); + return 0; } -static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_byte); - } - else if (REG_IS_W(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_word); - } - else if (REG_IS_L(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_long); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_CALL(block, codegen_mem_load_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_Q(dest_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } - - return 0; + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, uop->imm_data); + return 0; } -static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + host_x86_MOV32_STACK_IMM(block, STACK_ARG2, uop->imm_data); + return 0; +} +static int +codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_STACK_IMM(block, STACK_ARG3, uop->imm_data); + return 0; +} - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); +static int +codegen_LOAD_SEG(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (!REG_IS_W(src_size)) + fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p); +# endif + host_x86_MOV16_STACK_REG(block, STACK_ARG0, src_reg); + host_x86_MOV32_STACK_IMM(block, STACK_ARG1, (uint32_t) uop->p); + host_x86_CALL(block, loadseg); + host_x86_TEST32_REG(block, REG_EAX, REG_EAX); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } + + return 0; +} +static int +codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(dest_size)) { + host_x86_CALL(block, codegen_mem_load_byte); + } else if (REG_IS_W(dest_size)) { + host_x86_CALL(block, codegen_mem_load_word); + } else if (REG_IS_L(dest_size)) { + host_x86_CALL(block, codegen_mem_load_long); + } else if (REG_IS_Q(dest_size)) { + host_x86_CALL(block, codegen_mem_load_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_Q(dest_size)) { host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } - return 0; + return 0; +} +static int +codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + + return 0; } -static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); -#ifdef RECOMPILER_DEBUG - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); +# ifdef RECOMPILER_DEBUG + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - if (!REG_IS_D(dest_size)) - fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CALL(block, codegen_mem_load_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + if (!REG_IS_D(dest_size)) + fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CALL(block, codegen_mem_load_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - return 0; + return 0; } -static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); - int src_size = IREG_GET_SIZE(uop->src_reg_b_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real); + int src_size = IREG_GET_SIZE(uop->src_reg_b_real); - host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - if (REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_byte); - } - else if (REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_word); - } - else if (REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); - host_x86_CALL(block, codegen_mem_store_long); - } - else if (REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_quad); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); -#endif - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_byte); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_word); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); - - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); host_x86_CALL(block, codegen_mem_store_long); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); - return 0; + return 0; } -static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +static int +codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop) { - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); - host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_single); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} -static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); -#ifdef RECOMPILER_DEBUG - int src_size = IREG_GET_SIZE(uop->src_reg_c_real); - - if (!REG_IS_D(src_size)) - fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); -#endif - host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); - if (uop->imm_data) - host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + if (REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_byte); + } else if (REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_word); + } else if (REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, REG_ECX, src_reg); + host_x86_CALL(block, codegen_mem_store_long); + } else if (REG_IS_Q(src_size)) { host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); - host_x86_CALL(block, codegen_mem_store_double); - host_x86_TEST32_REG(block, REG_ESI, REG_ESI); - host_x86_JNZ(block, codegen_exit_rout); - - return 0; -} - -static int codegen_MOV(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t)uop->p); - return 0; -} -static int codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); - } - else if (REG_IS_B(dest_size)) - { - host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size)) - { - host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); - } - else if (REG_IS_W(dest_size)) - { - host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); - } - else - fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); - - return 0; -} -static int codegen_MOVSX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOVZX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) - { - host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) - { - host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); - } - else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) - { - host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_D(dest_size) && REG_IS_L(src_size)) - { - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); - } - else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) - { - host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); - host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); - } - else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) - { - /*There is no SSE instruction to convert a 64-bit integer to a floating point value. - Instead we have to bounce the integer through memory via x87.*/ - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); - host_x87_FILDq_BASE(block, REG_ESP); - host_x87_FSTPd_BASE(block, REG_ESP); - host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } - else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) - { - host_x86_LDMXCSR(block, &cpu_state.new_fp_control); - host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); - host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) - { - uint32_t *branch_offset; - - /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ - host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); - host_x86_TEST8_REG(block, tag_reg, tag_reg); - branch_offset = host_x86_JS_long(block); - - /*There is no SSE instruction to convert a floating point value to a 64-bit integer. - Instead we have to bounce through memory via x87.*/ - host_x87_FLDCW(block, &cpu_state.new_fp_control2); - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); - host_x87_FLDd_BASE(block, REG_ESP); - host_x87_FISTPq_BASE(block, REG_ESP); - host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); - host_x87_FLDCW(block, &cpu_state.old_fp_control2); - - *branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4; - } -#ifdef RECOMPILER_DEBUG - else - fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_NOP(codeblock_t *block, uop_t *uop) -{ - return 0; -} - -static int codegen_OR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_OR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_L(dest_size) && dest_reg == src_reg) - { - host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && dest_reg == src_reg) - { - host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && dest_reg == src_reg) - { - host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PACKUSWB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PADDB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PCMPEQB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPEQD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PF2ID(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); - host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); - host_x86_LDMXCSR(block, &cpu_state.old_fp_control); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFADD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMAX(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMIN(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFMUL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PFRCP(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RCPSS + iteration)*/ - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - /*TODO: This could be improved (use RSQRTSS + iteration)*/ - host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_MOV32_REG_IMM(block, REG_ECX, 1); - host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); - host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} -static int codegen_PFSUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) - { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); - host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PI2FD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) - { - host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); -#endif - return 0; -} - -static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULHW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PMULLW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); - - if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_PSUBB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PSUBUSW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); - host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); - host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); - host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} - -static int codegen_ROL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_ROR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_SAR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SAR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHL_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_CL(block, dest_reg); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_CL(block, dest_reg); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_CL(block, dest_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} -static int codegen_SHR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} -static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} -static int codegen_STORE_PTR_IMM_16(codeblock_t *block, uop_t *uop) -{ - host_x86_MOV16_ABS_IMM(block, uop->p, uop->imm_data); - return 0; -} - -static int codegen_SUB(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) - { - if (uop->dest_reg_a_real != uop->src_reg_a_real) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); - host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_SUB_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV32_REG_REG(block, dest_reg, src_reg); - host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV16_REG_REG(block, dest_reg, src_reg); - host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) - { - if (dest_reg != src_reg) - host_x86_MOV8_REG_REG(block, dest_reg, src_reg); - host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -static int codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JNS_long(block); - - return 0; -} -static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) -{ - int src_reg = HOST_REG_GET(uop->src_reg_a_real); - int src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(src_size)) - { - host_x86_TEST32_REG(block, src_reg, src_reg); - } - else if (REG_IS_W(src_size)) - { - host_x86_TEST16_REG(block, src_reg, src_reg); - } - else if (REG_IS_B(src_size)) - { - host_x86_TEST8_REG(block, src_reg, src_reg); - } -#ifdef RECOMPILER_DEBUG - else - fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); -#endif - uop->p = host_x86_JS_long(block); - - return 0; -} - -static int codegen_XOR(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); - } - else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); -#endif - return 0; -} -static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop) -{ - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); - - if (REG_IS_L(dest_size) && REG_IS_L(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); - } - else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) - { - host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); - } -#ifdef RECOMPILER_DEBUG - else - fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); -#endif - return 0; -} - -#ifdef DEBUG_EXTRA -static int codegen_LOG_INSTR(codeblock_t *block, uop_t *uop) -{ - if (uop->imm_data > 256*256) - fatal("LOG_INSTR %08x\n", uop->imm_data); - host_x86_INC32_ABS(block, &instr_counts[uop->imm_data]); - return 0; -} -#endif - -const uOpFn uop_handlers[UOP_MAX] = -{ - [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, - [UOP_CALL_FUNC_RESULT & UOP_MASK] = codegen_CALL_FUNC_RESULT, - [UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC, - - [UOP_JMP & UOP_MASK] = codegen_JMP, - [UOP_JMP_DEST & UOP_MASK] = codegen_JMP_DEST, - - [UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG, - - [UOP_LOAD_FUNC_ARG_0 & UOP_MASK] = codegen_LOAD_FUNC_ARG0, - [UOP_LOAD_FUNC_ARG_1 & UOP_MASK] = codegen_LOAD_FUNC_ARG1, - [UOP_LOAD_FUNC_ARG_2 & UOP_MASK] = codegen_LOAD_FUNC_ARG2, - [UOP_LOAD_FUNC_ARG_3 & UOP_MASK] = codegen_LOAD_FUNC_ARG3, - - [UOP_LOAD_FUNC_ARG_0_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG0_IMM, - [UOP_LOAD_FUNC_ARG_1_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG1_IMM, - [UOP_LOAD_FUNC_ARG_2_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG2_IMM, - [UOP_LOAD_FUNC_ARG_3_IMM & UOP_MASK] = codegen_LOAD_FUNC_ARG3_IMM, - - [UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM, - [UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8, - [UOP_STORE_P_IMM_16 & UOP_MASK] = codegen_STORE_PTR_IMM_16, - - [UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS, - [UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG, - [UOP_MEM_LOAD_SINGLE & UOP_MASK] = codegen_MEM_LOAD_SINGLE, - [UOP_MEM_LOAD_DOUBLE & UOP_MASK] = codegen_MEM_LOAD_DOUBLE, - - [UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS, - [UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG, - [UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8, - [UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16, - [UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32, - [UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE, - [UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE, - - [UOP_MOV & UOP_MASK] = codegen_MOV, - [UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR, - [UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM, - [UOP_MOVSX & UOP_MASK] = codegen_MOVSX, - [UOP_MOVZX & UOP_MASK] = codegen_MOVZX, - [UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT, - [UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE, - [UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64, - [UOP_MOV_REG_PTR & UOP_MASK] = codegen_MOV_REG_PTR, - [UOP_MOVZX_REG_PTR_8 & UOP_MASK] = codegen_MOVZX_REG_PTR_8, - [UOP_MOVZX_REG_PTR_16 & UOP_MASK] = codegen_MOVZX_REG_PTR_16, - - [UOP_ADD & UOP_MASK] = codegen_ADD, - [UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM, - [UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT, - [UOP_AND & UOP_MASK] = codegen_AND, - [UOP_AND_IMM & UOP_MASK] = codegen_AND_IMM, - [UOP_ANDN & UOP_MASK] = codegen_ANDN, - [UOP_OR & UOP_MASK] = codegen_OR, - [UOP_OR_IMM & UOP_MASK] = codegen_OR_IMM, - [UOP_SUB & UOP_MASK] = codegen_SUB, - [UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM, - [UOP_XOR & UOP_MASK] = codegen_XOR, - [UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM, - - [UOP_SAR & UOP_MASK] = codegen_SAR, - [UOP_SAR_IMM & UOP_MASK] = codegen_SAR_IMM, - [UOP_SHL & UOP_MASK] = codegen_SHL, - [UOP_SHL_IMM & UOP_MASK] = codegen_SHL_IMM, - [UOP_SHR & UOP_MASK] = codegen_SHR, - [UOP_SHR_IMM & UOP_MASK] = codegen_SHR_IMM, - [UOP_ROL & UOP_MASK] = codegen_ROL, - [UOP_ROL_IMM & UOP_MASK] = codegen_ROL_IMM, - [UOP_ROR & UOP_MASK] = codegen_ROR, - [UOP_ROR_IMM & UOP_MASK] = codegen_ROR_IMM, - - [UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ, - - [UOP_CMP_JB & UOP_MASK] = codegen_CMP_JB, - [UOP_CMP_JNBE & UOP_MASK] = codegen_CMP_JNBE, - - [UOP_CMP_JNB_DEST & UOP_MASK] = codegen_CMP_JNB_DEST, - [UOP_CMP_JNBE_DEST & UOP_MASK] = codegen_CMP_JNBE_DEST, - [UOP_CMP_JNL_DEST & UOP_MASK] = codegen_CMP_JNL_DEST, - [UOP_CMP_JNLE_DEST & UOP_MASK] = codegen_CMP_JNLE_DEST, - [UOP_CMP_JNO_DEST & UOP_MASK] = codegen_CMP_JNO_DEST, - [UOP_CMP_JNZ_DEST & UOP_MASK] = codegen_CMP_JNZ_DEST, - [UOP_CMP_JB_DEST & UOP_MASK] = codegen_CMP_JB_DEST, - [UOP_CMP_JBE_DEST & UOP_MASK] = codegen_CMP_JBE_DEST, - [UOP_CMP_JL_DEST & UOP_MASK] = codegen_CMP_JL_DEST, - [UOP_CMP_JLE_DEST & UOP_MASK] = codegen_CMP_JLE_DEST, - [UOP_CMP_JO_DEST & UOP_MASK] = codegen_CMP_JO_DEST, - [UOP_CMP_JZ_DEST & UOP_MASK] = codegen_CMP_JZ_DEST, - - [UOP_CMP_IMM_JNZ_DEST & UOP_MASK] = codegen_CMP_IMM_JNZ_DEST, - [UOP_CMP_IMM_JZ_DEST & UOP_MASK] = codegen_CMP_IMM_JZ_DEST, - - [UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST, - [UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST, - - [UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER, - [UOP_MMX_ENTER & UOP_MASK] = codegen_MMX_ENTER, - - [UOP_FADD & UOP_MASK] = codegen_FADD, - [UOP_FDIV & UOP_MASK] = codegen_FDIV, - [UOP_FMUL & UOP_MASK] = codegen_FMUL, - [UOP_FSUB & UOP_MASK] = codegen_FSUB, - [UOP_FCOM & UOP_MASK] = codegen_FCOM, - - [UOP_FABS & UOP_MASK] = codegen_FABS, - [UOP_FCHS & UOP_MASK] = codegen_FCHS, - [UOP_FSQRT & UOP_MASK] = codegen_FSQRT, - [UOP_FTST & UOP_MASK] = codegen_FTST, - - [UOP_PACKSSWB & UOP_MASK] = codegen_PACKSSWB, - [UOP_PACKSSDW & UOP_MASK] = codegen_PACKSSDW, - [UOP_PACKUSWB & UOP_MASK] = codegen_PACKUSWB, - - [UOP_PADDB & UOP_MASK] = codegen_PADDB, - [UOP_PADDW & UOP_MASK] = codegen_PADDW, - [UOP_PADDD & UOP_MASK] = codegen_PADDD, - [UOP_PADDSB & UOP_MASK] = codegen_PADDSB, - [UOP_PADDSW & UOP_MASK] = codegen_PADDSW, - [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, - [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, - - [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, - [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, - [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, - [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, - [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, - [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, - - [UOP_PF2ID & UOP_MASK] = codegen_PF2ID, - [UOP_PFADD & UOP_MASK] = codegen_PFADD, - [UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ, - [UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE, - [UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT, - [UOP_PFMAX & UOP_MASK] = codegen_PFMAX, - [UOP_PFMIN & UOP_MASK] = codegen_PFMIN, - [UOP_PFMUL & UOP_MASK] = codegen_PFMUL, - [UOP_PFRCP & UOP_MASK] = codegen_PFRCP, - [UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT, - [UOP_PFSUB & UOP_MASK] = codegen_PFSUB, - [UOP_PI2FD & UOP_MASK] = codegen_PI2FD, - - [UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD, - [UOP_PMULHW & UOP_MASK] = codegen_PMULHW, - [UOP_PMULLW & UOP_MASK] = codegen_PMULLW, - - [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, - [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, - [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, - [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, - [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, - [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, - [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, - [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, - [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, - - [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, - [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, - [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, - [UOP_PSUBSB & UOP_MASK] = codegen_PSUBSB, - [UOP_PSUBSW & UOP_MASK] = codegen_PSUBSW, - [UOP_PSUBUSB & UOP_MASK] = codegen_PSUBUSB, - [UOP_PSUBUSW & UOP_MASK] = codegen_PSUBUSW, - - [UOP_PUNPCKHBW & UOP_MASK] = codegen_PUNPCKHBW, - [UOP_PUNPCKHWD & UOP_MASK] = codegen_PUNPCKHWD, - [UOP_PUNPCKHDQ & UOP_MASK] = codegen_PUNPCKHDQ, - [UOP_PUNPCKLBW & UOP_MASK] = codegen_PUNPCKLBW, - [UOP_PUNPCKLWD & UOP_MASK] = codegen_PUNPCKLWD, - [UOP_PUNPCKLDQ & UOP_MASK] = codegen_PUNPCKLDQ, - - [UOP_NOP_BARRIER & UOP_MASK] = codegen_NOP, - -#ifdef DEBUG_EXTRA - [UOP_LOG_INSTR & UOP_MASK] = codegen_LOG_INSTR -#endif + host_x86_CALL(block, codegen_mem_store_quad); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real); +# endif + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_byte); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_word); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real); + + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_CALL(block, codegen_mem_store_long); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_CVTSD2SS_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_single); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} +static int +codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real); +# ifdef RECOMPILER_DEBUG + int src_size = IREG_GET_SIZE(uop->src_reg_c_real); + + if (!REG_IS_D(src_size)) + fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real); +# endif + host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg); + if (uop->imm_data) + host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg); + host_x86_CALL(block, codegen_mem_store_double); + host_x86_TEST32_REG(block, REG_ESI, REG_ESI); + host_x86_JNZ(block, codegen_exit_rout); + + return 0; +} + +static int +codegen_MOV(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_D(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_IMM %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_PTR(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_REG_IMM(block, uop->dest_reg_a_real, (uint32_t) uop->p); + return 0; +} +static int +codegen_MOV_REG_PTR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOV32_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOV_REG_PTR %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_8(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_8(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOVZX_REG_ABS_16_8(block, dest_reg, uop->p); + } else if (REG_IS_B(dest_size)) { + host_x86_MOV8_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_8 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVZX_REG_PTR_16(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size)) { + host_x86_MOVZX_REG_ABS_32_16(block, dest_reg, uop->p); + } else if (REG_IS_W(dest_size)) { + host_x86_MOV16_REG_ABS(block, dest_reg, uop->p); + } else + fatal("MOVZX_REG_PTR_16 %02x\n", uop->dest_reg_a_real); + + return 0; +} +static int +codegen_MOVSX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVSX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVSX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOVZX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_L(src_size)) { + host_x86_MOVD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { + host_x86_MOVD_REG_XREG(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVZX_REG_32_16(block, dest_reg, src_reg); + } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_32_8(block, dest_reg, src_reg); + } else if (REG_IS_W(dest_size) && REG_IS_B(src_size)) { + host_x86_MOVZX_REG_16_8(block, dest_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOVZX %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_D(dest_size) && REG_IS_L(src_size)) { + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, src_reg); + } else if (REG_IS_D(dest_size) && REG_IS_W(src_size)) { + host_x86_MOVSX_REG_32_16(block, REG_ECX, src_reg); + host_x86_CVTSI2SD_XREG_REG(block, dest_reg, REG_ECX); + } else if (REG_IS_D(dest_size) && REG_IS_Q(src_size)) { + /*There is no SSE instruction to convert a 64-bit integer to a floating point value. + Instead we have to bounce the integer through memory via x87.*/ + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FILDq_BASE(block, REG_ESP); + host_x87_FSTPd_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_DOUBLE_INT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } else if (REG_IS_W(dest_size) && REG_IS_D(src_size)) { + host_x86_LDMXCSR(block, &cpu_state.new_fp_control); + host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg); + host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size)) { + uint32_t *branch_offset; + + /*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/ + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg); + host_x86_TEST8_REG(block, tag_reg, tag_reg); + branch_offset = host_x86_JS_long(block); + + /*There is no SSE instruction to convert a floating point value to a 64-bit integer. + Instead we have to bounce through memory via x87.*/ + host_x87_FLDCW(block, &cpu_state.new_fp_control2); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg); + host_x87_FLDd_BASE(block, REG_ESP); + host_x87_FISTPq_BASE(block, REG_ESP); + host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0); + host_x87_FLDCW(block, &cpu_state.old_fp_control2); + + *branch_offset = (uint32_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 4; + } +# ifdef RECOMPILER_DEBUG + else + fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_NOP(codeblock_t *block, uop_t *uop) +{ + return 0; +} + +static int +codegen_OR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_POR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_OR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_OR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_L(dest_size) && dest_reg == src_reg) { + host_x86_OR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && dest_reg == src_reg) { + host_x86_OR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && dest_reg == src_reg) { + host_x86_OR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("OR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PACKSSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKSSDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKSSDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PACKUSWB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PACKUSWB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PADDB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PADDUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PADDUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PADDUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PCMPEQB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPEQD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PCMPGTD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PF2ID(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_LDMXCSR(block, &cpu_state.trunc_fp_control); + host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_LDMXCSR(block, &cpu_state.old_fp_control); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFADD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPEQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGE(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFCMPGT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMAX(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMIN(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFMUL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PFRCP(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RCPSS + iteration)*/ + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFRSQRT(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + /*TODO: This could be improved (use RSQRTSS + iteration)*/ + host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_MOV32_REG_IMM(block, REG_ECX, 1); + host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX); + host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} +static int +codegen_PFSUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { + host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); + host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b); + host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PI2FD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) { + host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real); +# endif + return 0; +} + +static int +codegen_PMADDWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMADDWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULHW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULHW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PMULLW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PMULLW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PMULLW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_PSUBB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSB_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PSUBUSW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PSUBUSW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PSUBUSW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/ + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKHDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLBW(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLBW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLWD(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLWD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_PUNPCKLDQ(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("PUNPCKLDQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} + +static int +codegen_ROL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_ROR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_ROR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_ROR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_ROR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("ROR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_SAR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SAR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SAR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SAR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SAR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SAR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHL_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHL32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHL16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHL8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHL_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), shift_reg = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + host_x86_MOV32_REG_REG(block, REG_ECX, shift_reg); + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_CL(block, dest_reg); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_CL(block, dest_reg); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_CL(block, dest_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} +static int +codegen_SHR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SHR32_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SHR16_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SHR8_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SHR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_STORE_PTR_IMM(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV32_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int +codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} +static int +codegen_STORE_PTR_IMM_16(codeblock_t *block, uop_t *uop) +{ + host_x86_MOV16_ABS_IMM(block, uop->p, uop->imm_data); + return 0; +} + +static int +codegen_SUB(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b)) { + if (uop->dest_reg_a_real != uop->src_reg_a_real) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg_a); + host_x86_SUB8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_SUB_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV32_REG_REG(block, dest_reg, src_reg); + host_x86_SUB32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV16_REG_REG(block, dest_reg, src_reg); + host_x86_SUB16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size)) { + if (dest_reg != src_reg) + host_x86_MOV8_REG_REG(block, dest_reg, src_reg); + host_x86_SUB8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("SUB_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +static int +codegen_TEST_JNS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JNS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JNS_long(block); + + return 0; +} +static int +codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop) +{ + int src_reg = HOST_REG_GET(uop->src_reg_a_real); + int src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(src_size)) { + host_x86_TEST32_REG(block, src_reg, src_reg); + } else if (REG_IS_W(src_size)) { + host_x86_TEST16_REG(block, src_reg, src_reg); + } else if (REG_IS_B(src_size)) { + host_x86_TEST8_REG(block, src_reg, src_reg); + } +# ifdef RECOMPILER_DEBUG + else + fatal("TEST_JS_DEST %02x\n", uop->src_reg_a_real); +# endif + uop->p = host_x86_JS_long(block); + + return 0; +} + +static int +codegen_XOR(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_PXOR_XREG_XREG(block, dest_reg, src_reg_b); + } else if (REG_IS_L(dest_size) && REG_IS_L(src_size_a) && REG_IS_L(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR32_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size_a) && REG_IS_W(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR16_REG_REG(block, dest_reg, src_reg_b); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size_a) && REG_IS_B(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR8_REG_REG(block, dest_reg, src_reg_b); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); +# endif + return 0; +} +static int +codegen_XOR_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_L(dest_size) && REG_IS_L(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR32_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_W(dest_size) && REG_IS_W(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR16_REG_IMM(block, dest_reg, uop->imm_data); + } else if (REG_IS_B(dest_size) && REG_IS_B(src_size) && uop->dest_reg_a_real == uop->src_reg_a_real) { + host_x86_XOR8_REG_IMM(block, dest_reg, uop->imm_data); + } +# ifdef RECOMPILER_DEBUG + else + fatal("XOR_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); +# endif + return 0; +} + +# ifdef DEBUG_EXTRA +static int +codegen_LOG_INSTR(codeblock_t *block, uop_t *uop) +{ + if (uop->imm_data > 256 * 256) + fatal("LOG_INSTR %08x\n", uop->imm_data); + host_x86_INC32_ABS(block, &instr_counts[uop->imm_data]); + return 0; +} +# endif + +const uOpFn uop_handlers[UOP_MAX] = { + [UOP_CALL_FUNC & UOP_MASK] = codegen_CALL_FUNC, + [UOP_CALL_FUNC_RESULT & + UOP_MASK] + = codegen_CALL_FUNC_RESULT, + [UOP_CALL_INSTRUCTION_FUNC & + UOP_MASK] + = codegen_CALL_INSTRUCTION_FUNC, + + [UOP_JMP & + UOP_MASK] + = codegen_JMP, + [UOP_JMP_DEST & + UOP_MASK] + = codegen_JMP_DEST, + + [UOP_LOAD_SEG & + UOP_MASK] + = codegen_LOAD_SEG, + + [UOP_LOAD_FUNC_ARG_0 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0, + [UOP_LOAD_FUNC_ARG_1 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1, + [UOP_LOAD_FUNC_ARG_2 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2, + [UOP_LOAD_FUNC_ARG_3 & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3, + + [UOP_LOAD_FUNC_ARG_0_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG0_IMM, + [UOP_LOAD_FUNC_ARG_1_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG1_IMM, + [UOP_LOAD_FUNC_ARG_2_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG2_IMM, + [UOP_LOAD_FUNC_ARG_3_IMM & + UOP_MASK] + = codegen_LOAD_FUNC_ARG3_IMM, + + [UOP_STORE_P_IMM & + UOP_MASK] + = codegen_STORE_PTR_IMM, + [UOP_STORE_P_IMM_8 & + UOP_MASK] + = codegen_STORE_PTR_IMM_8, + [UOP_STORE_P_IMM_16 & + UOP_MASK] + = codegen_STORE_PTR_IMM_16, + + [UOP_MEM_LOAD_ABS & + UOP_MASK] + = codegen_MEM_LOAD_ABS, + [UOP_MEM_LOAD_REG & + UOP_MASK] + = codegen_MEM_LOAD_REG, + [UOP_MEM_LOAD_SINGLE & + UOP_MASK] + = codegen_MEM_LOAD_SINGLE, + [UOP_MEM_LOAD_DOUBLE & + UOP_MASK] + = codegen_MEM_LOAD_DOUBLE, + + [UOP_MEM_STORE_ABS & + UOP_MASK] + = codegen_MEM_STORE_ABS, + [UOP_MEM_STORE_REG & + UOP_MASK] + = codegen_MEM_STORE_REG, + [UOP_MEM_STORE_IMM_8 & + UOP_MASK] + = codegen_MEM_STORE_IMM_8, + [UOP_MEM_STORE_IMM_16 & + UOP_MASK] + = codegen_MEM_STORE_IMM_16, + [UOP_MEM_STORE_IMM_32 & + UOP_MASK] + = codegen_MEM_STORE_IMM_32, + [UOP_MEM_STORE_SINGLE & + UOP_MASK] + = codegen_MEM_STORE_SINGLE, + [UOP_MEM_STORE_DOUBLE & + UOP_MASK] + = codegen_MEM_STORE_DOUBLE, + + [UOP_MOV & + UOP_MASK] + = codegen_MOV, + [UOP_MOV_PTR & + UOP_MASK] + = codegen_MOV_PTR, + [UOP_MOV_IMM & + UOP_MASK] + = codegen_MOV_IMM, + [UOP_MOVSX & + UOP_MASK] + = codegen_MOVSX, + [UOP_MOVZX & + UOP_MASK] + = codegen_MOVZX, + [UOP_MOV_DOUBLE_INT & + UOP_MASK] + = codegen_MOV_DOUBLE_INT, + [UOP_MOV_INT_DOUBLE & + UOP_MASK] + = codegen_MOV_INT_DOUBLE, + [UOP_MOV_INT_DOUBLE_64 & + UOP_MASK] + = codegen_MOV_INT_DOUBLE_64, + [UOP_MOV_REG_PTR & + UOP_MASK] + = codegen_MOV_REG_PTR, + [UOP_MOVZX_REG_PTR_8 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_8, + [UOP_MOVZX_REG_PTR_16 & + UOP_MASK] + = codegen_MOVZX_REG_PTR_16, + + [UOP_ADD & + UOP_MASK] + = codegen_ADD, + [UOP_ADD_IMM & + UOP_MASK] + = codegen_ADD_IMM, + [UOP_ADD_LSHIFT & + UOP_MASK] + = codegen_ADD_LSHIFT, + [UOP_AND & + UOP_MASK] + = codegen_AND, + [UOP_AND_IMM & + UOP_MASK] + = codegen_AND_IMM, + [UOP_ANDN & + UOP_MASK] + = codegen_ANDN, + [UOP_OR & + UOP_MASK] + = codegen_OR, + [UOP_OR_IMM & + UOP_MASK] + = codegen_OR_IMM, + [UOP_SUB & + UOP_MASK] + = codegen_SUB, + [UOP_SUB_IMM & + UOP_MASK] + = codegen_SUB_IMM, + [UOP_XOR & + UOP_MASK] + = codegen_XOR, + [UOP_XOR_IMM & + UOP_MASK] + = codegen_XOR_IMM, + + [UOP_SAR & + UOP_MASK] + = codegen_SAR, + [UOP_SAR_IMM & + UOP_MASK] + = codegen_SAR_IMM, + [UOP_SHL & + UOP_MASK] + = codegen_SHL, + [UOP_SHL_IMM & + UOP_MASK] + = codegen_SHL_IMM, + [UOP_SHR & + UOP_MASK] + = codegen_SHR, + [UOP_SHR_IMM & + UOP_MASK] + = codegen_SHR_IMM, + [UOP_ROL & + UOP_MASK] + = codegen_ROL, + [UOP_ROL_IMM & + UOP_MASK] + = codegen_ROL_IMM, + [UOP_ROR & + UOP_MASK] + = codegen_ROR, + [UOP_ROR_IMM & + UOP_MASK] + = codegen_ROR_IMM, + + [UOP_CMP_IMM_JZ & + UOP_MASK] + = codegen_CMP_IMM_JZ, + + [UOP_CMP_JB & + UOP_MASK] + = codegen_CMP_JB, + [UOP_CMP_JNBE & + UOP_MASK] + = codegen_CMP_JNBE, + + [UOP_CMP_JNB_DEST & + UOP_MASK] + = codegen_CMP_JNB_DEST, + [UOP_CMP_JNBE_DEST & + UOP_MASK] + = codegen_CMP_JNBE_DEST, + [UOP_CMP_JNL_DEST & + UOP_MASK] + = codegen_CMP_JNL_DEST, + [UOP_CMP_JNLE_DEST & + UOP_MASK] + = codegen_CMP_JNLE_DEST, + [UOP_CMP_JNO_DEST & + UOP_MASK] + = codegen_CMP_JNO_DEST, + [UOP_CMP_JNZ_DEST & + UOP_MASK] + = codegen_CMP_JNZ_DEST, + [UOP_CMP_JB_DEST & + UOP_MASK] + = codegen_CMP_JB_DEST, + [UOP_CMP_JBE_DEST & + UOP_MASK] + = codegen_CMP_JBE_DEST, + [UOP_CMP_JL_DEST & + UOP_MASK] + = codegen_CMP_JL_DEST, + [UOP_CMP_JLE_DEST & + UOP_MASK] + = codegen_CMP_JLE_DEST, + [UOP_CMP_JO_DEST & + UOP_MASK] + = codegen_CMP_JO_DEST, + [UOP_CMP_JZ_DEST & + UOP_MASK] + = codegen_CMP_JZ_DEST, + + [UOP_CMP_IMM_JNZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JNZ_DEST, + [UOP_CMP_IMM_JZ_DEST & + UOP_MASK] + = codegen_CMP_IMM_JZ_DEST, + + [UOP_TEST_JNS_DEST & + UOP_MASK] + = codegen_TEST_JNS_DEST, + [UOP_TEST_JS_DEST & + UOP_MASK] + = codegen_TEST_JS_DEST, + + [UOP_FP_ENTER & + UOP_MASK] + = codegen_FP_ENTER, + [UOP_MMX_ENTER & + UOP_MASK] + = codegen_MMX_ENTER, + + [UOP_FADD & + UOP_MASK] + = codegen_FADD, + [UOP_FDIV & + UOP_MASK] + = codegen_FDIV, + [UOP_FMUL & + UOP_MASK] + = codegen_FMUL, + [UOP_FSUB & + UOP_MASK] + = codegen_FSUB, + [UOP_FCOM & + UOP_MASK] + = codegen_FCOM, + + [UOP_FABS & + UOP_MASK] + = codegen_FABS, + [UOP_FCHS & + UOP_MASK] + = codegen_FCHS, + [UOP_FSQRT & + UOP_MASK] + = codegen_FSQRT, + [UOP_FTST & + UOP_MASK] + = codegen_FTST, + + [UOP_PACKSSWB & + UOP_MASK] + = codegen_PACKSSWB, + [UOP_PACKSSDW & + UOP_MASK] + = codegen_PACKSSDW, + [UOP_PACKUSWB & + UOP_MASK] + = codegen_PACKUSWB, + + [UOP_PADDB & + UOP_MASK] + = codegen_PADDB, + [UOP_PADDW & + UOP_MASK] + = codegen_PADDW, + [UOP_PADDD & + UOP_MASK] + = codegen_PADDD, + [UOP_PADDSB & + UOP_MASK] + = codegen_PADDSB, + [UOP_PADDSW & + UOP_MASK] + = codegen_PADDSW, + [UOP_PADDUSB & + UOP_MASK] + = codegen_PADDUSB, + [UOP_PADDUSW & + UOP_MASK] + = codegen_PADDUSW, + + [UOP_PCMPEQB & + UOP_MASK] + = codegen_PCMPEQB, + [UOP_PCMPEQW & + UOP_MASK] + = codegen_PCMPEQW, + [UOP_PCMPEQD & + UOP_MASK] + = codegen_PCMPEQD, + [UOP_PCMPGTB & + UOP_MASK] + = codegen_PCMPGTB, + [UOP_PCMPGTW & + UOP_MASK] + = codegen_PCMPGTW, + [UOP_PCMPGTD & + UOP_MASK] + = codegen_PCMPGTD, + + [UOP_PF2ID & + UOP_MASK] + = codegen_PF2ID, + [UOP_PFADD & + UOP_MASK] + = codegen_PFADD, + [UOP_PFCMPEQ & + UOP_MASK] + = codegen_PFCMPEQ, + [UOP_PFCMPGE & + UOP_MASK] + = codegen_PFCMPGE, + [UOP_PFCMPGT & + UOP_MASK] + = codegen_PFCMPGT, + [UOP_PFMAX & + UOP_MASK] + = codegen_PFMAX, + [UOP_PFMIN & + UOP_MASK] + = codegen_PFMIN, + [UOP_PFMUL & + UOP_MASK] + = codegen_PFMUL, + [UOP_PFRCP & + UOP_MASK] + = codegen_PFRCP, + [UOP_PFRSQRT & + UOP_MASK] + = codegen_PFRSQRT, + [UOP_PFSUB & + UOP_MASK] + = codegen_PFSUB, + [UOP_PI2FD & + UOP_MASK] + = codegen_PI2FD, + + [UOP_PMADDWD & + UOP_MASK] + = codegen_PMADDWD, + [UOP_PMULHW & + UOP_MASK] + = codegen_PMULHW, + [UOP_PMULLW & + UOP_MASK] + = codegen_PMULLW, + + [UOP_PSLLW_IMM & + UOP_MASK] + = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & + UOP_MASK] + = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & + UOP_MASK] + = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & + UOP_MASK] + = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & + UOP_MASK] + = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & + UOP_MASK] + = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & + UOP_MASK] + = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & + UOP_MASK] + = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & + UOP_MASK] + = codegen_PSRLQ_IMM, + + [UOP_PSUBB & + UOP_MASK] + = codegen_PSUBB, + [UOP_PSUBW & + UOP_MASK] + = codegen_PSUBW, + [UOP_PSUBD & + UOP_MASK] + = codegen_PSUBD, + [UOP_PSUBSB & + UOP_MASK] + = codegen_PSUBSB, + [UOP_PSUBSW & + UOP_MASK] + = codegen_PSUBSW, + [UOP_PSUBUSB & + UOP_MASK] + = codegen_PSUBUSB, + [UOP_PSUBUSW & + UOP_MASK] + = codegen_PSUBUSW, + + [UOP_PUNPCKHBW & + UOP_MASK] + = codegen_PUNPCKHBW, + [UOP_PUNPCKHWD & + UOP_MASK] + = codegen_PUNPCKHWD, + [UOP_PUNPCKHDQ & + UOP_MASK] + = codegen_PUNPCKHDQ, + [UOP_PUNPCKLBW & + UOP_MASK] + = codegen_PUNPCKLBW, + [UOP_PUNPCKLWD & + UOP_MASK] + = codegen_PUNPCKLWD, + [UOP_PUNPCKLDQ & + UOP_MASK] + = codegen_PUNPCKLDQ, + + [UOP_NOP_BARRIER & + UOP_MASK] + = codegen_NOP, + +# ifdef DEBUG_EXTRA + [UOP_LOG_INSTR & + UOP_MASK] + = codegen_LOG_INSTR +# endif }; -void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_8(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV8_REG_ABS(block, host_reg, p); + host_x86_MOV8_REG_ABS(block, host_reg, p); } -void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_16(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV16_REG_ABS(block, host_reg, p); + host_x86_MOV16_REG_ABS(block, host_reg, p); } -void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_32(codeblock_t *block, int host_reg, void *p) { - host_x86_MOV32_REG_ABS(block, host_reg, p); + host_x86_MOV32_REG_ABS(block, host_reg, p); } -void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p) { - codegen_direct_read_32(block, host_reg, p); + codegen_direct_read_32(block, host_reg, p); } -void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_64(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) +void +codegen_direct_read_double(codeblock_t *block, int host_reg, void *p) { - host_x86_MOVQ_XREG_ABS(block, host_reg, p); + host_x86_MOVQ_XREG_ABS(block, host_reg, p); } -void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 0); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 0); } -void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } -void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) +void +codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3); } -void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_8(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV8_ABS_REG(block, p, host_reg); + host_x86_MOV8_ABS_REG(block, p, host_reg); } -void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_16(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV16_ABS_REG(block, p, host_reg); + host_x86_MOV16_ABS_REG(block, p, host_reg); } -void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_32(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV32_ABS_REG(block, p, host_reg); + host_x86_MOV32_ABS_REG(block, p, host_reg); } -void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_64(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_double(codeblock_t *block, void *p, int host_reg) { - host_x86_MOVQ_ABS_XREG(block, p, host_reg); + host_x86_MOVQ_ABS_XREG(block, p, host_reg); } -void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg); } -void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) +void +codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg) { - int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128); + int offset = (uintptr_t) base - (((uintptr_t) &cpu_state) + 128); - host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); - host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); - host_x86_AND32_REG_IMM(block, REG_ECX, 7); - host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); + host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset); + host_x86_ADD32_REG_IMM(block, REG_ECX, reg_idx); + host_x86_AND32_REG_IMM(block, REG_ECX, 7); + host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(block, offset, REG_EBP, REG_ECX, 3, host_reg); } -void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) +void +codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg) { - host_x86_MOV32_ABS_REG(block, p, host_reg); + host_x86_MOV32_ABS_REG(block, p, host_reg); } -void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOV16_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOV32_REG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset) { - codegen_direct_read_32_stack(block, host_reg, stack_offset); + codegen_direct_read_32_stack(block, host_reg, stack_offset); } -void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) +void +codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { - host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); + host_x86_MOVQ_XREG_BASE_OFFSET(block, host_reg, REG_ESP, stack_offset); } -void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); + host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, stack_offset, host_reg); } -void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); } -void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) +void +codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { - host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); + host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, stack_offset, host_reg); } -void codegen_set_jump_dest(codeblock_t *block, void *p) +void +codegen_set_jump_dest(codeblock_t *block, void *p) { - *(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4); + *(uint32_t *) p = (uintptr_t) &block_write_data[block_pos] - ((uintptr_t) p + 4); } -void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) +void +codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data) { - host_x86_MOV8_ABS_IMM(block, p, imm_data); + host_x86_MOV8_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) +void +codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data) { - host_x86_MOV16_ABS_IMM(block, p, imm_data); + host_x86_MOV16_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) +void +codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data) { - host_x86_MOV32_ABS_IMM(block, p, imm_data); + host_x86_MOV32_ABS_IMM(block, p, imm_data); } -void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) +void +codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data) { - host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); + host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data); } #endif diff --git a/src/codegen_new/codegen_block.c b/src/codegen_new/codegen_block.c index 283faf140..c519b34d2 100644 --- a/src/codegen_new/codegen_block.c +++ b/src/codegen_new/codegen_block.c @@ -21,39 +21,39 @@ uint8_t *block_write_data = NULL; -int codegen_flat_ds, codegen_flat_ss; -int mmx_ebx_ecx_loaded; -int codegen_flags_changed = 0; -int codegen_fpu_entered = 0; -int codegen_mmx_entered = 0; -int codegen_fpu_loaded_iq[8]; -x86seg *op_ea_seg; -int op_ssegs; +int codegen_flat_ds, codegen_flat_ss; +int mmx_ebx_ecx_loaded; +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_mmx_entered = 0; +int codegen_fpu_loaded_iq[8]; +x86seg *op_ea_seg; +int op_ssegs; uint32_t op_old_pc; uint32_t recomp_page = -1; -int block_current = 0; +int block_current = 0; static int block_num; -int block_pos; +int block_pos; uint32_t codegen_endpc; -int codegen_block_cycles; +int codegen_block_cycles; static int codegen_block_ins; static int codegen_block_full_ins; static uint32_t last_op32; -static x86seg *last_ea_seg; -static int last_ssegs; +static x86seg *last_ea_seg; +static int last_ssegs; #ifdef DEBUG_EXTRA -uint32_t instr_counts[256*256]; +uint32_t instr_counts[256 * 256]; #endif static uint16_t block_free_list; -static void delete_block(codeblock_t *block); -static void delete_dirty_block(codeblock_t *block); +static void delete_block(codeblock_t *block); +static void delete_dirty_block(codeblock_t *block); /*Temporary list of code blocks that have recently been evicted. This allows for some historical state to be kept when a block is the target of self-modifying @@ -62,830 +62,793 @@ static void delete_dirty_block(codeblock_t *block); The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is exceeded the oldest entry will be moved to the free list.*/ static uint16_t block_dirty_list_head, block_dirty_list_tail; -static int dirty_list_size = 0; +static int dirty_list_size = 0; #define DIRTY_LIST_MAX_SIZE 64 -static void block_free_list_add(codeblock_t *block) +static void +block_free_list_add(codeblock_t *block) { #ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("block_free_list_add: block=%p in dirty list\n", block); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("block_free_list_add: block=%p in dirty list\n", block); #endif - if (block_free_list) - block->next = block_free_list; - else - block->next = 0; - block_free_list = get_block_nr(block); - block->flags = CODEBLOCK_IN_FREE_LIST; + if (block_free_list) + block->next = block_free_list; + else + block->next = 0; + block_free_list = get_block_nr(block); + block->flags = CODEBLOCK_IN_FREE_LIST; } -static void block_dirty_list_add(codeblock_t *block) +static void +block_dirty_list_add(codeblock_t *block) { #ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("block_dirty_list_add: block=%p already in dirty list\n", block); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("block_dirty_list_add: block=%p already in dirty list\n", block); #endif - if (block_dirty_list_head != BLOCK_INVALID) - { - codeblock_t *old_head = &codeblock[block_dirty_list_head]; + if (block_dirty_list_head != BLOCK_INVALID) { + codeblock_t *old_head = &codeblock[block_dirty_list_head]; - block->next = block_dirty_list_head; - block->prev = BLOCK_INVALID; - block_dirty_list_head = old_head->prev = get_block_nr(block); - } - else - { - /*List empty*/ - block->prev = block->next = BLOCK_INVALID; - block_dirty_list_head = block_dirty_list_tail = get_block_nr(block); - } - block->flags |= CODEBLOCK_IN_DIRTY_LIST; - dirty_list_size++; - if (dirty_list_size > DIRTY_LIST_MAX_SIZE) - { - /*Evict oldest block to the free list*/ - codeblock_t *evict_block = &codeblock[block_dirty_list_tail]; + block->next = block_dirty_list_head; + block->prev = BLOCK_INVALID; + block_dirty_list_head = old_head->prev = get_block_nr(block); + } else { + /*List empty*/ + block->prev = block->next = BLOCK_INVALID; + block_dirty_list_head = block_dirty_list_tail = get_block_nr(block); + } + block->flags |= CODEBLOCK_IN_DIRTY_LIST; + dirty_list_size++; + if (dirty_list_size > DIRTY_LIST_MAX_SIZE) { + /*Evict oldest block to the free list*/ + codeblock_t *evict_block = &codeblock[block_dirty_list_tail]; #ifndef RELEASE_BUILD - if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST)) - fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags); - if (!block_dirty_list_tail) - fatal("block_dirty_list_add - !block_dirty_list_tail\n"); - if (evict_block->prev == BLOCK_INVALID) - fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n"); + if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST)) + fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags); + if (!block_dirty_list_tail) + fatal("block_dirty_list_add - !block_dirty_list_tail\n"); + if (evict_block->prev == BLOCK_INVALID) + fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n"); #endif - block_dirty_list_tail = evict_block->prev; - codeblock[evict_block->prev].next = BLOCK_INVALID; - - dirty_list_size--; - evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; - delete_dirty_block(evict_block); - } -} - -static void block_dirty_list_remove(codeblock_t *block) -{ - codeblock_t *prev_block = &codeblock[block->prev]; - codeblock_t *next_block = &codeblock[block->next]; - -#ifndef RELEASE_BUILD - if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST)) - fatal("block_dirty_list_remove: block=%p not in dirty list\n", block); -#endif - - /*Is block head of list*/ - if (block->prev == BLOCK_INVALID) - block_dirty_list_head = block->next; - else - prev_block->next = block->next; - - /*Is block tail of list?*/ - if (block->next == BLOCK_INVALID) - block_dirty_list_tail = block->prev; - else - next_block->prev = block->prev; + block_dirty_list_tail = evict_block->prev; + codeblock[evict_block->prev].next = BLOCK_INVALID; dirty_list_size--; + evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; + delete_dirty_block(evict_block); + } +} + +static void +block_dirty_list_remove(codeblock_t *block) +{ + codeblock_t *prev_block = &codeblock[block->prev]; + codeblock_t *next_block = &codeblock[block->next]; + #ifndef RELEASE_BUILD - if (dirty_list_size < 0) - fatal("remove - dirty_list_size < 0!\n"); + if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST)) + fatal("block_dirty_list_remove: block=%p not in dirty list\n", block); #endif - block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; -} -int codegen_purge_purgable_list(void) -{ - if (purgable_page_list_head) - { - page_t *page = &pages[purgable_page_list_head]; + /*Is block head of list*/ + if (block->prev == BLOCK_INVALID) + block_dirty_list_head = block->next; + else + prev_block->next = block->next; - if (page->code_present_mask & page->dirty_mask) - { - codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12); + /*Is block tail of list?*/ + if (block->next == BLOCK_INVALID) + block_dirty_list_tail = block->prev; + else + next_block->prev = block->prev; - if (block_free_list) - return 1; - } - } - return 0; -} - -static codeblock_t *block_free_list_get(void) -{ - codeblock_t *block = NULL; - - while (!block_free_list) - { - /*Free list is empty, check the dirty list*/ - if (block_dirty_list_tail) - { + dirty_list_size--; #ifndef RELEASE_BUILD - if (dirty_list_size <= 0) - fatal("get - dirty_list_size <= 0!\n"); + if (dirty_list_size < 0) + fatal("remove - dirty_list_size < 0!\n"); #endif - /*Reuse oldest block*/ - block = &codeblock[block_dirty_list_tail]; - - block_dirty_list_tail = block->prev; - if (block->prev == BLOCK_INVALID) - block_dirty_list_head = BLOCK_INVALID; - else - codeblock[block->prev].next = BLOCK_INVALID; - dirty_list_size--; - block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; - delete_dirty_block(block); - block_free_list = get_block_nr(block); - break; - } - /*Free list is empty - free up a block*/ - if (!codegen_purge_purgable_list()) - codegen_delete_random_block(0); - } - - block = &codeblock[block_free_list]; - block_free_list = block->next; - block->flags &= ~CODEBLOCK_IN_FREE_LIST; - block->next = 0; - return block; + block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; } -void codegen_init(void) +int +codegen_purge_purgable_list(void) { - int c; + if (purgable_page_list_head) { + page_t *page = &pages[purgable_page_list_head]; - codegen_allocator_init(); + if (page->code_present_mask & page->dirty_mask) { + codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12); - codegen_backend_init(); - block_free_list = 0; - for (c = 0; c < BLOCK_SIZE; c++) - block_free_list_add(&codeblock[c]); - block_dirty_list_head = block_dirty_list_tail = 0; - dirty_list_size = 0; + if (block_free_list) + return 1; + } + } + return 0; +} + +static codeblock_t * +block_free_list_get(void) +{ + codeblock_t *block = NULL; + + while (!block_free_list) { + /*Free list is empty, check the dirty list*/ + if (block_dirty_list_tail) { +#ifndef RELEASE_BUILD + if (dirty_list_size <= 0) + fatal("get - dirty_list_size <= 0!\n"); +#endif + /*Reuse oldest block*/ + block = &codeblock[block_dirty_list_tail]; + + block_dirty_list_tail = block->prev; + if (block->prev == BLOCK_INVALID) + block_dirty_list_head = BLOCK_INVALID; + else + codeblock[block->prev].next = BLOCK_INVALID; + dirty_list_size--; + block->flags &= ~CODEBLOCK_IN_DIRTY_LIST; + delete_dirty_block(block); + block_free_list = get_block_nr(block); + break; + } + /*Free list is empty - free up a block*/ + if (!codegen_purge_purgable_list()) + codegen_delete_random_block(0); + } + + block = &codeblock[block_free_list]; + block_free_list = block->next; + block->flags &= ~CODEBLOCK_IN_FREE_LIST; + block->next = 0; + return block; +} + +void +codegen_init(void) +{ + int c; + + codegen_allocator_init(); + + codegen_backend_init(); + block_free_list = 0; + for (c = 0; c < BLOCK_SIZE; c++) + block_free_list_add(&codeblock[c]); + block_dirty_list_head = block_dirty_list_tail = 0; + dirty_list_size = 0; #ifdef DEBUG_EXTRA - memset(instr_counts, 0, sizeof(instr_counts)); + memset(instr_counts, 0, sizeof(instr_counts)); #endif } -void codegen_close(void) +void +codegen_close(void) { #ifdef DEBUG_EXTRA - pclog("Instruction counts :\n"); - while (1) - { - int c; - uint32_t highest_num = 0, highest_idx = 0; + pclog("Instruction counts :\n"); + while (1) { + int c; + uint32_t highest_num = 0, highest_idx = 0; - for (c = 0; c < 256*256; c++) - { - if (instr_counts[c] > highest_num) - { - highest_num = instr_counts[c]; - highest_idx = c; - } - } - if (!highest_num) - break; - - instr_counts[highest_idx] = 0; - if (highest_idx > 256) - pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num); - else - pclog(" %02x = %u\n", highest_idx & 0xff, highest_num); + for (c = 0; c < 256 * 256; c++) { + if (instr_counts[c] > highest_num) { + highest_num = instr_counts[c]; + highest_idx = c; + } } -#endif -} + if (!highest_num) + break; -void codegen_reset(void) -{ - int c; - - for (c = 1; c < BLOCK_SIZE; c++) - { - codeblock_t *block = &codeblock[c]; - - if (block->pc != BLOCK_PC_INVALID) - { - block->phys = 0; - block->phys_2 = 0; - delete_block(block); - } - } - - memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); - memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); - mem_reset_page_blocks(); - - block_free_list = 0; - for (c = 0; c < BLOCK_SIZE; c++) - { - codeblock[c].pc = BLOCK_PC_INVALID; - block_free_list_add(&codeblock[c]); - } -} - -void dump_block(void) -{ -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ -} - -static void add_to_block_list(codeblock_t *block) -{ - uint16_t block_prev_nr = pages[block->phys >> 12].block; - uint16_t block_nr = get_block_nr(block); - -#ifndef RELEASE_BUILD - if (!block->page_mask) - fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2); -#endif - - if (block_prev_nr) - { - block->next = block_prev_nr; - codeblock[block_prev_nr].prev = block_nr; - pages[block->phys >> 12].block = block_nr; - } + instr_counts[highest_idx] = 0; + if (highest_idx > 256) + pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num); else - { - block->next = BLOCK_INVALID; - pages[block->phys >> 12].block = block_nr; - } + pclog(" %02x = %u\n", highest_idx & 0xff, highest_num); + } +#endif +} +void +codegen_reset(void) +{ + int c; + + for (c = 1; c < BLOCK_SIZE; c++) { + codeblock_t *block = &codeblock[c]; + + if (block->pc != BLOCK_PC_INVALID) { + block->phys = 0; + block->phys_2 = 0; + delete_block(block); + } + } + + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t)); + mem_reset_page_blocks(); + + block_free_list = 0; + for (c = 0; c < BLOCK_SIZE; c++) { + codeblock[c].pc = BLOCK_PC_INVALID; + block_free_list_add(&codeblock[c]); + } +} + +void +dump_block(void) +{ + /* codeblock_t *block = pages[0x119000 >> 12].block; + + pclog("dump_block:\n"); + while (block) + { + uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); + uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); + pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); + if (!block->pc) + fatal("Dead PC=0\n"); + + block = block->next; + } + pclog("dump_block done\n");*/ +} + +static void +add_to_block_list(codeblock_t *block) +{ + uint16_t block_prev_nr = pages[block->phys >> 12].block; + uint16_t block_nr = get_block_nr(block); + +#ifndef RELEASE_BUILD + if (!block->page_mask) + fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask, block->page_mask2); +#endif + + if (block_prev_nr) { + block->next = block_prev_nr; + codeblock[block_prev_nr].prev = block_nr; + pages[block->phys >> 12].block = block_nr; + } else { + block->next = BLOCK_INVALID; + pages[block->phys >> 12].block = block_nr; + } + + if (block->next) { +#ifndef RELEASE_BUILD + if (codeblock[block->next].pc == BLOCK_PC_INVALID) + fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *) &codeblock[block->next], (void *) codeblock, block_current, block_pos); +#endif + } + + if (block->page_mask2) { + block->flags |= CODEBLOCK_HAS_PAGE2; + + block_prev_nr = pages[block->phys_2 >> 12].block_2; + + if (block_prev_nr) { + block->next_2 = block_prev_nr; + codeblock[block_prev_nr].prev_2 = block_nr; + pages[block->phys_2 >> 12].block_2 = block_nr; + } else { + block->next_2 = BLOCK_INVALID; + pages[block->phys_2 >> 12].block_2 = block_nr; + } + } +} + +static void +remove_from_block_list(codeblock_t *block, uint32_t pc) +{ + if (!block->page_mask) + return; +#ifndef RELEASE_BUILD + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("remove_from_block_list: in dirty list\n"); +#endif + if (block->prev) { + codeblock[block->prev].next = block->next; if (block->next) - { + codeblock[block->next].prev = block->prev; + } else { + pages[block->phys >> 12].block = block->next; + if (block->next) + codeblock[block->next].prev = BLOCK_INVALID; + else + mem_flush_write_page(block->phys, 0); + } + + if (!(block->flags & CODEBLOCK_HAS_PAGE2)) { #ifndef RELEASE_BUILD - if (codeblock[block->next].pc == BLOCK_PC_INVALID) - fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos); + if (block->prev_2 || block->next_2) + fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys); #endif - } + return; + } + block->flags &= ~CODEBLOCK_HAS_PAGE2; - if (block->page_mask2) - { - block->flags |= CODEBLOCK_HAS_PAGE2; - - block_prev_nr = pages[block->phys_2 >> 12].block_2; - - if (block_prev_nr) - { - block->next_2 = block_prev_nr; - codeblock[block_prev_nr].prev_2 = block_nr; - pages[block->phys_2 >> 12].block_2 = block_nr; - } - else - { - block->next_2 = BLOCK_INVALID; - pages[block->phys_2 >> 12].block_2 = block_nr; - } - } + if (block->prev_2) { + codeblock[block->prev_2].next_2 = block->next_2; + if (block->next_2) + codeblock[block->next_2].prev_2 = block->prev_2; + } else { + pages[block->phys_2 >> 12].block_2 = block->next_2; + if (block->next_2) + codeblock[block->next_2].prev_2 = BLOCK_INVALID; + else + mem_flush_write_page(block->phys_2, 0); + } } -static void remove_from_block_list(codeblock_t *block, uint32_t pc) +static void +invalidate_block(codeblock_t *block) { - if (!block->page_mask) - return; -#ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("remove_from_block_list: in dirty list\n"); -#endif - if (block->prev) - { - codeblock[block->prev].next = block->next; - if (block->next) - codeblock[block->next].prev = block->prev; - } - else - { - pages[block->phys >> 12].block = block->next; - if (block->next) - codeblock[block->next].prev = BLOCK_INVALID; - else - mem_flush_write_page(block->phys, 0); - } + uint32_t old_pc = block->pc; - if (!(block->flags & CODEBLOCK_HAS_PAGE2)) - { #ifndef RELEASE_BUILD - if (block->prev_2 || block->next_2) - fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + fatal("invalidate_block: already in dirty list\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Invalidating deleted block\n"); #endif - return; - } - block->flags &= ~CODEBLOCK_HAS_PAGE2; - - if (block->prev_2) - { - codeblock[block->prev_2].next_2 = block->next_2; - if (block->next_2) - codeblock[block->next_2].prev_2 = block->prev_2; - } - else - { - pages[block->phys_2 >> 12].block_2 = block->next_2; - if (block->next_2) - codeblock[block->next_2].prev_2 = BLOCK_INVALID; - else - mem_flush_write_page(block->phys_2, 0); - } + remove_from_block_list(block, old_pc); + block_dirty_list_add(block); + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; } -static void invalidate_block(codeblock_t *block) +static void +delete_block(codeblock_t *block) { - uint32_t old_pc = block->pc; + uint32_t old_pc = block->pc; + + if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) + codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; #ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - fatal("invalidate_block: already in dirty list\n"); - if (block->pc == BLOCK_PC_INVALID) - fatal("Invalidating deleted block\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Deleting deleted block\n"); #endif + block->pc = BLOCK_PC_INVALID; + + codeblock_tree_delete(block); + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block_dirty_list_remove(block); + else remove_from_block_list(block, old_pc); - block_dirty_list_add(block); - if (block->head_mem_block) - codegen_allocator_free(block->head_mem_block); - block->head_mem_block = NULL; + if (block->head_mem_block) + codegen_allocator_free(block->head_mem_block); + block->head_mem_block = NULL; + block_free_list_add(block); } -static void delete_block(codeblock_t *block) +static void +delete_dirty_block(codeblock_t *block) { - uint32_t old_pc = block->pc; - - if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) - codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; + if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) + codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; #ifndef RELEASE_BUILD - if (block->pc == BLOCK_PC_INVALID) - fatal("Deleting deleted block\n"); + if (block->pc == BLOCK_PC_INVALID) + fatal("Deleting deleted block\n"); #endif - block->pc = BLOCK_PC_INVALID; + block->pc = BLOCK_PC_INVALID; - codeblock_tree_delete(block); - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block_dirty_list_remove(block); - else - remove_from_block_list(block, old_pc); - if (block->head_mem_block) - codegen_allocator_free(block->head_mem_block); - block->head_mem_block = NULL; - block_free_list_add(block); + codeblock_tree_delete(block); + block_free_list_add(block); } -static void delete_dirty_block(codeblock_t *block) +void +codegen_delete_block(codeblock_t *block) { - if (block == &codeblock[codeblock_hash[HASH(block->phys)]]) - codeblock_hash[HASH(block->phys)] = BLOCK_INVALID; - -#ifndef RELEASE_BUILD - if (block->pc == BLOCK_PC_INVALID) - fatal("Deleting deleted block\n"); -#endif - block->pc = BLOCK_PC_INVALID; - - codeblock_tree_delete(block); - block_free_list_add(block); + if (block->pc != BLOCK_PC_INVALID) + delete_block(block); } -void codegen_delete_block(codeblock_t *block) +void +codegen_delete_random_block(int required_mem_block) { - if (block->pc != BLOCK_PC_INVALID) + int block_nr = rand() & BLOCK_MASK; + + while (1) { + if (block_nr && block_nr != block_current) { + codeblock_t *block = &codeblock[block_nr]; + + if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block)) { delete_block(block); + return; + } + } + block_nr = (block_nr + 1) & BLOCK_MASK; + } } -void codegen_delete_random_block(int required_mem_block) +void +codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) { - int block_nr = rand() & BLOCK_MASK; + uint16_t block_nr = page->block; + int remove_from_evict_list = 0; + int c; - while (1) - { - if (block_nr && block_nr != block_current) - { - codeblock_t *block = &codeblock[block_nr]; + while (block_nr) { + codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next; - if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block)) - { - delete_block(block); - return; - } - } - block_nr = (block_nr + 1) & BLOCK_MASK; + if (*block->dirty_mask & block->page_mask) { + invalidate_block(block); } +#ifndef RELEASE_BUILD + if (block_nr == next_block) + fatal("Broken 1\n"); +#endif + block_nr = next_block; + } + + block_nr = page->block_2; + + while (block_nr) { + codeblock_t *block = &codeblock[block_nr]; + uint16_t next_block = block->next_2; + + if (*block->dirty_mask2 & block->page_mask2) { + invalidate_block(block); + } +#ifndef RELEASE_BUILD + if (block_nr == next_block) + fatal("Broken 2\n"); +#endif + block_nr = next_block; + } + + if (page->code_present_mask & page->dirty_mask) + remove_from_evict_list = 1; + page->code_present_mask &= ~page->dirty_mask; + page->dirty_mask = 0; + + for (c = 0; c < 64; c++) { + if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c]) + remove_from_evict_list = 0; + page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c]; + page->byte_dirty_mask[c] = 0; + } + if (remove_from_evict_list) + page_remove_from_evict_list(page); } -void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +void +codegen_block_init(uint32_t phys_addr) { - uint16_t block_nr = page->block; - int remove_from_evict_list = 0; - int c; + codeblock_t *block; + page_t *page = &pages[phys_addr >> 12]; - while (block_nr) - { - codeblock_t *block = &codeblock[block_nr]; - uint16_t next_block = block->next; - - if (*block->dirty_mask & block->page_mask) - { - invalidate_block(block); - } + if (!page->block) + mem_flush_write_page(phys_addr, cs + cpu_state.pc); + block = block_free_list_get(); #ifndef RELEASE_BUILD - if (block_nr == next_block) - fatal("Broken 1\n"); + if (!block) + fatal("codegen_block_init: block_free_list_get() returned NULL\n"); #endif - block_nr = next_block; - } + block_current = get_block_nr(block); - block_nr = page->block_2; + block_num = HASH(phys_addr); + codeblock_hash[block_num] = block_current; - while (block_nr) - { - codeblock_t *block = &codeblock[block_nr]; - uint16_t next_block = block->next_2; + block->ins = 0; + block->pc = cs + cpu_state.pc; + block->_cs = cs; + block->phys = phys_addr; + block->dirty_mask = &page->dirty_mask; + block->dirty_mask2 = NULL; + block->next = block->prev = BLOCK_INVALID; + block->next_2 = block->prev_2 = BLOCK_INVALID; + block->page_mask = block->page_mask2 = 0; + block->flags = CODEBLOCK_STATIC_TOP; + block->status = cpu_cur_status; - if (*block->dirty_mask2 & block->page_mask2) - { - invalidate_block(block); - } -#ifndef RELEASE_BUILD - if (block_nr == next_block) - fatal("Broken 2\n"); -#endif - block_nr = next_block; - } - - if (page->code_present_mask & page->dirty_mask) - remove_from_evict_list = 1; - page->code_present_mask &= ~page->dirty_mask; - page->dirty_mask = 0; - - for (c = 0; c < 64; c++) - { - if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c]) - remove_from_evict_list = 0; - page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c]; - page->byte_dirty_mask[c] = 0; - } - if (remove_from_evict_list) - page_remove_from_evict_list(page); -} - -void codegen_block_init(uint32_t phys_addr) -{ - codeblock_t *block; - page_t *page = &pages[phys_addr >> 12]; - - if (!page->block) - mem_flush_write_page(phys_addr, cs+cpu_state.pc); - block = block_free_list_get(); -#ifndef RELEASE_BUILD - if (!block) - fatal("codegen_block_init: block_free_list_get() returned NULL\n"); -#endif - block_current = get_block_nr(block); - - block_num = HASH(phys_addr); - codeblock_hash[block_num] = block_current; - - block->ins = 0; - block->pc = cs + cpu_state.pc; - block->_cs = cs; - block->phys = phys_addr; - block->dirty_mask = &page->dirty_mask; - block->dirty_mask2 = NULL; - block->next = block->prev = BLOCK_INVALID; - block->next_2 = block->prev_2 = BLOCK_INVALID; - block->page_mask = block->page_mask2 = 0; - block->flags = CODEBLOCK_STATIC_TOP; - block->status = cpu_cur_status; - - recomp_page = block->phys & ~0xfff; - codeblock_tree_add(block); + recomp_page = block->phys & ~0xfff; + codeblock_tree_add(block); } static ir_data_t *ir_data; -ir_data_t *codegen_get_ir_data(void) +ir_data_t * +codegen_get_ir_data(void) { - return ir_data; + return ir_data; } -void codegen_block_start_recompile(codeblock_t *block) +void +codegen_block_start_recompile(codeblock_t *block) { - page_t *page = &pages[block->phys >> 12]; + page_t *page = &pages[block->phys >> 12]; - if (!page->block) - mem_flush_write_page(block->phys, cs+cpu_state.pc); + if (!page->block) + mem_flush_write_page(block->phys, cs + cpu_state.pc); - block_num = HASH(block->phys); - block_current = get_block_nr(block);//block->pnt; + block_num = HASH(block->phys); + block_current = get_block_nr(block); // block->pnt; #ifndef RELEASE_BUILD - if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) - fatal("Recompile to used block!\n"); + if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED)) + fatal("Recompile to used block!\n"); #endif - block->head_mem_block = codegen_allocator_allocate(NULL, block_current); - block->data = codeblock_allocator_get_ptr(block->head_mem_block); + block->head_mem_block = codegen_allocator_allocate(NULL, block_current); + block->data = codeblock_allocator_get_ptr(block->head_mem_block); - block->status = cpu_cur_status; + block->status = cpu_cur_status; - block->page_mask = block->page_mask2 = 0; - block->ins = 0; + block->page_mask = block->page_mask2 = 0; + block->ins = 0; - cpu_block_end = 0; + cpu_block_end = 0; - last_op32 = -1; - last_ea_seg = NULL; - last_ssegs = -1; + last_op32 = -1; + last_ea_seg = NULL; + last_ssegs = -1; - codegen_block_cycles = 0; - codegen_timing_block_start(); + codegen_block_cycles = 0; + codegen_timing_block_start(); - codegen_block_ins = 0; - codegen_block_full_ins = 0; + codegen_block_ins = 0; + codegen_block_full_ins = 0; - recomp_page = block->phys & ~0xfff; + recomp_page = block->phys & ~0xfff; - codegen_flags_changed = 0; - codegen_fpu_entered = 0; - codegen_mmx_entered = 0; + codegen_flags_changed = 0; + codegen_fpu_entered = 0; + codegen_mmx_entered = 0; - codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = - codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; + codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] = codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0; - cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; + cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; - block->TOP = cpu_state.TOP & 7; - block->flags |= CODEBLOCK_WAS_RECOMPILED; + block->TOP = cpu_state.TOP & 7; + block->flags |= CODEBLOCK_WAS_RECOMPILED; - codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); - codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); + codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); + codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS); - if (block->flags & CODEBLOCK_BYTE_MASK) - { - block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK]; - block->dirty_mask2 = NULL; - } + if (block->flags & CODEBLOCK_BYTE_MASK) { + block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK]; + block->dirty_mask2 = NULL; + } - ir_data = codegen_ir_init(); - ir_data->block = block; - codegen_reg_reset(); - codegen_accumulate_reset(); - codegen_generate_reset(); + ir_data = codegen_ir_init(); + ir_data->block = block; + codegen_reg_reset(); + codegen_accumulate_reset(); + codegen_generate_reset(); } - -void codegen_block_remove(void) +void +codegen_block_remove(void) { - codeblock_t *block = &codeblock[block_current]; + codeblock_t *block = &codeblock[block_current]; - delete_block(block); + delete_block(block); - recomp_page = -1; + recomp_page = -1; } -void codegen_block_generate_end_mask_recompile(void) +void +codegen_block_generate_end_mask_recompile(void) { - codeblock_t *block = &codeblock[block_current]; - page_t *p; + codeblock_t *block = &codeblock[block_current]; + page_t *p; - p = &pages[block->phys >> 12]; - if (block->flags & CODEBLOCK_BYTE_MASK) - { - int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + p = &pages[block->phys >> 12]; + if (block->flags & CODEBLOCK_BYTE_MASK) { + int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - p->byte_code_present_mask[offset] |= block->page_mask; - } - else - p->code_present_mask |= block->page_mask; - - if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - - block->phys_2 = -1; - block->next_2 = block->prev_2 = BLOCK_INVALID; - if (block->page_mask2) - { - block->phys_2 = get_phys_noabrt(codegen_endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; - - if (block->flags & CODEBLOCK_BYTE_MASK) - { - int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - - page_2->byte_code_present_mask[offset] |= block->page_mask2; - block->dirty_mask2 = &page_2->byte_dirty_mask[offset]; - } - else - { - page_2->code_present_mask |= block->page_mask2; - block->dirty_mask2 = &page_2->dirty_mask; - } - if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2)) - page_add_to_evict_list(page_2); - - if (!pages[block->phys_2 >> 12].block_2) - mem_flush_write_page(block->phys_2, codegen_endpc); - -#ifndef RELEASE_BUILD - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) - fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); - } -#endif - } - else - { - /*Second page not present. page_mask2 is most likely set only because - the recompiler didn't know how long the last instruction was, so - clear it*/ - block->page_mask2 = 0; - } - } - - recomp_page = -1; -} - -void codegen_block_generate_end_mask_mark(void) -{ - codeblock_t *block = &codeblock[block_current]; - uint32_t start_pc; - uint32_t end_pc; - page_t *p; - -#ifndef RELEASE_BUILD - if (block->flags & CODEBLOCK_BYTE_MASK) - fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n"); -#endif - - block->page_mask = 0; - start_pc = (block->pc & 0xfff) & ~63; - if ((block->pc ^ codegen_endpc) & ~0xfff) - end_pc = 0xfff & ~63; - else - end_pc = (codegen_endpc & 0xfff) & ~63; - if (end_pc < start_pc) - end_pc = 0xfff; - start_pc >>= PAGE_MASK_SHIFT; - end_pc >>= PAGE_MASK_SHIFT; - - for (; start_pc <= end_pc; start_pc++) - { - block->page_mask |= ((uint64_t)1 << start_pc); - } - - p = &pages[block->phys >> 12]; + p->byte_code_present_mask[offset] |= block->page_mask; + } else p->code_present_mask |= block->page_mask; - if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - block->phys_2 = -1; - block->page_mask2 = 0; - block->next_2 = block->prev_2 = BLOCK_INVALID; - if ((block->pc ^ codegen_endpc) & ~0xfff) - { - block->phys_2 = get_phys_noabrt(codegen_endpc); - if (block->phys_2 != -1) - { - page_t *page_2 = &pages[block->phys_2 >> 12]; + if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); - start_pc = 0; - end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT; - for (; start_pc <= end_pc; start_pc++) - block->page_mask2 |= ((uint64_t)1 << start_pc); + block->phys_2 = -1; + block->next_2 = block->prev_2 = BLOCK_INVALID; + if (block->page_mask2) { + block->phys_2 = get_phys_noabrt(codegen_endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; - page_2->code_present_mask |= block->page_mask2; - if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2)) - page_add_to_evict_list(page_2); + if (block->flags & CODEBLOCK_BYTE_MASK) { + int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - if (!pages[block->phys_2 >> 12].block_2) - mem_flush_write_page(block->phys_2, codegen_endpc); + page_2->byte_code_present_mask[offset] |= block->page_mask2; + block->dirty_mask2 = &page_2->byte_dirty_mask[offset]; + } else { + page_2->code_present_mask |= block->page_mask2; + block->dirty_mask2 = &page_2->dirty_mask; + } + if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2)) + page_add_to_evict_list(page_2); + + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, codegen_endpc); #ifndef RELEASE_BUILD - if (!block->page_mask2) - fatal("!page_mask2\n"); - if (block->next_2) - { - if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) - fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]); - } + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *) &codeblock[block->next_2]); + } #endif - block->dirty_mask2 = &page_2->dirty_mask; - } - else - { - /*Second page not present. page_mask2 is most likely set only because - the recompiler didn't know how long the last instruction was, so - clear it*/ - block->page_mask2 = 0; - } + } else { + /*Second page not present. page_mask2 is most likely set only because + the recompiler didn't know how long the last instruction was, so + clear it*/ + block->page_mask2 = 0; } + } - recomp_page = -1; + recomp_page = -1; } -void codegen_block_end(void) +void +codegen_block_generate_end_mask_mark(void) { - codeblock_t *block = &codeblock[block_current]; + codeblock_t *block = &codeblock[block_current]; + uint32_t start_pc; + uint32_t end_pc; + page_t *p; - codegen_block_generate_end_mask_mark(); - add_to_block_list(block); -} +#ifndef RELEASE_BUILD + if (block->flags & CODEBLOCK_BYTE_MASK) + fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n"); +#endif -void codegen_block_end_recompile(codeblock_t *block) -{ - codegen_timing_block_end(); - codegen_accumulate(ir_data, ACCREG_cycles, -codegen_block_cycles); + block->page_mask = 0; + start_pc = (block->pc & 0xfff) & ~63; + if ((block->pc ^ codegen_endpc) & ~0xfff) + end_pc = 0xfff & ~63; + else + end_pc = (codegen_endpc & 0xfff) & ~63; + if (end_pc < start_pc) + end_pc = 0xfff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; - if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block_dirty_list_remove(block); - else - remove_from_block_list(block, block->pc); - block->next = block->prev = BLOCK_INVALID; - block->next_2 = block->prev_2 = BLOCK_INVALID; - codegen_block_generate_end_mask_recompile(); - add_to_block_list(block); + for (; start_pc <= end_pc; start_pc++) { + block->page_mask |= ((uint64_t) 1 << start_pc); + } - if (!(block->flags & CODEBLOCK_HAS_FPU)) - block->flags &= ~CODEBLOCK_STATIC_TOP; + p = &pages[block->phys >> 12]; + p->code_present_mask |= block->page_mask; + if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); - codegen_accumulate_flush(ir_data); - codegen_ir_compile(ir_data, block); -} + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = BLOCK_INVALID; + if ((block->pc ^ codegen_endpc) & ~0xfff) { + block->phys_2 = get_phys_noabrt(codegen_endpc); + if (block->phys_2 != -1) { + page_t *page_2 = &pages[block->phys_2 >> 12]; -void codegen_flush(void) -{ - return; -} + start_pc = 0; + end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t) 1 << start_pc); -void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len) -{ - if (len) - { - uint32_t end_pc = start_pc + (len-1); + page_2->code_present_mask |= block->page_mask2; + if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2)) + page_add_to_evict_list(page_2); - if (block->flags & CODEBLOCK_BYTE_MASK) - { - uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK; - uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK; + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, codegen_endpc); - if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/ - { - for (; start_pc_masked <= end_pc_masked; start_pc_masked++) - block->page_mask2 |= ((uint64_t)1 << start_pc_masked); - } - else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/ - { - for (; start_pc_masked <= 63; start_pc_masked++) - block->page_mask |= ((uint64_t)1 << start_pc_masked); - for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++) - block->page_mask2 |= ((uint64_t)1 << start_pc_masked); - } - else /*First page only*/ - { - for (; start_pc_masked <= end_pc_masked; start_pc_masked++) - block->page_mask |= ((uint64_t)1 << start_pc_masked); - } - } - else - { - uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT; - uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT; - start_pc_shifted &= PAGE_MASK_MASK; - end_pc_shifted &= PAGE_MASK_MASK; - - if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/ - { - for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) - block->page_mask2 |= ((uint64_t)1 << start_pc_shifted); - } - else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/ - { - for (; start_pc_shifted <= 63; start_pc_shifted++) - block->page_mask |= ((uint64_t)1 << start_pc_shifted); - for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) - block->page_mask2 |= ((uint64_t)1 << start_pc_shifted); - } - else /*First page only*/ - { - for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) - block->page_mask |= ((uint64_t)1 << start_pc_shifted); - } - } +#ifndef RELEASE_BUILD + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) { + if (codeblock[block->next_2].pc == BLOCK_PC_INVALID) + fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *) &codeblock[block->next_2]); + } +#endif + block->dirty_mask2 = &page_2->dirty_mask; + } else { + /*Second page not present. page_mask2 is most likely set only because + the recompiler didn't know how long the last instruction was, so + clear it*/ + block->page_mask2 = 0; } + } + + recomp_page = -1; +} + +void +codegen_block_end(void) +{ + codeblock_t *block = &codeblock[block_current]; + + codegen_block_generate_end_mask_mark(); + add_to_block_list(block); +} + +void +codegen_block_end_recompile(codeblock_t *block) +{ + codegen_timing_block_end(); + codegen_accumulate(ir_data, ACCREG_cycles, -codegen_block_cycles); + + if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block_dirty_list_remove(block); + else + remove_from_block_list(block, block->pc); + block->next = block->prev = BLOCK_INVALID; + block->next_2 = block->prev_2 = BLOCK_INVALID; + codegen_block_generate_end_mask_recompile(); + add_to_block_list(block); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; + + codegen_accumulate_flush(ir_data); + codegen_ir_compile(ir_data, block); +} + +void +codegen_flush(void) +{ + return; +} + +void +codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len) +{ + if (len) { + uint32_t end_pc = start_pc + (len - 1); + + if (block->flags & CODEBLOCK_BYTE_MASK) { + uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK; + uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK; + + if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/ + { + for (; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_masked); + } else if (((start_pc + (len - 1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/ + { + for (; start_pc_masked <= 63; start_pc_masked++) + block->page_mask |= ((uint64_t) 1 << start_pc_masked); + for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_masked); + } else /*First page only*/ + { + for (; start_pc_masked <= end_pc_masked; start_pc_masked++) + block->page_mask |= ((uint64_t) 1 << start_pc_masked); + } + } else { + uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT; + uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT; + start_pc_shifted &= PAGE_MASK_MASK; + end_pc_shifted &= PAGE_MASK_MASK; + + if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/ + { + for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_shifted); + } else if (((start_pc + (len - 1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/ + { + for (; start_pc_shifted <= 63; start_pc_shifted++) + block->page_mask |= ((uint64_t) 1 << start_pc_shifted); + for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask2 |= ((uint64_t) 1 << start_pc_shifted); + } else /*First page only*/ + { + for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++) + block->page_mask |= ((uint64_t) 1 << start_pc_shifted); + } + } + } } diff --git a/src/codegen_new/codegen_ir.c b/src/codegen_new/codegen_ir.c index 09c593f08..bc38a3666 100644 --- a/src/codegen_new/codegen_ir.c +++ b/src/codegen_new/codegen_ir.c @@ -9,208 +9,186 @@ #include "codegen_ir.h" #include "codegen_reg.h" -extern int has_ea; +extern int has_ea; static ir_data_t ir_block; static int codegen_unroll_start, codegen_unroll_count; static int codegen_unroll_first_instruction; -ir_data_t *codegen_ir_init(void) +ir_data_t * +codegen_ir_init(void) { - ir_block.wr_pos = 0; + ir_block.wr_pos = 0; - codegen_unroll_count = 0; + codegen_unroll_count = 0; - return &ir_block; + return &ir_block; } -void codegen_ir_set_unroll(int count, int start, int first_instruction) +void +codegen_ir_set_unroll(int count, int start, int first_instruction) { - codegen_unroll_count = count; - codegen_unroll_start = start; - codegen_unroll_first_instruction = first_instruction; + codegen_unroll_count = count; + codegen_unroll_start = start; + codegen_unroll_first_instruction = first_instruction; } -static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) +static void +duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) { - uop_t *new_uop = uop_alloc(ir, uop->type); + uop_t *new_uop = uop_alloc(ir, uop->type); - if (!ir_reg_is_invalid(uop->src_reg_a)) - new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg); - if (!ir_reg_is_invalid(uop->src_reg_b)) - new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg); - if (!ir_reg_is_invalid(uop->src_reg_c)) - new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg); - if (!ir_reg_is_invalid(uop->dest_reg_a)) - new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos-1); + if (!ir_reg_is_invalid(uop->src_reg_a)) + new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg); + if (!ir_reg_is_invalid(uop->src_reg_b)) + new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg); + if (!ir_reg_is_invalid(uop->src_reg_c)) + new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg); + if (!ir_reg_is_invalid(uop->dest_reg_a)) + new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos - 1); - new_uop->type = uop->type; - new_uop->imm_data = uop->imm_data; - new_uop->p = uop->p; - new_uop->pc = uop->pc; + new_uop->type = uop->type; + new_uop->imm_data = uop->imm_data; + new_uop->p = uop->p; + new_uop->pc = uop->pc; - if (uop->jump_dest_uop != -1) - { - new_uop->jump_dest_uop = uop->jump_dest_uop + offset; + if (uop->jump_dest_uop != -1) { + new_uop->jump_dest_uop = uop->jump_dest_uop + offset; + } +} + +void +codegen_ir_compile(ir_data_t *ir, codeblock_t *block) +{ + int jump_target_at_end = -1; + int c; + + if (codegen_unroll_count) { + int unroll_count; + int unroll_end; + + codegen_set_loop_start(ir, codegen_unroll_first_instruction); + unroll_end = ir->wr_pos; + + for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) { + int offset = ir->wr_pos - codegen_unroll_start; + // pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count); + for (c = codegen_unroll_start; c < unroll_end; c++) { + // pclog(" Duplicate uop %i\n", c); + duplicate_uop(ir, &ir->uops[c], offset); + } } -} + } -void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) -{ - int jump_target_at_end = -1; - int c; + codegen_reg_mark_as_required(); + codegen_reg_process_dead_list(ir); + block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); + block_pos = 0; + codegen_backend_prologue(block); - if (codegen_unroll_count) - { - int unroll_count; - int unroll_end; + for (c = 0; c < ir->wr_pos; c++) { + uop_t *uop = &ir->uops[c]; - codegen_set_loop_start(ir, codegen_unroll_first_instruction); - unroll_end = ir->wr_pos; + // pclog("uOP %i : %08x\n", c, uop->type); - for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) - { - int offset = ir->wr_pos - codegen_unroll_start; -// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count); - for (c = codegen_unroll_start; c < unroll_end; c++) - { -// pclog(" Duplicate uop %i\n", c); - duplicate_uop(ir, &ir->uops[c], offset); - } - } + if (uop->type & UOP_TYPE_BARRIER) + codegen_reg_flush_invalidate(ir, block); + + if (uop->type & UOP_TYPE_JUMP_DEST) { + uop_t *uop_dest = uop; + + while (uop_dest->jump_list_next != -1) { + uop_dest = &ir->uops[uop_dest->jump_list_next]; + codegen_set_jump_dest(block, uop_dest->p); + } } - codegen_reg_mark_as_required(); - codegen_reg_process_dead_list(ir); - block_write_data = codeblock_allocator_get_ptr(block->head_mem_block); - block_pos = 0; - codegen_backend_prologue(block); - - for (c = 0; c < ir->wr_pos; c++) - { - uop_t *uop = &ir->uops[c]; - -// pclog("uOP %i : %08x\n", c, uop->type); - - if (uop->type & UOP_TYPE_BARRIER) - codegen_reg_flush_invalidate(ir, block); - - if (uop->type & UOP_TYPE_JUMP_DEST) - { - uop_t *uop_dest = uop; - - while (uop_dest->jump_list_next != -1) - { - uop_dest = &ir->uops[uop_dest->jump_list_next]; - codegen_set_jump_dest(block, uop_dest->p); - } - } - - if ((uop->type & UOP_MASK) == UOP_INVALID) - continue; + if ((uop->type & UOP_MASK) == UOP_INVALID) + continue; #ifdef CODEGEN_BACKEND_HAS_MOV_IMM - if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0) - { - /*Special case for UOP_MOV_IMM - if destination not already in host register - and won't be used again then just store directly to memory*/ - codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data); - } - else + if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0) { + /*Special case for UOP_MOV_IMM - if destination not already in host register + and won't be used again then just store directly to memory*/ + codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data); + } else #endif - if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 && - reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a)) - { - /*Special case for UOP_MOV - if source register won't be used again then - just rename it to dest register instead of moving*/ - codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg); - uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); - codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a); - if (uop->type & UOP_TYPE_ORDER_BARRIER) - codegen_reg_flush(ir, block); + if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 && reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a)) { + /*Special case for UOP_MOV - if source register won't be used again then + just rename it to dest register instead of moving*/ + codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg); + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); + codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a); + if (uop->type & UOP_TYPE_ORDER_BARRIER) + codegen_reg_flush(ir, block); + } else { + if (uop->type & UOP_TYPE_PARAMS_REGS) { + codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); + if (uop->src_reg_a.reg != IREG_INVALID) { + uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); } - else - { - if (uop->type & UOP_TYPE_PARAMS_REGS) - { - codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c); - if (uop->src_reg_a.reg != IREG_INVALID) - { - uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL); - } - if (uop->src_reg_b.reg != IREG_INVALID) - { - uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); - } - if (uop->src_reg_c.reg != IREG_INVALID) - { - uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL); - } - } + if (uop->src_reg_b.reg != IREG_INVALID) { + uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL); + } + if (uop->src_reg_c.reg != IREG_INVALID) { + uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL); + } + } - if (uop->type & UOP_TYPE_ORDER_BARRIER) - codegen_reg_flush(ir, block); + if (uop->type & UOP_TYPE_ORDER_BARRIER) + codegen_reg_flush(ir, block); - if (uop->type & UOP_TYPE_PARAMS_REGS) - { - if (uop->dest_reg_a.reg != IREG_INVALID) - { - uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); - } - } + if (uop->type & UOP_TYPE_PARAMS_REGS) { + if (uop->dest_reg_a.reg != IREG_INVALID) { + uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a); + } + } #ifndef RELEASE_BUILD - if (!uop_handlers[uop->type & UOP_MASK]) - fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type); + if (!uop_handlers[uop->type & UOP_MASK]) + fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type); #endif - uop_handlers[uop->type & UOP_MASK](block, uop); - } - - if (uop->type & UOP_TYPE_JUMP) - { - if (uop->jump_dest_uop == ir->wr_pos) - { - if (jump_target_at_end == -1) - jump_target_at_end = c; - else - { - uop_t *uop_dest = &ir->uops[jump_target_at_end]; - - while (uop_dest->jump_list_next != -1) - uop_dest = &ir->uops[uop_dest->jump_list_next]; - - uop_dest->jump_list_next = c; - } - } - else - { - uop_t *uop_dest = &ir->uops[uop->jump_dest_uop]; - - while (uop_dest->jump_list_next != -1) - uop_dest = &ir->uops[uop_dest->jump_list_next]; - - uop_dest->jump_list_next = c; - ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST; - } - } + uop_handlers[uop->type & UOP_MASK](block, uop); } - codegen_reg_flush_invalidate(ir, block); + if (uop->type & UOP_TYPE_JUMP) { + if (uop->jump_dest_uop == ir->wr_pos) { + if (jump_target_at_end == -1) + jump_target_at_end = c; + else { + uop_t *uop_dest = &ir->uops[jump_target_at_end]; - if (jump_target_at_end != -1) - { - uop_t *uop_dest = &ir->uops[jump_target_at_end]; - - while (1) - { - codegen_set_jump_dest(block, uop_dest->p); - if (uop_dest->jump_list_next == -1) - break; + while (uop_dest->jump_list_next != -1) uop_dest = &ir->uops[uop_dest->jump_list_next]; - } - } - codegen_backend_epilogue(block); - block_write_data = NULL; -// if (has_ea) -// fatal("IR compilation complete\n"); + uop_dest->jump_list_next = c; + } + } else { + uop_t *uop_dest = &ir->uops[uop->jump_dest_uop]; + + while (uop_dest->jump_list_next != -1) + uop_dest = &ir->uops[uop_dest->jump_list_next]; + + uop_dest->jump_list_next = c; + ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST; + } + } + } + + codegen_reg_flush_invalidate(ir, block); + + if (jump_target_at_end != -1) { + uop_t *uop_dest = &ir->uops[jump_target_at_end]; + + while (1) { + codegen_set_jump_dest(block, uop_dest->p); + if (uop_dest->jump_list_next == -1) + break; + uop_dest = &ir->uops[uop_dest->jump_list_next]; + } + } + + codegen_backend_epilogue(block); + block_write_data = NULL; + // if (has_ea) + // fatal("IR compilation complete\n"); } diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index 30bf44d98..26a1c3cb4 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -18,761 +18,793 @@ #define UOP_TYPE_ORDER_BARRIER (1 << 27) /*uOP uses source and dest registers*/ -#define UOP_TYPE_PARAMS_REGS (1 << 28) +#define UOP_TYPE_PARAMS_REGS (1 << 28) /*uOP uses pointer*/ #define UOP_TYPE_PARAMS_POINTER (1 << 29) /*uOP uses immediate data*/ -#define UOP_TYPE_PARAMS_IMM (1 << 30) +#define UOP_TYPE_PARAMS_IMM (1 << 30) /*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must set jump_dest in the destination uOP to the address of the branch offset to be written when known.*/ -#define UOP_TYPE_JUMP (1 << 26) +#define UOP_TYPE_JUMP (1 << 26) /*uOP is the destination of a jump, and must set the destination offset of the jump at compile time.*/ #define UOP_TYPE_JUMP_DEST (1 << 25) - -#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00) -#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01) -#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02) -#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03) -#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER) -#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER) -#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER) -#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER) -#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00) +#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01) +#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02) +#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03) +#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER) +#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER) +#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) /*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/ #define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) -#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) -#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) +#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) +#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) /*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/ -#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER) +#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER) /*UOP_JMP - jump to ptr*/ -#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER) +#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER) /*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/ -#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) +#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER) /*UOP_JMP_DEST - jump to ptr*/ -#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) -#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18) -#define UOP_STORE_P_IMM_16 (UOP_TYPE_PARAMS_IMM | 0x19) +#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18) +#define UOP_STORE_P_IMM_16 (UOP_TYPE_PARAMS_IMM | 0x19) #ifdef DEBUG_EXTRA /*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/ -#define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f) +# define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f) #endif /*UOP_MOV_PTR - dest_reg = p*/ -#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) +#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20) /*UOP_MOV_IMM - dest_reg = imm_data*/ -#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) +#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21) /*UOP_MOV - dest_reg = src_reg_a*/ -#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) +#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22) /*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/ -#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) +#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23) /*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/ -#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) +#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24) /*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/ -#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25) +#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25) /*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ -#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26) +#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26) /*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/ -#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27) +#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27) /*UOP_MOV_REG_PTR - dest_reg = *p*/ -#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28) +#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28) /*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/ -#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29) +#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29) /*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/ -#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a) +#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a) /*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/ -#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) +#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30) /*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/ -#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) +#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31) /*UOP_AND - dest_reg = src_reg_a & src_reg_b*/ -#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) +#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32) /*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/ -#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) +#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33) /*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data) Intended for EA calcluations, imm_data must be between 0 and 3*/ -#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) +#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34) /*UOP_OR - dest_reg = src_reg_a | src_reg_b*/ -#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) +#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35) /*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/ -#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) +#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36) /*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/ -#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) +#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37) /*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/ -#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) +#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38) /*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/ -#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) +#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39) /*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/ -#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) +#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a) /*UOP_ANDN - dest_reg = ~src_reg_a & src_reg_b*/ -#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b) +#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b) /*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/ -#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/ -#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/ -#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/ -#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/ -#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/ -#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/ -#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_SINGLE - dest_reg = (float)src_reg_a:[src_reg_b]*/ -#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/ -#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) +#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_LOAD_DOUBLE - dest_reg = (double)src_reg_a:[src_reg_b]*/ -#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_SINGLE - src_reg_a:[src_reg_b] = src_reg_c*/ -#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER) /*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/ -#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER) +#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_JB - if (src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER) +#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER) /*UOP_CMP_JNBE - if (src_reg_a > src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER) +#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER) /*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/ -#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) +#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50) /*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/ -#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51) +#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51) /*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/ -#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52) +#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52) /*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/ -#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53) +#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53) /*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/ -#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54) +#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54) /*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/ -#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) +#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55) /*UOP_ROL - dest_reg = src_reg_a rotate<< src_reg_b*/ -#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56) +#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56) /*UOP_ROL_IMM - dest_reg = src_reg_a rotate<< immediate*/ -#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57) +#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57) /*UOP_ROR - dest_reg = src_reg_a rotate>> src_reg_b*/ -#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58) +#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58) /*UOP_ROR_IMM - dest_reg = src_reg_a rotate>> immediate*/ -#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59) +#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59) /*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/ -#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/ -#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/ -#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/ -#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/ -#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/ -#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) - +#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/ -#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/ -#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) +#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP) /*UOP_FP_ENTER - must be called before any FPU register accessed*/ -#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) +#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER) /*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) +#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81) /*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82) +#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82) /*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/ -#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83) +#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83) /*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/ -#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) +#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84) /*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/ -#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) +#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85) /*UOP_FABS - dest_reg = fabs(src_reg_a)*/ -#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86) +#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86) /*UOP_FCHS - dest_reg = fabs(src_reg_a)*/ -#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87) +#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87) /*UOP_FTST - dest_reg = flags from compare(src_reg_a, 0)*/ -#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88) +#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88) /*UOP_FSQRT - dest_reg = fsqrt(src_reg_a)*/ -#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89) +#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89) /*UOP_MMX_ENTER - must be called before any MMX registers accessed*/ -#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) +#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER) /*UOP_PADDB - (packed byte) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91) +#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91) /*UOP_PADDW - (packed word) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92) +#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92) /*UOP_PADDD - (packed long) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93) +#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93) /*UOP_PADDSB - (packed byte with signed saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94) +#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94) /*UOP_PADDSW - (packed word with signed saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95) +#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95) /*UOP_PADDUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96) +#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96) /*UOP_PADDUSW - (packed word with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97) +#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97) /*UOP_PSUBB - (packed byte) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98) +#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98) /*UOP_PSUBW - (packed word) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99) +#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99) /*UOP_PSUBD - (packed long) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a) +#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a) /*UOP_PSUBSB - (packed byte with signed saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b) +#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b) /*UOP_PSUBSW - (packed word with signed saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c) +#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c) /*UOP_PSUBUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) +#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) /*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) +#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) /*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/ -#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f) +#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f) /*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/ -#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0) +#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0) /*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/ -#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1) +#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1) /*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2) +#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2) /*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3) +#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3) /*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4) +#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4) /*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5) +#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5) /*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) +#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) /*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ -#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) +#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) /*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8) +#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8) /*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9) +#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9) /*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa) +#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa) /*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab) +#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab) /*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) +#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) /*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) +#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) /*UOP_PUNPCKLBW - (packed byte) dest_reg = interleave low src_reg_a/src_reg_b*/ -#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae) +#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae) /*UOP_PUNPCKLWD - (packed word) dest_reg = interleave low src_reg_a/src_reg_b*/ -#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf) +#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf) /*UOP_PUNPCKLDQ - (packed long) dest_reg = interleave low src_reg_a/src_reg_b*/ -#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0) +#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0) /*UOP_PUNPCKHBW - (packed byte) dest_reg = interleave high src_reg_a/src_reg_b*/ -#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1) +#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1) /*UOP_PUNPCKHWD - (packed word) dest_reg = interleave high src_reg_a/src_reg_b*/ -#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2) +#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2) /*UOP_PUNPCKHDQ - (packed long) dest_reg = interleave high src_reg_a/src_reg_b*/ -#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3) +#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3) /*UOP_PACKSSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with signed saturation*/ -#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4) +#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4) /*UOP_PACKSSDW - dest_reg = interleave src_reg_a/src_reg_b, converting longs to words with signed saturation*/ -#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5) +#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5) /*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/ -#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6) +#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6) /*UOP_PMULLW - (packed word) dest_reg = (src_reg_a * src_reg_b) & 0xffff*/ -#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7) +#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7) /*UOP_PMULHW - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ -#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8) +#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8) /*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/ -#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9) +#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9) /*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/ -#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba) +#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba) /*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/ -#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb) +#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb) /*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/ -#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc) +#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc) /*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/ -#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd) +#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd) /*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/ -#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe) +#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe) /*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ -#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf) +#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf) /*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/ -#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0) +#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0) /*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ -#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1) +#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1) /*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/ -#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2) +#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2) /*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/ -#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3) +#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3) /*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/ -#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4) +#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4) /*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/ -#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5) +#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5) -#define UOP_MAX 0xc6 +#define UOP_MAX 0xc6 #define UOP_INVALID 0xff -#define UOP_MASK 0xffff +#define UOP_MASK 0xffff -typedef struct uop_t -{ - uint32_t type; - ir_reg_t dest_reg_a; - ir_reg_t src_reg_a; - ir_reg_t src_reg_b; - ir_reg_t src_reg_c; - uint32_t imm_data; - void *p; - ir_host_reg_t dest_reg_a_real; - ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; - int jump_dest_uop; - int jump_list_next; - void *jump_dest; - uint32_t pc; +typedef struct uop_t { + uint32_t type; + ir_reg_t dest_reg_a; + ir_reg_t src_reg_a; + ir_reg_t src_reg_b; + ir_reg_t src_reg_c; + uint32_t imm_data; + void *p; + ir_host_reg_t dest_reg_a_real; + ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; + int jump_dest_uop; + int jump_list_next; + void *jump_dest; + uint32_t pc; } uop_t; #define UOP_NR_MAX 4096 -typedef struct ir_data_t -{ - uop_t uops[UOP_NR_MAX]; - int wr_pos; - struct codeblock_t *block; +typedef struct ir_data_t { + uop_t uops[UOP_NR_MAX]; + int wr_pos; + struct codeblock_t *block; } ir_data_t; -static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type) +static inline uop_t * +uop_alloc(ir_data_t *ir, uint32_t uop_type) { - uop_t *uop; + uop_t *uop; - if (ir->wr_pos >= UOP_NR_MAX) - fatal("Exceeded uOP max\n"); + if (ir->wr_pos >= UOP_NR_MAX) + fatal("Exceeded uOP max\n"); - uop = &ir->uops[ir->wr_pos++]; + uop = &ir->uops[ir->wr_pos++]; - uop->dest_reg_a = invalid_ir_reg; - uop->src_reg_a = invalid_ir_reg; - uop->src_reg_b = invalid_ir_reg; - uop->src_reg_c = invalid_ir_reg; + uop->dest_reg_a = invalid_ir_reg; + uop->src_reg_a = invalid_ir_reg; + uop->src_reg_b = invalid_ir_reg; + uop->src_reg_c = invalid_ir_reg; - uop->pc = cpu_state.oldpc; + uop->pc = cpu_state.oldpc; - uop->jump_dest_uop = -1; - uop->jump_list_next = -1; + uop->jump_dest_uop = -1; + uop->jump_list_next = -1; - if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) - codegen_reg_mark_as_required(); + if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) + codegen_reg_mark_as_required(); - return uop; + return uop; } -static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop) +static inline void +uop_set_jump_dest(ir_data_t *ir, int jump_uop) { - uop_t *uop = &ir->uops[jump_uop]; + uop_t *uop = &ir->uops[jump_uop]; - uop->jump_dest_uop = ir->wr_pos; + uop->jump_dest_uop = ir->wr_pos; } -static inline int uop_gen(uint32_t uop_type, ir_data_t *ir) +static inline int +uop_gen(uint32_t uop_type, ir_data_t *ir) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; + uop->type = uop_type; - return ir->wr_pos-1; + return ir->wr_pos - 1; } -static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) +static inline int +uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); - return ir->wr_pos-1; + return ir->wr_pos - 1; } -static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) +static inline void +uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); } -static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm) +static inline int +uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->imm_data = imm; - return ir->wr_pos-1; + return ir->wr_pos - 1; } -static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) +static inline void +uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p) +static inline void +uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->p = p; + uop->type = uop_type; + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->p = p; } -static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg) +static inline void +uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } -static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) +static inline void +uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) +static inline void +uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } -static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm) +static inline void +uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c) +static inline void +uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->src_reg_c = codegen_reg_read(src_reg_c); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); } -static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) +static inline void +uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg); - uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg); + uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1); + uop->imm_data = imm; } -static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b) +static inline int +uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); - return ir->wr_pos-1; + return ir->wr_pos - 1; } -static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) +static inline void +uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->imm_data = imm; } -static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c) +static inline void +uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); } -static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm) +static inline void +uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->src_reg_c = codegen_reg_read(src_reg_c); - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->src_reg_c = codegen_reg_read(src_reg_c); + uop->imm_data = imm; } -static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) +static inline void +uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->imm_data = imm; + uop->type = uop_type; + uop->imm_data = imm; } -static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) +static inline void +uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->p = p; + uop->type = uop_type; + uop->p = p; } -static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm) +static inline void +uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->p = p; - uop->imm_data = imm; + uop->type = uop_type; + uop->p = p; + uop->imm_data = imm; } -static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p) +static inline void +uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->p = p; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; } -static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) +static inline void +uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->p = p; - uop->imm_data = imm; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->p = p; + uop->imm_data = imm; } -static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p) +static inline void +uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p) { - uop_t *uop = uop_alloc(ir, uop_type); + uop_t *uop = uop_alloc(ir, uop_type); - uop->type = uop_type; - uop->src_reg_a = codegen_reg_read(src_reg_a); - uop->src_reg_b = codegen_reg_read(src_reg_b); - uop->p = p; + uop->type = uop_type; + uop->src_reg_a = codegen_reg_read(src_reg_a); + uop->src_reg_b = codegen_reg_read(src_reg_b); + uop->p = p; } -#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) +#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg) -#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) +#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm) -#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) +#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm) #define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift) -#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) -#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) -#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) +#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm) +#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm) +#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg) -#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm) -#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg) -#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm) -#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) -#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) -#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg) -#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm) -#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg) -#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg) +#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm) +#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg) +#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm) +#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg) +#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm) +#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg) +#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm) +#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg) +#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm) -#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) -#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) -#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) +#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) +#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) -#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) +#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) -#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm) -#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm) +#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm) +#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm) -#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p) -#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p) +#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p) +#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p) -#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b) -#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b) +#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b) -#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg) -#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg) -#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg) -#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg) +#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg) +#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg) +#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg) +#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg) -#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0) -#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0) +#define uop_FP_ENTER(ir) \ + do { \ + if (!codegen_fpu_entered) \ + uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); \ + codegen_fpu_entered = 1; \ + codegen_mmx_entered = 0; \ + } while (0) +#define uop_MMX_ENTER(ir) \ + do { \ + if (!codegen_mmx_entered) \ + uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); \ + codegen_mmx_entered = 1; \ + codegen_fpu_entered = 0; \ + } while (0) -#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) -#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) +#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p) +#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir) -#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) +#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p) -#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) -#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0) -#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset) -#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0) -#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0) -#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) -#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm) +#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset) +#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0) +#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm) +#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0) #define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset) -#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) -#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) -#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) -#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0) -#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm) +#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0) +#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0) -#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) -#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) -#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) -#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p) -#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p) -#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p) -#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) -#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) -#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) -#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/) -#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) +#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg) +#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm) +#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p) +#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p) +#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p) +#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p) +#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg) +#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg) +#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg) +#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg /*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg /*, nrc, orc*/) +#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag) -#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir) +#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir) -#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg) -#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg) -#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg) -#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg) +#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg) +#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg) +#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg) +#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg) -#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm) -#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b) -#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) -#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) -#define uop_STORE_PTR_IMM_16(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_16, ir, p, imm) +#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm) +#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm) +#define uop_STORE_PTR_IMM_16(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_16, ir, p, imm) -#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) -#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) +#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg) +#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg) #ifdef DEBUG_EXTRA -#define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm) +# define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm) #endif void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p); diff --git a/src/codegen_new/codegen_ops.h b/src/codegen_new/codegen_ops.h index 361479b6d..9cef07e15 100644 --- a/src/codegen_new/codegen_ops.h +++ b/src/codegen_new/codegen_ops.h @@ -29,21 +29,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512];*/ #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 -#define REG_AX 0 -#define REG_CX 1 -#define REG_DX 2 -#define REG_BX 3 -#define REG_SP 4 -#define REG_BP 5 -#define REG_SI 6 -#define REG_DI 7 -#define REG_AL 0 -#define REG_AH 4 -#define REG_CL 1 -#define REG_CH 5 -#define REG_DL 2 -#define REG_DH 6 -#define REG_BL 3 -#define REG_BH 7 +#define REG_AX 0 +#define REG_CX 1 +#define REG_DX 2 +#define REG_BX 3 +#define REG_SP 4 +#define REG_BP 5 +#define REG_SI 6 +#define REG_DI 7 +#define REG_AL 0 +#define REG_AH 4 +#define REG_CL 1 +#define REG_CH 5 +#define REG_DL 2 +#define REG_DH 6 +#define REG_BL 3 +#define REG_BH 7 #endif diff --git a/src/codegen_new/codegen_ops_3dnow.c b/src/codegen_new/codegen_ops_3dnow.c index 2c4ecc353..ff0c136e2 100644 --- a/src/codegen_new/codegen_ops_3dnow.c +++ b/src/codegen_new/codegen_ops_3dnow.c @@ -13,199 +13,184 @@ #include "codegen_ops_3dnow.h" #include "codegen_ops_helpers.h" -#define ropParith(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - codegen_mark_code_present(block, cs+op_pc+1, 1); \ - return op_pc + 2; \ -} +#define ropParith(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + codegen_mark_code_present(block, cs + op_pc + 1, 1); \ + return op_pc + 2; \ + } ropParith(PFADD) -ropParith(PFCMPEQ) -ropParith(PFCMPGE) -ropParith(PFCMPGT) -ropParith(PFMAX) -ropParith(PFMIN) -ropParith(PFMUL) -ropParith(PFSUB) + ropParith(PFCMPEQ) + ropParith(PFCMPGE) + ropParith(PFCMPGT) + ropParith(PFMAX) + ropParith(PFMIN) + ropParith(PFMUL) + ropParith(PFSUB) -uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg)); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg)); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q); + } - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MMX_ENTER(ir); + uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } diff --git a/src/codegen_new/codegen_ops_arith.c b/src/codegen_new/codegen_ops_arith.c index 66715730d..5325b282b 100644 --- a/src/codegen_new/codegen_ops_arith.c +++ b/src/codegen_new/codegen_ops_arith.c @@ -12,2509 +12,2378 @@ #include "codegen_ops_arith.h" #include "codegen_ops_helpers.h" -static inline void get_cf(ir_data_t *ir, int dest_reg) +static inline void +get_cf(ir_data_t *ir, int dest_reg) { - uop_CALL_FUNC_RESULT(ir, dest_reg, CF_SET); + uop_CALL_FUNC_RESULT(ir, dest_reg, CF_SET); } -uint32_t ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_ADD(ir, IREG_AL, IREG_AL, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_ADD(ir, IREG_AL, IREG_AL, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_ADD(ir, IREG_AX, IREG_AX, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_ADD(ir, IREG_AX, IREG_AX, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + fetchdat = fastreadl(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; +} +uint32_t +ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); + uop_ADD(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } + + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); + uop_ADD(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } + + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); + uop_ADD(ir, IREG_temp2, IREG_temp2, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp2); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; +} +uint32_t +ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { fetchdat = fastreadl(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + codegen_mark_code_present(block, cs + op_pc, 4); + } - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + codegen_flags_changed = 1; + return op_pc + 4; } -uint32_t ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); - uop_ADD(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); - uop_ADD(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); - } - - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); - uop_ADD(ir, IREG_temp2, IREG_temp2, IREG_temp1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_temp2); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_ADD_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_AL, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_ADD_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_AX, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV(ir, IREG_flags_op1, IREG_EAX); + fetchdat = fastreadl(cs + op_pc); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_ADD(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - uop_ADD_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - codegen_mark_code_present(block, cs+op_pc, 4); - } + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_flags_res_B, IREG_temp0_B, IREG_8(src_reg)); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_16(src_reg)); + } + + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint8_t imm_data = fastreadb(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_SUB(ir, IREG_AL, IREG_AL, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm_data = fastreadw(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_SUB(ir, IREG_AX, IREG_AX, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; +} +uint32_t +ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + fetchdat = fastreadl(cs + op_pc); + + get_cf(ir, IREG_temp0); + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; +} +uint32_t +ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } + + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); + uop_SUB(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); + uop_SUB(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + get_cf(ir, IREG_temp1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); + uop_SUB(ir, IREG_temp2, IREG_temp2, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp2); + } - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_AL, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_op1, IREG_AL); + uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_AX, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_op1, IREG_AX); + uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op2, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { + uop_MOV(ir, IREG_flags_op1, IREG_EAX); + + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { fetchdat = fastreadl(cs + op_pc); - - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - uop_SUB_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; -} -uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_flags_res_B, IREG_temp0_B, IREG_8(src_reg)); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_16(src_reg)); - } - - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_32(src_reg)); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint8_t imm_data = fastreadb(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_SUB(ir, IREG_AL, IREG_AL, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} -uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm_data = fastreadw(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_SUB(ir, IREG_AX, IREG_AX, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; -} -uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - fetchdat = fastreadl(cs + op_pc); - - get_cf(ir, IREG_temp0); - uop_MOV(ir, IREG_flags_op1, IREG_EAX); + codegen_mark_code_present(block, cs + op_pc, 4); uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + } - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); + + codegen_flags_changed = 1; + return op_pc + 4; } -uint32_t ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp2_B, IREG_temp0_B, IREG_8(src_reg)); - uop_SUB(ir, IREG_temp2_B, IREG_temp2_B, IREG_temp1_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp2_W, IREG_temp0_W, IREG_16(src_reg)); - uop_SUB(ir, IREG_temp2_W, IREG_temp2_W, IREG_temp1_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_temp2_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); - } - - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int skip_immediate = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - get_cf(ir, IREG_temp1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint8_t imm = fastreadb(cs + op_pc + 1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp2, IREG_temp0, IREG_32(src_reg)); - uop_SUB(ir, IREG_temp2, IREG_temp2, IREG_temp1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp2); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_temp2); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp0_B, cs + op_pc + 1); } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint8_t imm_data = fastreadb(cs + op_pc); - - uop_MOVZX(ir, IREG_flags_op1, IREG_AL); - uop_SUB_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} -uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm_data = fastreadw(cs + op_pc); - - uop_MOVZX(ir, IREG_flags_op1, IREG_AX); - uop_SUB_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op2, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; -} -uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uop_MOV(ir, IREG_flags_op1, IREG_EAX); - - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_SUB(ir, IREG_EAX, IREG_EAX, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_SUB_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - uop_MOV_IMM(ir, IREG_flags_op2, fetchdat); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); - - codegen_flags_changed = 1; - return op_pc + 4; -} -uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + else + uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + } else { + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint8_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); else - { - x86seg *target_seg; + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp1_B, IREG_temp0_B, IREG_8(src_reg)); + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_8(src_reg)); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; - codegen_flags_changed = 1; - return op_pc + 1; + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_ADD(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_B, IREG_temp0_B, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int skip_immediate = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint16_t imm = fastreadw(cs + op_pc + 1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp0_W, cs + op_pc + 1); } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + else + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + } else { + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint16_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); else - { - x86seg *target_seg; + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadw(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp2_W, cs + op_pc + 1); + } - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_16(src_reg)); + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_16(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp3); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x28: /*SUB*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); + else + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); + else + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); + uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_temp2_W); + } else { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + } + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs + op_pc + 1, 2); + return op_pc + 3; } -uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int skip_immediate = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint32_t imm = fastreadl(cs + op_pc + 1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_flags_op2, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_flags_op2); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc + 1); } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + else + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + } else { + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint32_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); else - { - x86seg *target_seg; + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadl(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + skip_immediate = 1; + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp2, cs + op_pc + 1); + } - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_32(src_reg)); + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_32(src_reg)); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); uop_MOV(ir, IREG_flags_res, IREG_temp1); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int skip_immediate = 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint8_t imm = fastreadb(cs + op_pc + 1); + break; + case 0x08: /*OR*/ if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp0_B, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - else - uop_OR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_ADD_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_ADD(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - else - uop_AND_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_SUB_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - else - uop_XOR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - } - else - { - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_8(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint8_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadb(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_ADD(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, IREG_temp2_B); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - break; - - case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0_B, IREG_temp0_B, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_B, IREG_temp0_B, imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - if (!skip_immediate) - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; -} -uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int skip_immediate = 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint16_t imm = fastreadw(cs + op_pc + 1); + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp3); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp0_W, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - else - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - else - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - else - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - } - else - { - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint16_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadw(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp3); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_16(block, ir, IREG_temp2_W, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); - else - uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp3_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); - else - uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x28: /*SUB*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2_W); - else - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2_W); - else - uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_MOVZX(ir, IREG_flags_op2, IREG_temp2_W); - uop_SUB(ir, IREG_flags_res_W, IREG_temp0_W, IREG_temp2_W); - } - else - { - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); - } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - if (!skip_immediate) - codegen_mark_code_present(block, cs+op_pc+1, 2); - return op_pc + 3; -} -uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int skip_immediate = 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint32_t imm = fastreadl(cs + op_pc + 1); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp3); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - else - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - else - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - else - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_SUB(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - } - else - { - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint32_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadl(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp3); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - skip_immediate = 1; - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp2, cs+op_pc+1); - } - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x08: /*OR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp2); - else - uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp3); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp3); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp3); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x20: /*AND*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_AND(ir, IREG_temp0, IREG_temp0, IREG_temp2); - else - uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x28: /*SUB*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); - else - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - else - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x30: /*XOR*/ - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_temp2); - else - uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_temp2); - } - else - { - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - if (!skip_immediate) - codegen_mark_code_present(block, cs+op_pc+1, 4); - return op_pc + 5; -} - -uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint16_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = (int16_t)(int8_t)fastreadb(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - break; - - case 0x38: /*CMP*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; -} -uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SUB*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - uint32_t imm; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x38) == 0x38) /*CMP*/ - codegen_check_seg_read(block, ir, target_seg); + case 0x20: /*AND*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_temp2); else - codegen_check_seg_write(block, ir, target_seg); - imm = (int32_t)(int8_t)fastreadb(cs + op_pc + 1); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - switch (fetchdat & 0x38) - { - case 0x00: /*ADD*/ - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; + case 0x28: /*SUB*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2); + else + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + else + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; - case 0x08: /*OR*/ - uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; + case 0x30: /*XOR*/ + if (block->flags & CODEBLOCK_NO_IMMEDIATES) + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + else + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; - case 0x10: /*ADC*/ - get_cf(ir, IREG_temp2); - uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x18: /*SBB*/ - get_cf(ir, IREG_temp2); - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x20: /*AND*/ - uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x28: /*SUB*/ - uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x30: /*XOR*/ - uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - break; - - case 0x38: /*CMP*/ - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - break; - - default: - return 0; + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_SUB(ir, IREG_flags_res, IREG_temp0, IREG_temp2); + } else { + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); } - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + default: + return 0; + } + } + + codegen_flags_changed = 1; + if (!skip_immediate) + codegen_mark_code_present(block, cs + op_pc + 1, 4); + return op_pc + 5; } -static void rebuild_c(ir_data_t *ir) +uint32_t +rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int needs_rebuild = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint16_t imm = (int16_t) (int8_t) fastreadb(cs + op_pc + 1); - if (codegen_flags_changed) - { - switch (cpu_state.flags_op) - { - case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32: - case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: - needs_rebuild = 0; - break; - } - } + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; - if (needs_rebuild) - { - uop_CALL_FUNC(ir, flags_rebuild_c); + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_ADD_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_16(dest_reg), imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; } + } else { + x86seg *target_seg; + uint16_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); + imm = (int16_t) (int8_t) fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_ADD(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, IREG_temp2_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0_W, IREG_temp0_W, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + break; + + case 0x38: /*CMP*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res_W, IREG_temp0_W, imm); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; +} +uint32_t +rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uint32_t imm = (int32_t) (int8_t) fastreadb(cs + op_pc + 1); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_ADD_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_ADD(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SUB*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SUB_IMM(ir, IREG_flags_res, IREG_32(dest_reg), imm); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + uint32_t imm; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x38) == 0x38) /*CMP*/ + codegen_check_seg_read(block, ir, target_seg); + else + codegen_check_seg_write(block, ir, target_seg); + imm = (int32_t) (int8_t) fastreadb(cs + op_pc + 1); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ADD*/ + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADD32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x08: /*OR*/ + uop_OR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x10: /*ADC*/ + get_cf(ir, IREG_temp2); + uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ADC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x18: /*SBB*/ + get_cf(ir, IREG_temp2); + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SBC32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x20: /*AND*/ + uop_AND_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x28: /*SUB*/ + uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x30: /*XOR*/ + uop_XOR_IMM(ir, IREG_temp0, IREG_temp0, imm); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + break; + + case 0x38: /*CMP*/ + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SUB_IMM(ir, IREG_flags_res, IREG_temp0, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropINC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static void +rebuild_c(ir_data_t *ir) { - rebuild_c(ir); + int needs_rebuild = 1; - uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); - uop_ADD_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); - uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + if (codegen_flags_changed) { + switch (cpu_state.flags_op) { + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + needs_rebuild = 0; + break; + } + } + + if (needs_rebuild) { + uop_CALL_FUNC(ir, flags_rebuild_c); + } +} + +uint32_t +ropINC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); + uop_ADD_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); + uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + codegen_flags_changed = 1; + + return op_pc; +} +uint32_t +ropINC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); + uop_ADD_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); + uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + codegen_flags_changed = 1; + + return op_pc; +} + +uint32_t +ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); + uop_SUB_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); + uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + codegen_flags_changed = 1; + + return op_pc; +} +uint32_t +ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + rebuild_c(ir); + + uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); + uop_SUB_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); + uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + codegen_flags_changed = 1; + + return op_pc; +} + +uint32_t +ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + codegen_mark_code_present(block, cs + op_pc, 1); + rebuild_c(ir); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op1, IREG_8(fetchdat & 7)); + if (fetchdat & 0x38) { + uop_SUB_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); + } else { + uop_ADD_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); + } + uop_MOVZX(ir, IREG_flags_res, IREG_8(fetchdat & 7)); uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); - codegen_flags_changed = 1; + } else { + x86seg *target_seg; - return op_pc; -} -uint32_t ropINC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - rebuild_c(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); - uop_ADD_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); - uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); - codegen_flags_changed = 1; - - return op_pc; -} - -uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - rebuild_c(ir); - - uop_MOVZX(ir, IREG_flags_op1, IREG_16(opcode & 7)); - uop_SUB_IMM(ir, IREG_16(opcode & 7), IREG_16(opcode & 7), 1); - uop_MOVZX(ir, IREG_flags_res, IREG_16(opcode & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); - codegen_flags_changed = 1; - - return op_pc; -} -uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - rebuild_c(ir); - - uop_MOV(ir, IREG_flags_op1, IREG_32(opcode & 7)); - uop_SUB_IMM(ir, IREG_32(opcode & 7), IREG_32(opcode & 7), 1); - uop_MOV(ir, IREG_flags_res, IREG_32(opcode & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); - codegen_flags_changed = 1; - - return op_pc; -} - -uint32_t ropINCDEC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - codegen_mark_code_present(block, cs+op_pc, 1); - rebuild_c(ir); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op1, IREG_8(fetchdat & 7)); - if (fetchdat & 0x38) - { - uop_SUB_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); - } - else - { - uop_ADD_IMM(ir, IREG_8(fetchdat & 7), IREG_8(fetchdat & 7), 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); - } - uop_MOVZX(ir, IREG_flags_res, IREG_8(fetchdat & 7)); - uop_MOV_IMM(ir, IREG_flags_op2, 1); + if (fetchdat & 0x38) { + uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); + } else { + uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - - if (fetchdat & 0x38) - { - uop_SUB_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); - } - else - { - uop_ADD_IMM(ir, IREG_temp1_B, IREG_temp0_B, 1); - } - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - if (fetchdat & 0x38) - { - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); - } - else - { - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); - } + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + if (fetchdat & 0x38) { + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC8); + } else { + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC8); } + } - return op_pc+1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_arith.h b/src/codegen_new/codegen_ops_arith.h index d1bbaa75d..176d4be7a 100644 --- a/src/codegen_new/codegen_ops_arith.h +++ b/src/codegen_new/codegen_ops_arith.h @@ -54,7 +54,6 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); - uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); diff --git a/src/codegen_new/codegen_ops_branch.c b/src/codegen_new/codegen_ops_branch.c index 70bfc1b10..85ebd3f8e 100644 --- a/src/codegen_new/codegen_ops_branch.c +++ b/src/codegen_new/codegen_ops_branch.c @@ -13,1002 +13,977 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" -static int NF_SET_01(void) +static int +NF_SET_01(void) { - return NF_SET() ? 1 : 0; + return NF_SET() ? 1 : 0; } -static int VF_SET_01(void) +static int +VF_SET_01(void) { - return VF_SET() ? 1 : 0; + return VF_SET() ? 1 : 0; } -static int ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop; + int jump_uop; - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Overflow is always zero*/ - return 0; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Overflow is always zero*/ + return 0; - case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; + case FLAGS_SUB8: + case FLAGS_DEC8: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; - case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; + case FLAGS_SUB16: + case FLAGS_DEC16: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; - case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; + case FLAGS_SUB32: + case FLAGS_DEC32: + jump_uop = uop_CMP_JNO_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; } -static int ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJNO_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop; + int jump_uop; - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Overflow is always zero*/ - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - return 0; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Overflow is always zero*/ + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + return 0; - case FLAGS_SUB8: case FLAGS_DEC8: - jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; + case FLAGS_SUB8: + case FLAGS_DEC8: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; - case FLAGS_SUB16: case FLAGS_DEC16: - jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; + case FLAGS_SUB16: + case FLAGS_DEC16: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; - case FLAGS_SUB32: case FLAGS_DEC32: - jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; + case FLAGS_SUB32: + case FLAGS_DEC32: + jump_uop = uop_CMP_JO_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, VF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} + +static int +ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero*/ + return 0; + + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + if (do_unroll) jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - break; + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} +static int +ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (!CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero*/ + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + return 0; + + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} + +static int +ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); } uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); uop_set_jump_dest(ir, jump_uop); - return 0; + } + return 0; +} +int +ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + } + return 0; } -static int ropJB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +static int +ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - int jump_uop; - int do_unroll = (CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + int jump_uop, jump_uop2 = -1; + int do_unroll = ((CF_SET() || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero*/ - return 0; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero, so test zero only*/ + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + break; - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: + case FLAGS_UNKNOWN: + default: + if (do_unroll) { uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} -static int ropJNB_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = (!CF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero*/ - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - return 0; - - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JNB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JB_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} - -static int ropJE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - if (ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - } - return 0; -} -int ropJNE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - if (!ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)) - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - if (!codegen_flags_changed || !flags_res_valid()) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - } - return 0; -} - -static int ropJBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = ((CF_SET() || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero, so test zero only*/ - if (do_unroll) - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - break; - - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - break; - } - if (do_unroll) - { - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 1; - } - else - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; - } -} -static int ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = ((!CF_SET() && !ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: case FLAGS_ZN16: case FLAGS_ZN32: - /*Carry is always zero, so test zero only*/ - if (do_unroll) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - else - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - break; - - case FLAGS_SUB8: - if (do_unroll) - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: - if (do_unroll) - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: - if (do_unroll) - jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - break; - } - if (do_unroll) - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 0; - } -} - -static int ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = (NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - break; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - break; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} -static int ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = (!NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - break; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - break; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); - if (do_unroll) - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - break; - } - uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} - -static int ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; -} -static int ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - - uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; -} - -static int ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = ((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - /*V flag is always clear. Condition is true if N is set*/ - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - break; - case FLAGS_ZN16: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - break; - case FLAGS_ZN32: - if (do_unroll) - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - if (do_unroll) - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - else - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - break; - } - if (do_unroll) - uop_MOV_IMM(ir, IREG_pc, next_pc); - else - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} -static int ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop; - int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_ZN8: - /*V flag is always clear. Condition is true if N is set*/ - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); - break; - case FLAGS_ZN16: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); - break; - case FLAGS_ZN32: - if (do_unroll) - jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); - else - jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); - break; - - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - if (do_unroll) - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - else - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - break; - } - if (do_unroll) - uop_MOV_IMM(ir, IREG_pc, next_pc); - else - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return do_unroll ? 1 : 0; -} - -static int ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = (((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - } - break; - } - if (do_unroll) - { - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 1; - } - else - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 0; - } -} -static int ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) -{ - int jump_uop, jump_uop2 = -1; - int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && !ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); - - switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) - { - case FLAGS_SUB8: case FLAGS_DEC8: - if (do_unroll) - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - else - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); - break; - case FLAGS_SUB16: case FLAGS_DEC16: - if (do_unroll) - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - else - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); - break; - case FLAGS_SUB32: case FLAGS_DEC32: - if (do_unroll) - jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - else - jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); - break; - - case FLAGS_UNKNOWN: - default: - if (do_unroll) - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); - } - else - { - uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); - uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); - jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); - } - break; - } - if (do_unroll) - { - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - uop_MOV_IMM(ir, IREG_pc, next_pc); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - return 1; - } - else - { - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - if (jump_uop2 != -1) - uop_set_jump_dest(ir, jump_uop2); - return 0; - } -} - -#define ropJ(cond) \ -uint32_t ropJ ## cond ## _8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); \ - uint32_t dest_addr = op_pc + 1 + offset; \ - int ret; \ - \ - if (!(op_32 & 0x100)) \ - dest_addr &= 0xffff; \ - ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+1); \ - \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - return ret ? dest_addr : (op_pc+1); \ -} \ -uint32_t ropJ ## cond ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); \ - uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ - int ret; \ - \ - ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+2); \ - \ - codegen_mark_code_present(block, cs+op_pc, 2); \ - return ret ? dest_addr : (op_pc+2); \ -} \ -uint32_t ropJ ## cond ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uint32_t offset = fastreadl(cs + op_pc); \ - uint32_t dest_addr = op_pc + 4 + offset; \ - int ret; \ - \ - ret = ropJ ## cond ## _common(block, ir, dest_addr, op_pc+4); \ - \ - codegen_mark_code_present(block, cs+op_pc, 4); \ - return ret ? dest_addr : (op_pc+4); \ -} - -ropJ(O) -ropJ(NO) -ropJ(B) -ropJ(NB) -ropJ(E) -ropJ(NE) -ropJ(BE) -ropJ(NBE) -ropJ(S) -ropJ(NS) -ropJ(P) -ropJ(NP) -ropJ(L) -ropJ(NL) -ropJ(LE) -ropJ(NLE) - - -uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - int jump_uop; - - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; - - if (op_32 & 0x200) - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); - else - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; -} - -uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - uint32_t ret_addr; - int jump_uop; - - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; - - if (((op_32 & 0x200) ? ECX : CX) != 1 && codegen_can_unroll(block, ir, op_pc+1, dest_addr)) - { - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); - } - uop_MOV_IMM(ir, IREG_pc, op_pc+1); - ret_addr = dest_addr; - CPU_BLOCK_END(); - } - else - { - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); - } - uop_MOV_IMM(ir, IREG_pc, dest_addr); - ret_addr = op_pc+1; - } - uop_JMP(ir, codegen_exit_rout); - uop_set_jump_dest(ir, jump_uop); - - codegen_mark_code_present(block, cs+op_pc, 1); - return ret_addr; -} - -uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - int jump_uop, jump_uop2; - - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; - - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); - } - if (!codegen_flags_changed || !flags_res_valid()) - { + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); - jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); - } + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } + break; + } + if (do_unroll) { + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 1; + } else { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); - uop_NOP_BARRIER(ir); uop_set_jump_dest(ir, jump_uop); - uop_set_jump_dest(ir, jump_uop2); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; + return 0; + } } -uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static int +ropJNBE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc + 1 + offset; - int jump_uop, jump_uop2; + int jump_uop, jump_uop2 = -1; + int do_unroll = ((!CF_SET() && !ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ZN16: + case FLAGS_ZN32: + /*Carry is always zero, so test zero only*/ + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + break; - if (op_32 & 0x200) - { - uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); - } - else - { - uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); - } - if (!codegen_flags_changed || !flags_res_valid()) - { + case FLAGS_SUB8: + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + if (do_unroll) + jump_uop = uop_CMP_JNBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JBE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + if (do_unroll) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, CF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); - } - else - { - jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); - } + } + break; + } + if (do_unroll) { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { uop_MOV_IMM(ir, IREG_pc, dest_addr); uop_JMP(ir, codegen_exit_rout); - uop_NOP_BARRIER(ir); uop_set_jump_dest(ir, jump_uop); - uop_set_jump_dest(ir, jump_uop2); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc+1; + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 0; + } +} + +static int +ropJS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + break; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + break; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); + if (do_unroll) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} +static int +ropJNS_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = (!NF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + case FLAGS_ADD8: + case FLAGS_SUB8: + case FLAGS_SHL8: + case FLAGS_SHR8: + case FLAGS_SAR8: + case FLAGS_INC8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + break; + + case FLAGS_ZN16: + case FLAGS_ADD16: + case FLAGS_SUB16: + case FLAGS_SHL16: + case FLAGS_SHR16: + case FLAGS_SAR16: + case FLAGS_INC16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + break; + + case FLAGS_ZN32: + case FLAGS_ADD32: + case FLAGS_SUB32: + case FLAGS_SHL32: + case FLAGS_SHR32: + case FLAGS_SAR32: + case FLAGS_INC32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET); + if (do_unroll) + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + break; + } + uop_MOV_IMM(ir, IREG_pc, do_unroll ? next_pc : dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} + +static int +ropJP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} +static int +ropJNP_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + + uop_CALL_FUNC_RESULT(ir, IREG_temp0, PF_SET); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; +} + +static int +ropJL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = ((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + /*V flag is always clear. Condition is true if N is set*/ + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + break; + case FLAGS_ZN16: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + break; + case FLAGS_ZN32: + if (do_unroll) + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + if (do_unroll) + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + else + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + if (do_unroll) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} +static int +ropJNL_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop; + int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_ZN8: + /*V flag is always clear. Condition is true if N is set*/ + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_B); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_B); + break; + case FLAGS_ZN16: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res_W); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res_W); + break; + case FLAGS_ZN32: + if (do_unroll) + jump_uop = uop_TEST_JNS_DEST(ir, IREG_flags_res); + else + jump_uop = uop_TEST_JS_DEST(ir, IREG_flags_res); + break; + + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JNL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JL_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + if (do_unroll) + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + else + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + break; + } + if (do_unroll) + uop_MOV_IMM(ir, IREG_pc, next_pc); + else + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return do_unroll ? 1 : 0; +} + +static int +ropJLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop, jump_uop2 = -1; + int do_unroll = (((NF_SET() ? 1 : 0) != (VF_SET() ? 1 : 0) || ZF_SET()) && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + if (do_unroll) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + } + break; + } + if (do_unroll) { + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 1; + } else { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 0; + } +} +static int +ropJNLE_common(codeblock_t *block, ir_data_t *ir, uint32_t dest_addr, uint32_t next_pc) +{ + int jump_uop, jump_uop2 = -1; + int do_unroll = ((NF_SET() ? 1 : 0) == (VF_SET() ? 1 : 0) && !ZF_SET() && codegen_can_unroll(block, ir, next_pc, dest_addr)); + + switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { + case FLAGS_SUB8: + case FLAGS_DEC8: + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_B, IREG_flags_op2_B); + break; + case FLAGS_SUB16: + case FLAGS_DEC16: + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1_W, IREG_flags_op2_W); + break; + case FLAGS_SUB32: + case FLAGS_DEC32: + if (do_unroll) + jump_uop = uop_CMP_JNLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + else + jump_uop = uop_CMP_JLE_DEST(ir, IREG_flags_op1, IREG_flags_op2); + break; + + case FLAGS_UNKNOWN: + default: + if (do_unroll) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JZ_DEST(ir, IREG_temp0, IREG_temp1); + } else { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + uop_CALL_FUNC_RESULT(ir, IREG_temp0, NF_SET_01); + uop_CALL_FUNC_RESULT(ir, IREG_temp1, VF_SET_01); + jump_uop = uop_CMP_JNZ_DEST(ir, IREG_temp0, IREG_temp1); + } + break; + } + if (do_unroll) { + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + uop_MOV_IMM(ir, IREG_pc, next_pc); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + return 1; + } else { + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + if (jump_uop2 != -1) + uop_set_jump_dest(ir, jump_uop2); + return 0; + } +} + +#define ropJ(cond) \ + uint32_t ropJ##cond##_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); \ + uint32_t dest_addr = op_pc + 1 + offset; \ + int ret; \ + \ + if (!(op_32 & 0x100)) \ + dest_addr &= 0xffff; \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 1); \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + return ret ? dest_addr : (op_pc + 1); \ + } \ + uint32_t ropJ##cond##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); \ + uint32_t dest_addr = (op_pc + 2 + offset) & 0xffff; \ + int ret; \ + \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 2); \ + \ + codegen_mark_code_present(block, cs + op_pc, 2); \ + return ret ? dest_addr : (op_pc + 2); \ + } \ + uint32_t ropJ##cond##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uint32_t offset = fastreadl(cs + op_pc); \ + uint32_t dest_addr = op_pc + 4 + offset; \ + int ret; \ + \ + ret = ropJ##cond##_common(block, ir, dest_addr, op_pc + 4); \ + \ + codegen_mark_code_present(block, cs + op_pc, 4); \ + return ret ? dest_addr : (op_pc + 4); \ + } + +ropJ(O) + ropJ(NO) + ropJ(B) + ropJ(NB) + ropJ(E) + ropJ(NE) + ropJ(BE) + ropJ(NBE) + ropJ(S) + ropJ(NS) + ropJ(P) + ropJ(NP) + ropJ(L) + ropJ(NL) + ropJ(LE) + ropJ(NLE) + + uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + int jump_uop; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (op_32 & 0x200) + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); + else + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} + +uint32_t +ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + uint32_t ret_addr; + int jump_uop; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (((op_32 & 0x200) ? ECX : CX) != 1 && codegen_can_unroll(block, ir, op_pc + 1, dest_addr)) { + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JNZ_DEST(ir, IREG_CX, 0); + } + uop_MOV_IMM(ir, IREG_pc, op_pc + 1); + ret_addr = dest_addr; + CPU_BLOCK_END(); + } else { + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + ret_addr = op_pc + 1; + } + uop_JMP(ir, codegen_exit_rout); + uop_set_jump_dest(ir, jump_uop); + + codegen_mark_code_present(block, cs + op_pc, 1); + return ret_addr; +} + +uint32_t +ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + int jump_uop, jump_uop2; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + uop_set_jump_dest(ir, jump_uop2); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + int jump_uop, jump_uop2; + + if (!(op_32 & 0x100)) + dest_addr &= 0xffff; + + if (op_32 & 0x200) { + uop_SUB_IMM(ir, IREG_ECX, IREG_ECX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_ECX, 0); + } else { + uop_SUB_IMM(ir, IREG_CX, IREG_CX, 1); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_CX, 0); + } + if (!codegen_flags_changed || !flags_res_valid()) { + uop_CALL_FUNC_RESULT(ir, IREG_temp0, ZF_SET); + jump_uop2 = uop_CMP_IMM_JNZ_DEST(ir, IREG_temp0, 0); + } else { + jump_uop2 = uop_CMP_IMM_JZ_DEST(ir, IREG_flags_res, 0); + } + uop_MOV_IMM(ir, IREG_pc, dest_addr); + uop_JMP(ir, codegen_exit_rout); + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + uop_set_jump_dest(ir, jump_uop2); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c index 598f63b80..e9739f830 100644 --- a/src/codegen_new/codegen_ops_fpu_arith.c +++ b/src/codegen_new/codegen_ops_fpu_arith.c @@ -14,562 +14,588 @@ #include "codegen_ops_fpu_arith.h" #include "codegen_ops_helpers.h" -uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - return op_pc; + return op_pc; } -uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP2(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP2(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - return op_pc; + return op_pc; } -uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - fpu_POP2(block, ir); + uop_FP_ENTER(ir); + uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + fpu_POP2(block, ir); - return op_pc; + return op_pc; } -#define ropF_arith_mem(name, load_uop) \ -uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - if ((cpu_state.npxc >> 10) & 3) \ - return 0; \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFCOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(block, ir); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFSUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFSUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} +#define ropF_arith_mem(name, load_uop) \ + uint32_t ropFADD##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + if ((cpu_state.npxc >> 10) & 3) \ + return 0; \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFCOM##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFCOMP##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(block, ir); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFDIV##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFDIVR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFMUL##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFSUB##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFSUBR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } ropF_arith_mem(s, uop_MEM_LOAD_SINGLE) -ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) + ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) -#define ropFI_arith_mem(name, temp_reg) \ -uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFICOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \ - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ - fpu_POP(block, ir); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFIDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFIMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFISUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} \ -uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\ -{ \ - x86seg *target_seg; \ - \ - uop_FP_ENTER(ir); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - op_pc--; \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ - uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ - \ - return op_pc+1; \ -} +#define ropFI_arith_mem(name, temp_reg) \ + uint32_t ropFIADD##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFICOM##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFICOMP##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ + fpu_POP(block, ir); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIDIV##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIDIVR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFIMUL##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFISUB##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } \ + uint32_t ropFISUBR##name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg; \ + \ + uop_FP_ENTER(ir); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + op_pc--; \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ + uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \ + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \ + \ + return op_pc + 1; \ + } -ropFI_arith_mem(l, IREG_temp0) -ropFI_arith_mem(w, IREG_temp0_W) + ropFI_arith_mem(l, IREG_temp0) + ropFI_arith_mem(w, IREG_temp0_W) - -uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FABS(ir, IREG_ST(0), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FABS(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FCHS(ir, IREG_ST(0), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FCHS(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FSQRT(ir, IREG_ST(0), IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); + uop_FP_ENTER(ir); + uop_FSQRT(ir, IREG_ST(0), IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); - return op_pc; + return op_pc; } -uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); - uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); + uop_FP_ENTER(ir); + uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_ops_fpu_constant.c b/src/codegen_new/codegen_ops_fpu_constant.c index fc59ae784..89c138637 100644 --- a/src/codegen_new/codegen_ops_fpu_constant.c +++ b/src/codegen_new/codegen_ops_fpu_constant.c @@ -14,23 +14,25 @@ #include "codegen_ops_fpu_constant.h" #include "codegen_ops_helpers.h" -uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_temp0, 1); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_temp0, 1); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_temp0, 0); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_temp0, 0); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_ops_fpu_loadstore.c b/src/codegen_new/codegen_ops_fpu_loadstore.c index 349d10de7..06709913d 100644 --- a/src/codegen_new/codegen_ops_fpu_loadstore.c +++ b/src/codegen_new/codegen_ops_fpu_loadstore.c @@ -14,221 +14,234 @@ #include "codegen_ops_fpu_arith.h" #include "codegen_ops_helpers.h" -uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); - uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); + uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); - uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); + uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0)); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } - -uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1)); - uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1)); + uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64); + fpu_PUSH(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); - uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q); + uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY); + fpu_POP(block, ir); - return op_pc+1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_fpu_misc.c b/src/codegen_new/codegen_ops_fpu_misc.c index cfe2ff698..cca9f4e4f 100644 --- a/src/codegen_new/codegen_ops_fpu_misc.c +++ b/src/codegen_new/codegen_ops_fpu_misc.c @@ -14,101 +14,109 @@ #include "codegen_ops_fpu_misc.h" #include "codegen_ops_helpers.h" -uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY); - return op_pc; + return op_pc; } -uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = fetchdat & 7; + int src_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); - uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg)); - uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); - fpu_PUSH(block, ir); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg)); + uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg)); + uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg)); + fpu_PUSH(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); - uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); - return op_pc; + return op_pc; } -uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); - uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); - uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); - fpu_POP(block, ir); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0)); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0)); + uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0)); + fpu_POP(block, ir); - return op_pc; + return op_pc; } -uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg; + x86seg *target_seg; - uop_FP_ENTER(ir); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - op_pc--; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS); + uop_FP_ENTER(ir); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + op_pc--; + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS); - return op_pc+1; + return op_pc + 1; } -uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_AX, IREG_NPXS); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_AX, IREG_NPXS); - return op_pc; + return op_pc; } -uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = fetchdat & 7; + int dest_reg = fetchdat & 7; - uop_FP_ENTER(ir); - uop_MOV(ir, IREG_temp0_D, IREG_ST(0)); - uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0)); - uop_MOV(ir, IREG_temp2, IREG_tag(0)); - uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg)); - uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg)); - uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg)); - uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D); - uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q); - uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2); + uop_FP_ENTER(ir); + uop_MOV(ir, IREG_temp0_D, IREG_ST(0)); + uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0)); + uop_MOV(ir, IREG_temp2, IREG_tag(0)); + uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg)); + uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg)); + uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg)); + uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D); + uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q); + uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_ops_helpers.c b/src/codegen_new/codegen_ops_helpers.c index 9c2280f07..242cbb818 100644 --- a/src/codegen_new/codegen_ops_helpers.c +++ b/src/codegen_new/codegen_ops_helpers.c @@ -11,65 +11,64 @@ #include "codegen_reg.h" #include "codegen_ops_helpers.h" -void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +void +LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - /*Word access that crosses two pages. Perform reads from both pages, shift and combine*/ - uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr)); - uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1)); - uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8); - uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W); + /*Word access that crosses two pages. Perform reads from both pages, shift and combine*/ + uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr)); + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr + 1)); + uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8); + uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W); } -void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +void +LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - /*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/ - uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3)); - uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3)); - uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8); - uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8); - uop_OR(ir, dest_reg, dest_reg, IREG_temp3); + /*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/ + uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3)); + uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3)); + uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8); + uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8); + uop_OR(ir, dest_reg, dest_reg, IREG_temp3); } #define UNROLL_MAX_REG_REFERENCES 200 -#define UNROLL_MAX_UOPS 1000 -#define UNROLL_MAX_COUNT 10 -int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) +#define UNROLL_MAX_UOPS 1000 +#define UNROLL_MAX_COUNT 10 +int +codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { - int start; - int max_unroll; - int first_instruction; - int TOP = -1; + int start; + int max_unroll; + int first_instruction; + int TOP = -1; - /*Check that dest instruction was actually compiled into block*/ - start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP); + /*Check that dest instruction was actually compiled into block*/ + start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP); - /*Couldn't find any uOPs corresponding to the destination instruction*/ - if (start == -1) - { - /*Is instruction jumping to itself?*/ - if (dest_addr != cpu_state.oldpc) - { - return 0; - } - else - { - start = ir->wr_pos; - TOP = cpu_state.TOP; - } + /*Couldn't find any uOPs corresponding to the destination instruction*/ + if (start == -1) { + /*Is instruction jumping to itself?*/ + if (dest_addr != cpu_state.oldpc) { + return 0; + } else { + start = ir->wr_pos; + TOP = cpu_state.TOP; } + } - if (TOP != cpu_state.TOP) - return 0; + if (TOP != cpu_state.TOP) + return 0; - max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6); - if ((max_version_refcount != 0) && (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))) - max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount); - if (max_unroll > UNROLL_MAX_COUNT) - max_unroll = UNROLL_MAX_COUNT; - if (max_unroll <= 1) - return 0; + max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos - start) + 6); + if ((max_version_refcount != 0) && (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))) + max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount); + if (max_unroll > UNROLL_MAX_COUNT) + max_unroll = UNROLL_MAX_COUNT; + if (max_unroll <= 1) + return 0; - codegen_ir_set_unroll(max_unroll, start, first_instruction); + codegen_ir_set_unroll(max_unroll, start, first_instruction); - return 1; + return 1; } diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 41ffe297f..5a8f1e1c7 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -1,126 +1,127 @@ #include "386_common.h" #include "codegen_backend.h" -static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) +static inline int +LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset) { - if (stack32) - { - if (offset) - { - uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset); - return IREG_eaaddr; - } - else - return IREG_ESP; - } - else - { - if (offset) - { - uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset); - uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W); - return IREG_eaaddr; - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - return IREG_eaaddr; - } + if (stack32) { + if (offset) { + uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset); + return IREG_eaaddr; + } else + return IREG_ESP; + } else { + if (offset) { + uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset); + uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W); + return IREG_eaaddr; + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + return IREG_eaaddr; } + } } -static inline int LOAD_SP(ir_data_t *ir) +static inline int +LOAD_SP(ir_data_t *ir) { - return LOAD_SP_WITH_OFFSET(ir, 0); + return LOAD_SP_WITH_OFFSET(ir, 0); } -static inline void ADD_SP(ir_data_t *ir, int offset) +static inline void +ADD_SP(ir_data_t *ir, int offset) { - if (stack32) - uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset); - else - uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset); + if (stack32) + uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset); + else + uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset); } -static inline void SUB_SP(ir_data_t *ir, int offset) +static inline void +SUB_SP(ir_data_t *ir, int offset) { - if (stack32) - uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset); - else - uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); + if (stack32) + uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset); + else + uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset); } -static inline void fpu_POP(codeblock_t *block, ir_data_t *ir) +static inline void +fpu_POP(codeblock_t *block, ir_data_t *ir) { - if (block->flags & CODEBLOCK_STATIC_TOP) - uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1); - else - uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1); + else + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } -static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir) +static inline void +fpu_POP2(codeblock_t *block, ir_data_t *ir) { - if (block->flags & CODEBLOCK_STATIC_TOP) - uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2); - else - uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2); + else + uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2); } -static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir) +static inline void +fpu_PUSH(codeblock_t *block, ir_data_t *ir) { - if (block->flags & CODEBLOCK_STATIC_TOP) - uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); - else - uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); + if (block->flags & CODEBLOCK_STATIC_TOP) + uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1); + else + uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1); } -static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset) +static inline void +CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, 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 ((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; - uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout); - if (end_offset) - { - uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset); - uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout); - } - else - uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout); + uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout); + if (end_offset) { + uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset); + uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout); + } else + uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout); } -static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +static inline void +LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); + uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr)); } void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr); -static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +static inline void +LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - if ((addr & 0xfff) == 0xfff) - LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr); - else - uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr)); + if ((addr & 0xfff) == 0xfff) + LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr); + else + uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr)); } void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr); -static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) +static inline void +LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr) { - if ((addr & 0xfff) >= 0xffd) - LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr); - else - uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr)); + if ((addr & 0xfff) >= 0xffd) + LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr); + else + uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr)); } int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr); -static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) +static inline int +codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { - if (block->flags & CODEBLOCK_BYTE_MASK) - return 0; + if (block->flags & CODEBLOCK_BYTE_MASK) + return 0; - /*Is dest within block?*/ - if (dest_addr > next_pc) - return 0; - if ((cs+dest_addr) < block->pc) - return 0; + /*Is dest within block?*/ + if (dest_addr > next_pc) + return 0; + if ((cs + dest_addr) < block->pc) + return 0; - return codegen_can_unroll_full(block, ir, next_pc, dest_addr); + return codegen_can_unroll_full(block, ir, next_pc, dest_addr); } diff --git a/src/codegen_new/codegen_ops_jump.c b/src/codegen_new/codegen_ops_jump.c index f672b40ca..0bd4db24a 100644 --- a/src/codegen_new/codegen_ops_jump.c +++ b/src/codegen_new/codegen_ops_jump.c @@ -11,282 +11,281 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" -uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); - uint32_t dest_addr = op_pc+1+offset; - - if (!(op_32 & 0x100)) - dest_addr &= 0xffff; - - if (offset < 0) - codegen_can_unroll(block, ir, op_pc+1, dest_addr); - codegen_mark_code_present(block, cs+op_pc, 1); - return dest_addr; -} -uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); - uint32_t dest_addr = op_pc+2+offset; + uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc); + uint32_t dest_addr = op_pc + 1 + offset; + if (!(op_32 & 0x100)) dest_addr &= 0xffff; - if (offset < 0) - codegen_can_unroll(block, ir, op_pc+1, dest_addr); - codegen_mark_code_present(block, cs+op_pc, 2); - return dest_addr; + if (offset < 0) + codegen_can_unroll(block, ir, op_pc + 1, dest_addr); + codegen_mark_code_present(block, cs + op_pc, 1); + return dest_addr; } -uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = fastreadl(cs + op_pc); - uint32_t dest_addr = op_pc+4+offset; + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); + uint32_t dest_addr = op_pc + 2 + offset; - if (offset < 0) - codegen_can_unroll(block, ir, op_pc+1, dest_addr); - codegen_mark_code_present(block, cs+op_pc, 4); - return dest_addr; + dest_addr &= 0xffff; + + if (offset < 0) + codegen_can_unroll(block, ir, op_pc + 1, dest_addr); + codegen_mark_code_present(block, cs + op_pc, 2); + return dest_addr; } - -uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t new_pc = fastreadw(cs + op_pc); - uint16_t new_cs = fastreadw(cs + op_pc + 2); + uint32_t offset = fastreadl(cs + op_pc); + uint32_t dest_addr = op_pc + 4 + offset; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_MOV_IMM(ir, IREG_pc, new_pc); - uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); - uop_CALL_FUNC(ir, loadcsjmp); - - codegen_mark_code_present(block, cs+op_pc, 4); - return -1; + if (offset < 0) + codegen_can_unroll(block, ir, op_pc + 1, dest_addr); + codegen_mark_code_present(block, cs + op_pc, 4); + return dest_addr; } -uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t new_pc = fastreadl(cs + op_pc); - uint16_t new_cs = fastreadw(cs + op_pc + 4); + uint16_t new_pc = fastreadw(cs + op_pc); + uint16_t new_cs = fastreadw(cs + op_pc + 2); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_MOV_IMM(ir, IREG_pc, new_pc); - uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); - uop_CALL_FUNC(ir, loadcsjmp); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_pc, new_pc); + uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); + uop_CALL_FUNC(ir, loadcsjmp); - codegen_mark_code_present(block, cs+op_pc, 6); - return -1; + codegen_mark_code_present(block, cs + op_pc, 4); + return -1; } - -uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); - uint16_t ret_addr = op_pc + 2; - uint16_t dest_addr = ret_addr + offset; - int sp_reg; + uint32_t new_pc = fastreadl(cs + op_pc); + uint16_t new_cs = fastreadw(cs + op_pc + 4); - dest_addr &= 0xffff; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_pc, new_pc); + uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4); + uop_CALL_FUNC(ir, loadcsjmp); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr); - SUB_SP(ir, 2); - uop_MOV_IMM(ir, IREG_pc, dest_addr); - - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + codegen_mark_code_present(block, cs + op_pc, 6); + return -1; } -uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = fastreadl(cs + op_pc); - uint32_t ret_addr = op_pc + 4; - uint32_t dest_addr = ret_addr + offset; - int sp_reg; + uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc); + uint16_t ret_addr = op_pc + 2; + uint16_t dest_addr = ret_addr + offset; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr); - SUB_SP(ir, 4); - uop_MOV_IMM(ir, IREG_pc, dest_addr); + dest_addr &= 0xffff; - codegen_mark_code_present(block, cs+op_pc, 4); - return -1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr); + SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_pc, dest_addr); + + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } - -uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uint32_t offset = fastreadl(cs + op_pc); + uint32_t ret_addr = op_pc + 4; + uint32_t dest_addr = ret_addr + offset; + int sp_reg; - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 2); - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr); + SUB_SP(ir, 4); + uop_MOV_IMM(ir, IREG_pc, dest_addr); - return -1; + codegen_mark_code_present(block, cs + op_pc, 4); + return -1; } -uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 4); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 2); + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - return -1; + return -1; } - -uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 4); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 2+offset); - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + return -1; } -uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t offset = fastreadw(cs + op_pc); + uint16_t offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); - } - ADD_SP(ir, 4+offset); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 2 + offset); + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } - -uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + uint16_t offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); - } - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 4); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr); + } + ADD_SP(ir, 4 + offset); - return -1; + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } -uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); - } - uop_MOV(ir, IREG_pc, IREG_temp0); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 8); + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); + } + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 4); - return -1; + return -1; } - -uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t offset; + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); + } + uop_MOV(ir, IREG_pc, IREG_temp0); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 8); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); - } - uop_MOVZX(ir, IREG_pc, IREG_temp0_W); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 4+offset); - - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + return -1; } -uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t offset; + uint16_t offset; - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) - return 0; + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; - offset = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - { - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); - } - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); - } - uop_MOV(ir, IREG_pc, IREG_temp0); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_CALL_FUNC(ir, loadcs); - ADD_SP(ir, 8+offset); + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2); + } + uop_MOVZX(ir, IREG_pc, IREG_temp0_W); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 4 + offset); - codegen_mark_code_present(block, cs+op_pc, 2); - return -1; + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; +} +uint32_t +ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t offset; + + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) + return 0; + + offset = fastreadw(cs + op_pc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) { + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4); + } else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4); + } + uop_MOV(ir, IREG_pc, IREG_temp0); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_CALL_FUNC(ir, loadcs); + ADD_SP(ir, 8 + offset); + + codegen_mark_code_present(block, cs + op_pc, 2); + return -1; } diff --git a/src/codegen_new/codegen_ops_logic.c b/src/codegen_new/codegen_ops_logic.c index dd02bd3f9..6db452a45 100644 --- a/src/codegen_new/codegen_ops_logic.c +++ b/src/codegen_new/codegen_ops_logic.c @@ -12,796 +12,754 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_logic.h" -uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - return op_pc + 4; + codegen_flags_changed = 1; + return op_pc + 4; } -uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, dest_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, dest_reg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W); + } - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm_data = fastreadb(cs + op_pc); + uint8_t imm_data = fastreadb(cs + op_pc); - uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - uop_MOVZX(ir, IREG_flags_res, IREG_AL); + uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_AL); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm_data = fastreadw(cs + op_pc); + uint16_t imm_data = fastreadw(cs + op_pc); - uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - uop_MOVZX(ir, IREG_flags_res, IREG_AX); + uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_AX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); - uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0); - } - else - { - fetchdat = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); - } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc); + uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0); + } else { + fetchdat = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); + uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, IREG_EAX); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, IREG_EAX); - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; } -uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B); + } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + x86seg *target_seg; - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + } + + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg)); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); + } - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + uop_MOV(ir, IREG_flags_res, dest_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - return op_pc + 1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - uop_MOV(ir, IREG_flags_res, dest_reg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + } - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg)); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - } - - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - return op_pc + 1; + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_misc.c b/src/codegen_new/codegen_ops_misc.c index adb478d13..7f7613dbf 100644 --- a/src/codegen_new/codegen_ops_misc.c +++ b/src/codegen_new/codegen_ops_misc.c @@ -12,603 +12,591 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_misc.h" -uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W); - - return op_pc + 1; -} -uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - if ((fetchdat & 0xc0) == 0xc0) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr); - - return op_pc + 1; -} - -uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - uint8_t imm_data; - int reg; - - if (fetchdat & 0x20) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - reg = IREG_8(fetchdat & 7); - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - reg = IREG_temp0_B; - } - - switch (fetchdat & 0x38) - { - case 0x00: case 0x08: /*TEST*/ - imm_data = fastreadb(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc+2; - - case 0x10: /*NOT*/ - uop_XOR_IMM(ir, reg, reg, 0xff); - if ((fetchdat & 0xc0) != 0xc0) - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - - codegen_flags_changed = 1; - return op_pc+1; - - case 0x18: /*NEG*/ - uop_MOV_IMM(ir, IREG_temp1_B, 0); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op2, reg); - uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - uop_MOV(ir, reg, IREG_temp1_B); - } - else - { - uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); - uop_MOV_IMM(ir, IREG_flags_op1, 0); - - codegen_flags_changed = 1; - return op_pc+1; - } + if ((fetchdat & 0xc0) == 0xc0) return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W); + + return op_pc + 1; } -uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg = NULL; - uint16_t imm_data; - int reg; + int dest_reg = (fetchdat >> 3) & 7; - if (fetchdat & 0x20) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - reg = IREG_16(fetchdat & 7); - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - reg = IREG_temp0_W; - } - - switch (fetchdat & 0x38) - { - case 0x00: case 0x08: /*TEST*/ - imm_data = fastreadw(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data); - uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 2); - return op_pc+3; - - case 0x10: /*NOT*/ - uop_XOR_IMM(ir, reg, reg, 0xffff); - if ((fetchdat & 0xc0) != 0xc0) - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - - codegen_flags_changed = 1; - return op_pc+1; - - case 0x18: /*NEG*/ - uop_MOV_IMM(ir, IREG_temp1_W, 0); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op2, reg); - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - uop_MOV(ir, reg, IREG_temp1_W); - } - else - { - uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); - uop_MOV_IMM(ir, IREG_flags_op1, 0); - - codegen_flags_changed = 1; - return op_pc+1; - } + if ((fetchdat & 0xc0) == 0xc0) return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr); + + return op_pc + 1; } -uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg = NULL; - uint32_t imm_data; - int reg; + x86seg *target_seg = NULL; + uint8_t imm_data; + int reg; - if (fetchdat & 0x20) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - reg = IREG_32(fetchdat & 7); - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - reg = IREG_temp0; - } - - switch (fetchdat & 0x38) - { - case 0x00: case 0x08: /*TEST*/ - imm_data = fastreadl(cs + op_pc + 1); - - uop_AND_IMM(ir, IREG_flags_res, reg, imm_data); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); - - codegen_flags_changed = 1; - codegen_mark_code_present(block, cs+op_pc+1, 4); - return op_pc+5; - - case 0x10: /*NOT*/ - uop_XOR_IMM(ir, reg, reg, 0xffffffff); - if ((fetchdat & 0xc0) != 0xc0) - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - - codegen_flags_changed = 1; - return op_pc+1; - - case 0x18: /*NEG*/ - uop_MOV_IMM(ir, IREG_temp1, 0); - - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_flags_op2, reg); - uop_SUB(ir, IREG_temp1, IREG_temp1, reg); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - uop_MOV(ir, reg, IREG_temp1); - } - else - { - uop_SUB(ir, IREG_temp1, IREG_temp1, reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op2, IREG_temp0); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - } - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); - uop_MOV_IMM(ir, IREG_flags_op1, 0); - - codegen_flags_changed = 1; - return op_pc+1; - } + if (fetchdat & 0x20) return 0; -} -static void rebuild_c(ir_data_t *ir) -{ - int needs_rebuild = 1; - - if (codegen_flags_changed) - { - switch (cpu_state.flags_op) - { - case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32: - case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32: - needs_rebuild = 0; - break; - } - } - - if (needs_rebuild) - { - uop_CALL_FUNC(ir, flags_rebuild_c); - } -} - -uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg, sp_reg; - - if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if ((fetchdat & 0x38) == 0x28) - return 0; - src_reg = IREG_16(fetchdat & 7); - } + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_8(fetchdat & 7); + else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if (!(fetchdat & 0x30)) /*INC/DEC*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - src_reg = IREG_temp0_W; - } + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0_B; + } - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + switch (fetchdat & 0x38) { + case 0x00: + case 0x08: /*TEST*/ + imm_data = fastreadb(cs + op_pc + 1); - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_ADD_IMM(ir, src_reg, src_reg, 1); - uop_MOVZX(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); - } - else - { - uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); - } - return op_pc+1; + uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8); - case 0x08: /*DEC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_SUB_IMM(ir, src_reg, src_reg, 1); - uop_MOVZX(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); - } - else - { - uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, src_reg); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); - } - return op_pc+1; + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - case 0x10: /*CALL*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1); - SUB_SP(ir, 2); - uop_MOVZX(ir, IREG_pc, src_reg); - return -1; + codegen_flags_changed = 1; + return op_pc + 1; - case 0x20: /*JMP*/ - uop_MOVZX(ir, IREG_pc, src_reg); - return -1; + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1_B, 0); - case 0x28: /*JMP far*/ - uop_MOVZX(ir, IREG_pc, src_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); - uop_CALL_FUNC(ir, loadcsjmp); - return -1; + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + uop_MOV(ir, reg, IREG_temp1_B); + } else { + uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8); + uop_MOV_IMM(ir, IREG_flags_op1, 0); - case 0x30: /*PUSH*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); - SUB_SP(ir, 2); - return op_pc+1; - } - return 0; + codegen_flags_changed = 1; + return op_pc + 1; + } + return 0; } - -uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - x86seg *target_seg = NULL; - int src_reg, sp_reg; + x86seg *target_seg = NULL; + uint16_t imm_data; + int reg; - if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) - return 0; + if (fetchdat & 0x20) + return 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if ((fetchdat & 0x38) == 0x28) - return 0; - src_reg = IREG_32(fetchdat & 7); - } + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_16(fetchdat & 7); + else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - if (!(fetchdat & 0x30)) /*INC/DEC*/ - codegen_check_seg_write(block, ir, target_seg); - else - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - src_reg = IREG_temp0; - } + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0_W; + } - switch (fetchdat & 0x38) - { - case 0x00: /*INC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + switch (fetchdat & 0x38) { + case 0x00: + case 0x08: /*TEST*/ + imm_data = fastreadw(cs + op_pc + 1); - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_ADD_IMM(ir, src_reg, src_reg, 1); - uop_MOV(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); - } - else - { - uop_ADD_IMM(ir, IREG_temp1, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); - } - return op_pc+1; + uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data); + uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16); - case 0x08: /*DEC*/ - rebuild_c(ir); - codegen_flags_changed = 1; + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 2); + return op_pc + 3; - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_SUB_IMM(ir, src_reg, src_reg, 1); - uop_MOV(ir, IREG_flags_res, src_reg); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); - } - else - { - uop_SUB_IMM(ir, IREG_temp1, src_reg, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, src_reg); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, 1); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); - } - return op_pc+1; + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xffff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); - case 0x10: /*CALL*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1); - SUB_SP(ir, 4); - uop_MOV(ir, IREG_pc, src_reg); - return -1; + codegen_flags_changed = 1; + return op_pc + 1; - case 0x20: /*JMP*/ - uop_MOV(ir, IREG_pc, src_reg); - return -1; + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1_W, 0); - case 0x28: /*JMP far*/ - uop_MOV(ir, IREG_pc, src_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); - uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); - uop_CALL_FUNC(ir, loadcsjmp); - return -1; + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV(ir, reg, IREG_temp1_W); + } else { + uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16); + uop_MOV_IMM(ir, IREG_flags_op1, 0); - case 0x30: /*PUSH*/ - if ((fetchdat & 0xc0) == 0xc0) - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); - SUB_SP(ir, 4); - return op_pc+1; - } + codegen_flags_changed = 1; + return op_pc + 1; + } + return 0; +} +uint32_t +ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint32_t imm_data; + int reg; + + if (fetchdat & 0x20) return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) + reg = IREG_32(fetchdat & 7); + else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + reg = IREG_temp0; + } + + switch (fetchdat & 0x38) { + case 0x00: + case 0x08: /*TEST*/ + imm_data = fastreadl(cs + op_pc + 1); + + uop_AND_IMM(ir, IREG_flags_res, reg, imm_data); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32); + + codegen_flags_changed = 1; + codegen_mark_code_present(block, cs + op_pc + 1, 4); + return op_pc + 5; + + case 0x10: /*NOT*/ + uop_XOR_IMM(ir, reg, reg, 0xffffffff); + if ((fetchdat & 0xc0) != 0xc0) + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg); + + codegen_flags_changed = 1; + return op_pc + 1; + + case 0x18: /*NEG*/ + uop_MOV_IMM(ir, IREG_temp1, 0); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_flags_op2, reg); + uop_SUB(ir, IREG_temp1, IREG_temp1, reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV(ir, reg, IREG_temp1); + } else { + uop_SUB(ir, IREG_temp1, IREG_temp1, reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op2, IREG_temp0); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + } + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32); + uop_MOV_IMM(ir, IREG_flags_op1, 0); + + codegen_flags_changed = 1; + return op_pc + 1; + } + return 0; } -uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static void +rebuild_c(ir_data_t *ir) { - return op_pc; + int needs_rebuild = 1; + + if (codegen_flags_changed) { + switch (cpu_state.flags_op) { + case FLAGS_INC8: + case FLAGS_INC16: + case FLAGS_INC32: + case FLAGS_DEC8: + case FLAGS_DEC16: + case FLAGS_DEC32: + needs_rebuild = 0; + break; + } + } + + if (needs_rebuild) { + uop_CALL_FUNC(ir, flags_rebuild_c); + } } -uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOVSX(ir, IREG_AX, IREG_AL); + x86seg *target_seg = NULL; + int src_reg, sp_reg; - return op_pc; + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if ((fetchdat & 0x38) == 0x28) + return 0; + src_reg = IREG_16(fetchdat & 7); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if (!(fetchdat & 0x30)) /*INC/DEC*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0_W; + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_ADD_IMM(ir, src_reg, src_reg, 1); + uop_MOVZX(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + } else { + uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16); + } + return op_pc + 1; + + case 0x08: /*DEC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_SUB_IMM(ir, src_reg, src_reg, 1); + uop_MOVZX(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + } else { + uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, src_reg); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16); + } + return op_pc + 1; + + case 0x10: /*CALL*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1); + SUB_SP(ir, 2); + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; + + case 0x20: /*JMP*/ + uop_MOVZX(ir, IREG_pc, src_reg); + return -1; + + case 0x28: /*JMP far*/ + uop_MOVZX(ir, IREG_pc, src_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); + uop_CALL_FUNC(ir, loadcsjmp); + return -1; + + case 0x30: /*PUSH*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); + SUB_SP(ir, 2); + return op_pc + 1; + } + return 0; } -uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31); + x86seg *target_seg = NULL; + int src_reg, sp_reg; - return op_pc; + if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30) + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if ((fetchdat & 0x38) == 0x28) + return 0; + src_reg = IREG_32(fetchdat & 7); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + if (!(fetchdat & 0x30)) /*INC/DEC*/ + codegen_check_seg_write(block, ir, target_seg); + else + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0; + } + + switch (fetchdat & 0x38) { + case 0x00: /*INC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_ADD_IMM(ir, src_reg, src_reg, 1); + uop_MOV(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + } else { + uop_ADD_IMM(ir, IREG_temp1, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32); + } + return op_pc + 1; + + case 0x08: /*DEC*/ + rebuild_c(ir); + codegen_flags_changed = 1; + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_SUB_IMM(ir, src_reg, src_reg, 1); + uop_MOV(ir, IREG_flags_res, src_reg); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + } else { + uop_SUB_IMM(ir, IREG_temp1, src_reg, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, src_reg); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, 1); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32); + } + return op_pc + 1; + + case 0x10: /*CALL*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1); + SUB_SP(ir, 4); + uop_MOV(ir, IREG_pc, src_reg); + return -1; + + case 0x20: /*JMP*/ + uop_MOV(ir, IREG_pc, src_reg); + return -1; + + case 0x28: /*JMP far*/ + uop_MOV(ir, IREG_pc, src_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); + uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); + uop_CALL_FUNC(ir, loadcsjmp); + return -1; + + case 0x30: /*PUSH*/ + if ((fetchdat & 0xc0) == 0xc0) + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg); + SUB_SP(ir, 4); + return op_pc + 1; + } + return 0; } -uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15); - - return op_pc; + return op_pc; } -uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + +uint32_t +ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOVSX(ir, IREG_EAX, IREG_AX); + uop_MOVSX(ir, IREG_AX, IREG_AL); - return op_pc; + return op_pc; +} +uint32_t +ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31); + + return op_pc; +} +uint32_t +ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15); + + return op_pc; +} +uint32_t +ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOVSX(ir, IREG_EAX, IREG_AX); + + return op_pc; } -#define ropLxS(name, seg) \ -uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg = NULL; \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ - uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ - uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ - \ - if (seg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); \ - \ - return op_pc + 1; \ -} \ -uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - x86seg *target_seg = NULL; \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - if ((fetchdat & 0xc0) == 0xc0) \ - return 0; \ - \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ - uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ - uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ - \ - if (seg == &cpu_state.seg_ss) \ - CPU_BLOCK_END(); \ - \ - return op_pc + 1; \ -} +#define ropLxS(name, seg) \ + uint32_t rop##name##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ + } \ + uint32_t rop##name##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + x86seg *target_seg = NULL; \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + if ((fetchdat & 0xc0) == 0xc0) \ + return 0; \ + \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \ + uop_LOAD_SEG(ir, seg, IREG_temp1_W); \ + uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \ + \ + if (seg == &cpu_state.seg_ss) \ + CPU_BLOCK_END(); \ + \ + return op_pc + 1; \ + } ropLxS(LDS, &cpu_state.seg_ds) -ropLxS(LES, &cpu_state.seg_es) -ropLxS(LFS, &cpu_state.seg_fs) -ropLxS(LGS, &cpu_state.seg_gs) -ropLxS(LSS, &cpu_state.seg_ss) + ropLxS(LES, &cpu_state.seg_es) + ropLxS(LFS, &cpu_state.seg_fs) + ropLxS(LGS, &cpu_state.seg_gs) + ropLxS(LSS, &cpu_state.seg_ss) -uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) + uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_CALL_FUNC(ir, flags_rebuild); - uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG); - return op_pc; + uop_CALL_FUNC(ir, flags_rebuild); + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG); + return op_pc; } -uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_CALL_FUNC(ir, flags_rebuild); - uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); - return op_pc; + uop_CALL_FUNC(ir, flags_rebuild); + uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); + return op_pc; } -uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_CALL_FUNC(ir, flags_rebuild); - uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); - return op_pc; + uop_CALL_FUNC(ir, flags_rebuild); + uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG); + return op_pc; } -uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG); - return op_pc; + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG); + return op_pc; } -uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG); - return op_pc; + uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG); + return op_pc; } -uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; - uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG); - return op_pc; + uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG); + return op_pc; } -uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) - return 0; + if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI))) + return 0; - uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG); - return op_pc; + uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG); + return op_pc; } diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index 66124ca5e..67e73883e 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -13,31 +13,28 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" -#define ropParith(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ -} +#define ropParith(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ + } ropParith(PADDB) ropParith(PADDW) diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index 29a28e14f..6e5010446 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -13,31 +13,28 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" -#define ropPcmp(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ -} +#define ropPcmp(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ + } ropPcmp(PCMPEQB) ropPcmp(PCMPEQW) diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index ebdf81555..a20e18e68 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -13,104 +13,96 @@ #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_helpers.h" -uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - if (cpu_iscyrix && in_smm) - return 0; + if (cpu_iscyrix && in_smm) + return 0; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); - uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); + uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg)); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); + } - return op_pc + 1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index 24dc2b4c7..664bfd14c 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -13,99 +13,91 @@ #include "codegen_ops_mmx_logic.h" #include "codegen_ops_helpers.h" -uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } -uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + int dest_reg = (fetchdat >> 3) & 7; - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); - } - else - { - x86seg *target_seg; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); + } else { + x86seg *target_seg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); - uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); + uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); + } - return op_pc + 1; + return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index 87b562d17..700cb7fbf 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -13,31 +13,28 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" -#define ropPpack(func) \ -uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int dest_reg = (fetchdat >> 3) & 7; \ - \ - uop_MMX_ENTER(ir); \ - codegen_mark_code_present(block, cs+op_pc, 1); \ - if ((fetchdat & 0xc0) == 0xc0) \ - { \ - int src_reg = fetchdat & 7; \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ - } \ - else \ - { \ - x86seg *target_seg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ - codegen_check_seg_read(block, ir, target_seg); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ - uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ - } \ - \ - return op_pc + 1; \ -} +#define ropPpack(func) \ + uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int dest_reg = (fetchdat >> 3) & 7; \ + \ + uop_MMX_ENTER(ir); \ + codegen_mark_code_present(block, cs + op_pc, 1); \ + if ((fetchdat & 0xc0) == 0xc0) { \ + int src_reg = fetchdat & 7; \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \ + } else { \ + x86seg *target_seg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \ + codegen_check_seg_read(block, ir, target_seg); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \ + uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ + } \ + \ + return op_pc + 1; \ + } ropPpack(PACKSSWB) ropPpack(PACKSSDW) diff --git a/src/codegen_new/codegen_ops_mmx_shift.c b/src/codegen_new/codegen_ops_mmx_shift.c index bb5277ef3..32449d188 100644 --- a/src/codegen_new/codegen_ops_mmx_shift.c +++ b/src/codegen_new/codegen_ops_mmx_shift.c @@ -13,84 +13,81 @@ #include "codegen_ops_mmx_shift.h" #include "codegen_ops_helpers.h" -uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = fastreadb(cs + op_pc + 1); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - switch (op) - { - case 0x10: /*PSRLW*/ - uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x20: /*PSRAW*/ - uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x30: /*PSLLW*/ - uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - default: - return 0; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + switch (op) { + case 0x10: /*PSRLW*/ + uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAW*/ + uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLW*/ + uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + } - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = fastreadb(cs + op_pc + 1); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - switch (op) - { - case 0x10: /*PSRLD*/ - uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x20: /*PSRAD*/ - uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x30: /*PSLLD*/ - uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - default: - return 0; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + switch (op) { + case 0x10: /*PSRLD*/ + uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAD*/ + uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLD*/ + uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + } - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } -uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int reg = fetchdat & 7; - int op = fetchdat & 0x38; - int shift = fastreadb(cs + op_pc + 1); + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); - uop_MMX_ENTER(ir); - codegen_mark_code_present(block, cs+op_pc, 1); - switch (op) - { - case 0x10: /*PSRLQ*/ - uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x20: /*PSRAQ*/ - uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - case 0x30: /*PSLLQ*/ - uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); - break; - default: - return 0; + uop_MMX_ENTER(ir); + codegen_mark_code_present(block, cs + op_pc, 1); + switch (op) { + case 0x10: /*PSRLQ*/ + uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAQ*/ + uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLQ*/ + uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + } - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; } diff --git a/src/codegen_new/codegen_ops_mov.c b/src/codegen_new/codegen_ops_mov.c index eb748a027..68e8fb011 100644 --- a/src/codegen_new/codegen_ops_mov.c +++ b/src/codegen_new/codegen_ops_mov.c @@ -11,763 +11,718 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_mov.h" -uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint8_t imm = fastreadb(cs + op_pc); + uint8_t imm = fastreadb(cs + op_pc); - uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); + uop_MOV_IMM(ir, IREG_8(opcode & 7), imm); - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; } -uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint16_t imm = fastreadw(cs + op_pc); + uint16_t imm = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); + uop_MOV_IMM(ir, IREG_16(opcode & 7), imm); - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; } -uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc); - } - else - { - fetchdat = fastreadl(cs + op_pc); - uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); - codegen_mark_code_present(block, cs+op_pc, 4); - } - return op_pc + 4; + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc); + } else { + fetchdat = fastreadl(cs + op_pc); + uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat); + codegen_mark_code_present(block, cs + op_pc, 4); + } + return op_pc + 4; } - - -uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int src_reg = (fetchdat >> 3) & 7; + int src_reg = (fetchdat >> 3) & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); - } - - return op_pc + 1; -} -uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); - } - - return op_pc + 1; -} -uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); - } - - return op_pc + 1; -} -uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } - - return op_pc + 1; -} -uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } - - return op_pc + 1; -} -uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int dest_reg = (fetchdat >> 3) & 7; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); - } - - return op_pc + 1; -} - -uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_read(block, ir, op_ea_seg); - uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_read(block, ir, op_ea_seg); - uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr = 0; - - if (op_32 & 0x200) - { - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc); - } - else - { - addr = fastreadl(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 4); - } - } - else - { - addr = fastreadw(cs + op_pc); - codegen_mark_code_present(block, cs+op_pc, 2); - } - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_read(block, ir, op_ea_seg); - if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200)) - uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr); - else - uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); - - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_write(block, ir, op_ea_seg); - uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_write(block, ir, op_ea_seg); - uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} -uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t addr; - - if (op_32 & 0x200) - addr = fastreadl(cs + op_pc); - else - addr = fastreadw(cs + op_pc); - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - codegen_check_seg_write(block, ir, op_ea_seg); - uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX); - - codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2); - return op_pc + ((op_32 & 0x200) ? 4 : 2); -} - -uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } else { x86seg *target_seg; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - imm = fastreadb(cs + op_pc + 1); - uop_MOV_IMM(ir, IREG_8(dest_reg), imm); - } - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadb(cs + op_pc + 1); - uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); - } - - codegen_mark_code_present(block, cs+op_pc+1, 1); - return op_pc + 2; -} -uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg; - uint16_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - imm = fastreadw(cs + op_pc + 1); - uop_MOV_IMM(ir, IREG_16(dest_reg), imm); - } - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadw(cs + op_pc + 1); - uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); - } - - codegen_mark_code_present(block, cs+op_pc+1, 2); - return op_pc + 3; -} -uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg; - uint32_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - imm = fastreadl(cs + op_pc + 1); - uop_MOV_IMM(ir, IREG_32(dest_reg), imm); - } - else - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - imm = fastreadl(cs + op_pc + 1); - uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); - } - - codegen_mark_code_present(block, cs+op_pc+1, 4); - return op_pc + 5; -} - -uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg; - - codegen_mark_code_present(block, cs+op_pc, 1); - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - src_reg = IREG_ES_seg_W; - break; - case 0x08: /*CS*/ - src_reg = IREG_CS_seg_W; - break; - case 0x18: /*DS*/ - src_reg = IREG_DS_seg_W; - break; - case 0x10: /*SS*/ - src_reg = IREG_SS_seg_W; - break; - case 0x20: /*FS*/ - src_reg = IREG_FS_seg_W; - break; - case 0x28: /*GS*/ - src_reg = IREG_GS_seg_W; - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOV(ir, IREG_16(dest_reg), src_reg); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); - } - - return op_pc + 1; -} -uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg; - - codegen_mark_code_present(block, cs+op_pc, 1); - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - src_reg = IREG_ES_seg_W; - break; - case 0x08: /*CS*/ - src_reg = IREG_CS_seg_W; - break; - case 0x18: /*DS*/ - src_reg = IREG_DS_seg_W; - break; - case 0x10: /*SS*/ - src_reg = IREG_SS_seg_W; - break; - case 0x20: /*FS*/ - src_reg = IREG_FS_seg_W; - break; - case 0x28: /*GS*/ - src_reg = IREG_GS_seg_W; - break; - default: - return 0; - } - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), src_reg); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); - } - - return op_pc + 1; -} - -uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int src_reg; - x86seg *rseg; - - codegen_mark_code_present(block, cs+op_pc, 1); - switch (fetchdat & 0x38) - { - case 0x00: /*ES*/ - rseg = &cpu_state.seg_es; - break; - case 0x18: /*DS*/ - rseg = &cpu_state.seg_ds; - break; - case 0x20: /*FS*/ - rseg = &cpu_state.seg_fs; - break; - case 0x28: /*GS*/ - rseg = &cpu_state.seg_gs; - break; - default: - return 0; - } uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg)); + } - if ((fetchdat & 0xc0) == 0xc0) - { - uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7)); - src_reg = IREG_temp0_W; - } - else - { - x86seg *target_seg; + return op_pc + 1; +} +uint32_t +ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - src_reg = IREG_temp0_W; - } + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; - uop_LOAD_SEG(ir, rseg, src_reg); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg)); + } - return op_pc + 1; + return op_pc + 1; +} +uint32_t +ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg)); + } + + return op_pc + 1; +} +uint32_t +ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; +} +uint32_t +ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; +} +uint32_t +ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); + } + + return op_pc + 1; } -uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr = 0; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + if (op_32 & 0x200) { + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc); + } else { + addr = fastreadl(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 4); } - else - { - x86seg *target_seg; + } else { + addr = fastreadw(cs + op_pc); + codegen_mark_code_present(block, cs + op_pc, 2); + } - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_read(block, ir, op_ea_seg); + if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200)) + uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr); + else + uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr); - return op_pc + 1; + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } -uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int dest_reg = (fetchdat >> 3) & 7; + uint32_t addr; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int src_reg = fetchdat & 7; - uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg)); - } - else - { - x86seg *target_seg; + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_read(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W); - } + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + codegen_check_seg_write(block, ir, op_ea_seg); + uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX); - return op_pc + 1; + codegen_mark_code_present(block, cs + op_pc, (op_32 & 0x200) ? 4 : 2); + return op_pc + ((op_32 & 0x200) ? 4 : 2); } - -uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int reg2 = IREG_16(opcode & 7); + x86seg *target_seg; + uint8_t imm; - uop_MOV(ir, IREG_temp0_W, IREG_AX); - uop_MOV(ir, IREG_AX, reg2); + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + imm = fastreadb(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_8(dest_reg), imm); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadb(cs + op_pc + 1); + uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + codegen_mark_code_present(block, cs + op_pc + 1, 1); + return op_pc + 2; +} +uint32_t +ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint16_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + imm = fastreadw(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_16(dest_reg), imm); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadw(cs + op_pc + 1); + uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + codegen_mark_code_present(block, cs + op_pc + 1, 2); + return op_pc + 3; +} +uint32_t +ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg; + uint32_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + imm = fastreadl(cs + op_pc + 1); + uop_MOV_IMM(ir, IREG_32(dest_reg), imm); + } else { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + imm = fastreadl(cs + op_pc + 1); + uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm); + } + + codegen_mark_code_present(block, cs + op_pc + 1, 4); + return op_pc + 5; +} + +uint32_t +ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + + codegen_mark_code_present(block, cs + op_pc, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + src_reg = IREG_ES_seg_W; + break; + case 0x08: /*CS*/ + src_reg = IREG_CS_seg_W; + break; + case 0x18: /*DS*/ + src_reg = IREG_DS_seg_W; + break; + case 0x10: /*SS*/ + src_reg = IREG_SS_seg_W; + break; + case 0x20: /*FS*/ + src_reg = IREG_FS_seg_W; + break; + case 0x28: /*GS*/ + src_reg = IREG_GS_seg_W; + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOV(ir, IREG_16(dest_reg), src_reg); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); + } + + return op_pc + 1; +} +uint32_t +ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + + codegen_mark_code_present(block, cs + op_pc, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + src_reg = IREG_ES_seg_W; + break; + case 0x08: /*CS*/ + src_reg = IREG_CS_seg_W; + break; + case 0x18: /*DS*/ + src_reg = IREG_DS_seg_W; + break; + case 0x10: /*SS*/ + src_reg = IREG_SS_seg_W; + break; + case 0x20: /*FS*/ + src_reg = IREG_FS_seg_W; + break; + case 0x28: /*GS*/ + src_reg = IREG_GS_seg_W; + break; + default: + return 0; + } + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), src_reg); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg); + } + + return op_pc + 1; +} + +uint32_t +ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int src_reg; + x86seg *rseg; + + codegen_mark_code_present(block, cs + op_pc, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ES*/ + rseg = &cpu_state.seg_es; + break; + case 0x18: /*DS*/ + rseg = &cpu_state.seg_ds; + break; + case 0x20: /*FS*/ + rseg = &cpu_state.seg_fs; + break; + case 0x28: /*GS*/ + rseg = &cpu_state.seg_gs; + break; + default: + return 0; + } + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if ((fetchdat & 0xc0) == 0xc0) { + uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7)); + src_reg = IREG_temp0_W; + } else { + x86seg *target_seg; + + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + src_reg = IREG_temp0_W; + } + + uop_LOAD_SEG(ir, rseg, src_reg); + + return op_pc + 1; +} + +uint32_t +ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W); + } + + return op_pc + 1; +} + +uint32_t +ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int dest_reg = (fetchdat >> 3) & 7; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int src_reg = fetchdat & 7; + uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg)); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_read(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W); + } + + return op_pc + 1; +} + +uint32_t +ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg2 = IREG_16(opcode & 7); + + uop_MOV(ir, IREG_temp0_W, IREG_AX); + uop_MOV(ir, IREG_AX, reg2); + uop_MOV(ir, reg2, IREG_temp0_W); + + return op_pc; +} +uint32_t +ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg2 = IREG_32(opcode & 7); + + uop_MOV(ir, IREG_temp0, IREG_EAX); + uop_MOV(ir, IREG_EAX, reg2); + uop_MOV(ir, reg2, IREG_temp0); + + return op_pc; +} + +uint32_t +ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_8((fetchdat >> 3) & 7); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int reg2 = IREG_8(fetchdat & 7); + + uop_MOV(ir, IREG_temp0_B, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0_B); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0_B); + } + + return op_pc + 1; +} +uint32_t +ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_16((fetchdat >> 3) & 7); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int reg2 = IREG_16(fetchdat & 7); + + uop_MOV(ir, IREG_temp0_W, reg1); + uop_MOV(ir, reg1, reg2); uop_MOV(ir, reg2, IREG_temp0_W); + } else { + x86seg *target_seg; - return op_pc; -} -uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg2 = IREG_32(opcode & 7); - - uop_MOV(ir, IREG_temp0, IREG_EAX); - uop_MOV(ir, IREG_EAX, reg2); - uop_MOV(ir, reg2, IREG_temp0); - - return op_pc; -} - -uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg1 = IREG_8((fetchdat >> 3) & 7); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int reg2 = IREG_8(fetchdat & 7); - - uop_MOV(ir, IREG_temp0_B, reg1); - uop_MOV(ir, reg1, reg2); - uop_MOV(ir, reg2, IREG_temp0_B); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); - uop_MOV(ir, reg1, IREG_temp0_B); - } - - return op_pc + 1; -} -uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg1 = IREG_16((fetchdat >> 3) & 7); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int reg2 = IREG_16(fetchdat & 7); - - uop_MOV(ir, IREG_temp0_W, reg1); - uop_MOV(ir, reg1, reg2); - uop_MOV(ir, reg2, IREG_temp0_W); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); - uop_MOV(ir, reg1, IREG_temp0_W); - } - - return op_pc + 1; -} -uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - int reg1 = IREG_32((fetchdat >> 3) & 7); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int reg2 = IREG_32(fetchdat & 7); - - uop_MOV(ir, IREG_temp0, reg1); - uop_MOV(ir, reg1, reg2); - uop_MOV(ir, reg2, IREG_temp0); - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); - uop_MOV(ir, reg1, IREG_temp0); - } - - return op_pc + 1; -} - -uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); - uop_MOVZX(ir, IREG_eaaddr, IREG_AL); - uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX); - if (!(op_32 & 0x200)) - uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0_W); + } - uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr); - - return op_pc; + return op_pc + 1; +} +uint32_t +ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg1 = IREG_32((fetchdat >> 3) & 7); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int reg2 = IREG_32(fetchdat & 7); + + uop_MOV(ir, IREG_temp0, reg1); + uop_MOV(ir, reg1, reg2); + uop_MOV(ir, reg2, IREG_temp0); + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1); + uop_MOV(ir, reg1, IREG_temp0); + } + + return op_pc + 1; +} + +uint32_t +ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + uop_MOVZX(ir, IREG_eaaddr, IREG_AL); + uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX); + if (!(op_32 & 0x200)) + uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff); + + uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr); + + return op_pc; } diff --git a/src/codegen_new/codegen_ops_shift.c b/src/codegen_new/codegen_ops_shift.c index 370585bf2..8ccf7d9e7 100644 --- a/src/codegen_new/codegen_ops_shift.c +++ b/src/codegen_new/codegen_ops_shift.c @@ -13,1126 +13,1097 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_shift.h" -static uint32_t shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) +static uint32_t +shift_common_8(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) { - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x20: + case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHL_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SAR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SAR_IMM(ir, IREG_8(dest_reg), IREG_8(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x28: /*SHR*/ - uop_SHR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x38: /*SAR*/ - uop_SAR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -static uint32_t shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SAR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x28: /*SHR*/ - uop_SHR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x38: /*SAR*/ - uop_SAR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} -static uint32_t shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SAR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL_IMM(ir, IREG_temp0, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR_IMM(ir, IREG_temp0, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x28: /*SHR*/ - uop_SHR_IMM(ir, IREG_temp1, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x38: /*SAR*/ - uop_SAR_IMM(ir, IREG_temp1, IREG_temp0, count); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, count); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -static uint32_t shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count_reg) -{ - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - default: - return 0; - } - } - else - { - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1, IREG_temp0, count_reg); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, count_reg); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - uint8_t imm; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + default: return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; - if (imm) - return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1; - return op_pc+1; -} -uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - uint8_t imm; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + case 0x20: + case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1_B, IREG_temp0_B, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + default: return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); + } - if (imm) - return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1; - return op_pc+1; -} -uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - } - if (block->flags & CODEBLOCK_NO_IMMEDIATES) - { - uint32_t new_pc; - int jump_uop; - - LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1); - uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f); - jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp2, 0); - - new_pc = shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; - uop_NOP_BARRIER(ir); - uop_set_jump_dest(ir, jump_uop); - return new_pc; - } - else - { - uint8_t imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (imm) - return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; - } - return op_pc+1; + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static uint32_t +shift_common_16(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) { - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - } - - return shift_common_8(ir, fetchdat, op_pc, target_seg, 1); -} -uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - } - - return shift_common_16(ir, fetchdat, op_pc, target_seg, 1); -} -uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - } - - return shift_common_32(ir, fetchdat, op_pc, target_seg, 1); -} - -uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - if (!(CL & 0x1f) || !block->ins) - return 0; - - uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SHR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); - uop_SAR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - if (!(CL & 0x1f) || !block->ins) - return 0; - - uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SAR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); - uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); - uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} -uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ - return 0; - - if (!(CL & 0x1f) || !block->ins) - return 0; - - uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); - uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x28: /*SHR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - case 0x38: /*SAR*/ - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - break; - - default: - return 0; - } - } - else - { - x86seg *target_seg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); - - switch (fetchdat & 0x38) - { - case 0x00: /*ROL*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROL(ir, IREG_temp0, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x08: /*ROR*/ - uop_CALL_FUNC(ir, flags_rebuild); - uop_ROR(ir, IREG_temp0, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - break; - - case 0x20: case 0x30: /*SHL*/ - uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x28: /*SHR*/ - uop_SHR(ir, IREG_temp1, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - case 0x38: /*SAR*/ - uop_SAR(ir, IREG_temp1, IREG_temp0, IREG_temp2); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); - uop_MOV(ir, IREG_flags_op1, IREG_temp0); - uop_MOV(ir, IREG_flags_op2, IREG_temp2); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); - uop_MOV(ir, IREG_flags_res, IREG_temp1); - break; - - default: - return 0; - } - } - - codegen_flags_changed = 1; - return op_pc + 1; -} - -uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHL_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); - uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SHL_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); - - uop_SHL_IMM(ir, IREG_temp0_W, IREG_temp2, imm); - uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - - uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); - uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); - } - - return op_pc+2; -} -uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; - - uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHL_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); - uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); - - uop_SHL_IMM(ir, IREG_temp0, IREG_temp2, imm); - uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - - uop_MOV(ir, IREG_flags_op1, IREG_temp2); - uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); - } - - return op_pc+2; -} -uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); - - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + break; + case 0x28: /*SHR*/ uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); - uop_SHR_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); - uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SHR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + break; - uop_SHR_IMM(ir, IREG_temp0_W, IREG_temp2, imm); - uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); - uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SAR_IMM(ir, IREG_16(dest_reg), IREG_16(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + default: + return 0; + } + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); - - uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); - } + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; - return op_pc+2; + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1_W, IREG_temp0_W, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; } -uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +static uint32_t +shift_common_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count) { - x86seg *target_seg = NULL; - int src_reg = (fetchdat >> 3) & 7; - uint8_t imm; + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) != 0xc0) - { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); - } - imm = fastreadb(cs + op_pc + 1) & 0x1f; - codegen_mark_code_present(block, cs+op_pc+1, 1); + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; - if (!imm) - return op_pc+2; - - if ((fetchdat & 0xc0) == 0xc0) - { - int dest_reg = fetchdat & 7; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + case 0x20: + case 0x30: /*SHL*/ uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); - uop_SHR_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); - uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); - uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_SHL_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); - } - else - { - codegen_check_seg_write(block, ir, target_seg); - uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + break; - uop_SHR_IMM(ir, IREG_temp0, IREG_temp2, imm); - uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); - uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR_IMM(ir, IREG_32(dest_reg), IREG_32(dest_reg), count); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL_IMM(ir, IREG_temp0, IREG_temp0, count); uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - - uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); uop_MOV(ir, IREG_flags_res, IREG_temp0); - uop_MOV_IMM(ir, IREG_flags_op2, imm); - uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); - } + break; - return op_pc+2; + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR_IMM(ir, IREG_temp0, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR_IMM(ir, IREG_temp1, IREG_temp0, count); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, count); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +static uint32_t +shift_common_variable_32(ir_data_t *ir, uint32_t fetchdat, uint32_t op_pc, x86seg *target_seg, int count_reg) +{ + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), count_reg); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } else { + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1, IREG_temp0, count_reg); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, count_reg); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (imm) + return shift_common_8(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc + 1; +} +uint32_t +ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + uint8_t imm; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (imm) + return shift_common_16(ir, fetchdat, op_pc, target_seg, imm) + 1; + return op_pc + 1; +} +uint32_t +ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + } + if (block->flags & CODEBLOCK_NO_IMMEDIATES) { + uint32_t new_pc; + int jump_uop; + + LOAD_IMMEDIATE_FROM_RAM_8(block, ir, IREG_temp2, cs + op_pc + 1); + uop_AND_IMM(ir, IREG_temp2, IREG_temp2, 0x1f); + jump_uop = uop_CMP_IMM_JZ_DEST(ir, IREG_temp2, 0); + + new_pc = shift_common_variable_32(ir, fetchdat, op_pc, target_seg, IREG_temp2) + 1; + uop_NOP_BARRIER(ir); + uop_set_jump_dest(ir, jump_uop); + return new_pc; + } else { + uint8_t imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (imm) + return shift_common_32(ir, fetchdat, op_pc, target_seg, imm) + 1; + } + return op_pc + 1; +} + +uint32_t +ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_8(ir, fetchdat, op_pc, target_seg, 1); +} +uint32_t +ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_16(ir, fetchdat, op_pc, target_seg, 1); +} +uint32_t +ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + } + + return shift_common_32(ir, fetchdat, op_pc, target_seg, 1); +} + +uint32_t +ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHL(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SHR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_8(dest_reg)); + uop_SAR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg)); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1_B, IREG_temp0_B, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_B); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR8); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SAR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1_W, IREG_temp0_W, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W); + uop_MOVZX(ir, IREG_flags_op1, IREG_temp0_W); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR16); + uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} +uint32_t +ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + if ((fetchdat & 0x30) == 0x10) /*RCL/RCR*/ + return 0; + + if (!(CL & 0x1f) || !block->ins) + return 0; + + uop_AND_IMM(ir, IREG_temp2, REG_ECX, 0x1f); + uop_CMP_IMM_JZ(ir, IREG_temp2, 0, codegen_exit_rout); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x28: /*SHR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + case 0x38: /*SAR*/ + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SAR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp2); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + break; + + default: + return 0; + } + } else { + x86seg *target_seg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); + + switch (fetchdat & 0x38) { + case 0x00: /*ROL*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROL(ir, IREG_temp0, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROL32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x08: /*ROR*/ + uop_CALL_FUNC(ir, flags_rebuild); + uop_ROR(ir, IREG_temp0, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ROR32); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + break; + + case 0x20: + case 0x30: /*SHL*/ + uop_SHL(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x28: /*SHR*/ + uop_SHR(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + case 0x38: /*SAR*/ + uop_SAR(ir, IREG_temp1, IREG_temp0, IREG_temp2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1); + uop_MOV(ir, IREG_flags_op1, IREG_temp0); + uop_MOV(ir, IREG_flags_op2, IREG_temp2); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SAR32); + uop_MOV(ir, IREG_flags_res, IREG_temp1); + break; + + default: + return 0; + } + } + + codegen_flags_changed = 1; + return op_pc + 1; +} + +uint32_t +ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHL_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); + uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHL_IMM(ir, IREG_temp0_W, IREG_temp2, imm); + uop_SHR_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + + uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL16); + } + + return op_pc + 2; +} +uint32_t +ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHL_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); + uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHL_IMM(ir, IREG_temp0, IREG_temp2, imm); + uop_SHR_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + + uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHL32); + } + + return op_pc + 2; +} +uint32_t +ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOVZX(ir, IREG_flags_op1, IREG_16(dest_reg)); + uop_SHR_IMM(ir, IREG_temp0_W, IREG_16(dest_reg), imm); + uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_16(dest_reg), IREG_temp0_W, IREG_temp1_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2_W, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHR_IMM(ir, IREG_temp0_W, IREG_temp2, imm); + uop_SHL_IMM(ir, IREG_temp1_W, IREG_16(src_reg), 16 - imm); + uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_temp1_W); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + + uop_MOVZX(ir, IREG_flags_op1, IREG_temp2_W); + uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR16); + } + + return op_pc + 2; +} +uint32_t +ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + x86seg *target_seg = NULL; + int src_reg = (fetchdat >> 3) & 7; + uint8_t imm; + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) != 0xc0) { + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); + } + imm = fastreadb(cs + op_pc + 1) & 0x1f; + codegen_mark_code_present(block, cs + op_pc + 1, 1); + + if (!imm) + return op_pc + 2; + + if ((fetchdat & 0xc0) == 0xc0) { + int dest_reg = fetchdat & 7; + + uop_MOV(ir, IREG_flags_op1, IREG_32(dest_reg)); + uop_SHR_IMM(ir, IREG_temp0, IREG_32(dest_reg), imm); + uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_32(dest_reg), IREG_temp0, IREG_temp1); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg)); + } else { + codegen_check_seg_write(block, ir, target_seg); + uop_MEM_LOAD_REG(ir, IREG_temp2, ireg_seg_base(target_seg), IREG_eaaddr); + + uop_SHR_IMM(ir, IREG_temp0, IREG_temp2, imm); + uop_SHL_IMM(ir, IREG_temp1, IREG_32(src_reg), 32 - imm); + uop_OR(ir, IREG_temp0, IREG_temp0, IREG_temp1); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + + uop_MOV(ir, IREG_flags_op1, IREG_temp2); + uop_MOV(ir, IREG_flags_res, IREG_temp0); + uop_MOV_IMM(ir, IREG_flags_op2, imm); + uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SHR32); + } + + return op_pc + 2; } diff --git a/src/codegen_new/codegen_ops_stack.c b/src/codegen_new/codegen_ops_stack.c index ff421488e..b7afdce25 100644 --- a/src/codegen_new/codegen_ops_stack.c +++ b/src/codegen_new/codegen_ops_stack.c @@ -12,248 +12,243 @@ #include "codegen_ops_helpers.h" #include "codegen_ops_misc.h" -uint32_t ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7)); - SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7)); + SUB_SP(ir, 2); - return op_pc; + return op_pc; } -uint32_t ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7)); - SUB_SP(ir, 4); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7)); + SUB_SP(ir, 4); - return op_pc; + return op_pc; } -uint32_t ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr); + } + if ((opcode & 7) != REG_SP) + ADD_SP(ir, 2); + + return op_pc; +} +uint32_t +ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr); + } + if ((opcode & 7) != REG_ESP) + ADD_SP(ir, 4); + + return op_pc; +} + +uint32_t +ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm = fastreadw(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 2); + + codegen_mark_code_present(block, cs + op_pc, 2); + return op_pc + 2; +} +uint32_t +ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t imm = fastreadl(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 4); + + codegen_mark_code_present(block, cs + op_pc, 4); + return op_pc + 4; +} + +uint32_t +ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint16_t imm = (int16_t) (int8_t) fastreadb(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 2); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} +uint32_t +ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uint32_t imm = (int32_t) (int8_t) fastreadb(cs + op_pc); + int sp_reg; + + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); + SUB_SP(ir, 4); + + codegen_mark_code_present(block, cs + op_pc, 1); + return op_pc + 1; +} + +uint32_t +ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr); + } + } else { + x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2); + codegen_check_seg_write(block, ir, target_seg); if (stack32) - uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_temp0, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0); } - if ((opcode & 7) != REG_SP) - ADD_SP(ir, 2); - return op_pc; + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + } + + if ((fetchdat & 0xc7) != (0xc0 | REG_SP)) + ADD_SP(ir, 2); + + return op_pc + 1; } -uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + + codegen_mark_code_present(block, cs + op_pc, 1); + if ((fetchdat & 0xc0) == 0xc0) { + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr); + } + } else { + x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4); + codegen_check_seg_write(block, ir, target_seg); if (stack32) - uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr); - } - if ((opcode & 7) != REG_ESP) - ADD_SP(ir, 4); - - return op_pc; -} - -uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm = fastreadw(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 2); - - codegen_mark_code_present(block, cs+op_pc, 2); - return op_pc + 2; -} -uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t imm = fastreadl(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 4); - - codegen_mark_code_present(block, cs+op_pc, 4); - return op_pc + 4; -} - -uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 2); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} -uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc); - int sp_reg; - - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm); - SUB_SP(ir, 4); - - codegen_mark_code_present(block, cs+op_pc, 1); - return op_pc + 1; -} - -uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr); - } - } - else - { - x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2); - codegen_check_seg_write(block, ir, target_seg); - - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_temp0, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0); - } - - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); + else { + uop_MOVZX(ir, IREG_temp0, IREG_SP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0); } - if ((fetchdat & 0xc7) != (0xc0 | REG_SP)) - ADD_SP(ir, 2); + uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); + } - return op_pc + 1; -} -uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) -{ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + if ((fetchdat & 0xc7) != (0xc0 | REG_ESP)) + ADD_SP(ir, 4); - codegen_mark_code_present(block, cs+op_pc, 1); - if ((fetchdat & 0xc0) == 0xc0) - { - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr); - } - } - else - { - x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4); - codegen_check_seg_write(block, ir, target_seg); - - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP); - else - { - uop_MOVZX(ir, IREG_temp0, IREG_SP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0); - } - - uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); - } - - if ((fetchdat & 0xc7) != (0xc0 | REG_ESP)) - ADD_SP(ir, 4); - - return op_pc + 1; + return op_pc + 1; } -#define ROP_PUSH_SEG(seg) \ -uint32_t ropPUSH_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int sp_reg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_ ## seg ## _seg_W); \ - SUB_SP(ir, 2); \ - \ - return op_pc; \ -} \ -uint32_t ropPUSH_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - int sp_reg; \ - \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ - uop_MOVZX(ir, IREG_temp0, IREG_ ## seg ## _seg_W); \ - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ - SUB_SP(ir, 4); \ - \ - return op_pc; \ -} - -#define ROP_POP_SEG(seg, rseg) \ -uint32_t ropPOP_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - \ - if (stack32) \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ - else \ - { \ - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ - } \ - uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ - ADD_SP(ir, 2); \ - \ - return op_pc; \ -} \ -uint32_t ropPOP_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ -{ \ - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ - \ - if (stack32) \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ - else \ - { \ - uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ - } \ - uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ - ADD_SP(ir, 4); \ - \ - return op_pc; \ -} +#define ROP_PUSH_SEG(seg) \ + uint32_t ropPUSH_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_##seg##_seg_W); \ + SUB_SP(ir, 2); \ + \ + return op_pc; \ + } \ + uint32_t ropPUSH_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + int sp_reg; \ + \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \ + uop_MOVZX(ir, IREG_temp0, IREG_##seg##_seg_W); \ + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \ + SUB_SP(ir, 4); \ + \ + return op_pc; \ + } +#define ROP_POP_SEG(seg, rseg) \ + uint32_t ropPOP_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 2); \ + \ + return op_pc; \ + } \ + uint32_t ropPOP_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ + { \ + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \ + \ + if (stack32) \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \ + else { \ + uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \ + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \ + } \ + uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \ + ADD_SP(ir, 4); \ + \ + return op_pc; \ + } ROP_PUSH_SEG(CS) ROP_PUSH_SEG(DS) @@ -266,147 +261,152 @@ ROP_POP_SEG(ES, cpu_state.seg_es) ROP_POP_SEG(FS, cpu_state.seg_fs) ROP_POP_SEG(GS, cpu_state.seg_gs) -uint32_t ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_BP); - uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); - } - uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2); - uop_MOV(ir, IREG_BP, IREG_temp0_W); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_BP); + uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); + } + uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2); + uop_MOV(ir, IREG_BP, IREG_temp0_W); - return op_pc; + return op_pc; } -uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - if (stack32) - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP); - else - { - uop_MOVZX(ir, IREG_eaaddr, IREG_BP); - uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); - } - uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4); - uop_MOV(ir, IREG_EBP, IREG_temp0); + if (stack32) + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP); + else { + uop_MOVZX(ir, IREG_eaaddr, IREG_BP); + uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr); + } + uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4); + uop_MOV(ir, IREG_EBP, IREG_temp0); - return op_pc; + return op_pc; } - -uint32_t ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -16); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI); - SUB_SP(ir, 16); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -16); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI); + SUB_SP(ir, 16); - return op_pc; + return op_pc; } -uint32_t ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -32); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI); - SUB_SP(ir, 32); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -32); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI); + SUB_SP(ir, 32); - return op_pc; + return op_pc; } -uint32_t ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP(ir); - uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14); - ADD_SP(ir, 16); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP(ir); + uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14); + ADD_SP(ir, 16); - return op_pc; + return op_pc; } -uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - sp_reg = LOAD_SP(ir); - uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24); - uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28); - ADD_SP(ir, 32); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + sp_reg = LOAD_SP(ir); + uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24); + uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28); + ADD_SP(ir, 32); - return op_pc; + return op_pc; } -uint32_t ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - return 0; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + return 0; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_CALL_FUNC(ir, flags_rebuild); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); - SUB_SP(ir, 2); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_CALL_FUNC(ir, flags_rebuild); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); + SUB_SP(ir, 2); - return op_pc; + return op_pc; } -uint32_t ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +uint32_t +ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - int sp_reg; + int sp_reg; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - return 0; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) + return 0; - uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); - uop_CALL_FUNC(ir, flags_rebuild); + uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); + uop_CALL_FUNC(ir, flags_rebuild); - if (cpu_CR4_mask & CR4_VME) - uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); - else if (CPUID) - uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24); - else - uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4); - sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); - uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); - uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W); - SUB_SP(ir, 4); + if (cpu_CR4_mask & CR4_VME) + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c); + else if (CPUID) + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24); + else + uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4); + sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); + uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags); + uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W); + SUB_SP(ir, 4); - return op_pc; + return op_pc; } diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index a62121af7..7cd7b418a 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -8,916 +8,879 @@ #include "codegen_ir_defs.h" #include "codegen_reg.h" -int max_version_refcount; +int max_version_refcount; uint16_t reg_dead_list = 0; -uint8_t reg_last_version[IREG_COUNT]; +uint8_t reg_last_version[IREG_COUNT]; reg_version_t reg_version[IREG_COUNT][256]; -ir_reg_t invalid_ir_reg = {IREG_INVALID}; +ir_reg_t invalid_ir_reg = { IREG_INVALID }; -ir_reg_t _host_regs[CODEGEN_HOST_REGS]; +ir_reg_t _host_regs[CODEGEN_HOST_REGS]; static uint8_t _host_reg_dirty[CODEGEN_HOST_REGS]; -ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS]; +ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS]; static uint8_t host_fp_reg_dirty[CODEGEN_HOST_FP_REGS]; -typedef struct host_reg_set_t -{ - ir_reg_t *regs; - uint8_t *dirty; - host_reg_def_t *reg_list; - uint16_t locked; - int nr_regs; +typedef struct host_reg_set_t { + ir_reg_t *regs; + uint8_t *dirty; + host_reg_def_t *reg_list; + uint16_t locked; + int nr_regs; } host_reg_set_t; static host_reg_set_t host_reg_set, host_fp_reg_set; -enum -{ - REG_BYTE, - REG_WORD, - REG_DWORD, - REG_QWORD, - REG_POINTER, - REG_DOUBLE, - REG_FPU_ST_BYTE, - REG_FPU_ST_DOUBLE, - REG_FPU_ST_QWORD +enum { + REG_BYTE, + REG_WORD, + REG_DWORD, + REG_QWORD, + REG_POINTER, + REG_DOUBLE, + REG_FPU_ST_BYTE, + REG_FPU_ST_DOUBLE, + REG_FPU_ST_QWORD }; -enum -{ - REG_INTEGER, - REG_FP +enum { + REG_INTEGER, + REG_FP }; -enum -{ - /*Register may be accessed outside of code block, and must be written - back before any control transfers*/ - REG_PERMANENT = 0, - /*Register will not be accessed outside of code block, and does not need - to be written back if there are no readers remaining*/ - REG_VOLATILE = 1 +enum { + /*Register may be accessed outside of code block, and must be written + back before any control transfers*/ + REG_PERMANENT = 0, + /*Register will not be accessed outside of code block, and does not need + to be written back if there are no readers remaining*/ + REG_VOLATILE = 1 }; struct { - int native_size; - void *p; - int type; - int is_volatile; -} ireg_data[IREG_COUNT] = -{ - [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT}, - [IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT}, - [IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT}, - [IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT}, - [IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT}, - [IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT}, - [IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT}, - [IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT}, + int native_size; + void *p; + int type; + int is_volatile; +} ireg_data[IREG_COUNT] = { + [IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT}, + [IREG_ECX] = { REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT}, + [IREG_EDX] = { REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT}, + [IREG_EBX] = { REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT}, + [IREG_ESP] = { REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT}, + [IREG_EBP] = { REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT}, + [IREG_ESI] = { REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT}, + [IREG_EDI] = { REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT}, - [IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op] = { REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_res] = { REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op1] = { REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT}, + [IREG_flags_op2] = { REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT}, - [IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT}, - [IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT}, + [IREG_pc] = { REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT}, + [IREG_oldpc] = { REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT}, - [IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, - [IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT}, + [IREG_eaaddr] = { REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT}, + [IREG_ea_seg] = { REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT}, - [IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT}, - [IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT}, + [IREG_op32] = { REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT}, + [IREG_ssegsx] = { REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT}, - [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT}, + [IREG_rm_mod_reg] = { REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT}, #ifdef USE_ACYCS - [IREG_acycs] = {REG_DWORD, &acycs, REG_INTEGER, REG_PERMANENT}, + [IREG_acycs] = { REG_DWORD, &acycs, REG_INTEGER, REG_PERMANENT}, #endif - [IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT}, + [IREG_cycles] = { REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT}, + [IREG_CS_base] = { REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_base] = { REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_base] = { REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_base] = { REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_base] = { REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_base] = { REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_CS_seg] = { REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_seg] = { REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_seg] = { REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_seg] = { REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_seg] = { REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_seg] = { REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT}, - [IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT}, + [IREG_FPU_TOP] = { REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT}, - [IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST0] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST1] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST2] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST3] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST4] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST5] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST6] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, + [IREG_ST7] = { REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT}, - [IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag0] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag1] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag2] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag3] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag4] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag5] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag6] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, + [IREG_tag7] = { REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT}, - [IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST0_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST1_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST2_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST3_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST4_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST5_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST6_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_ST7_i64] = { REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, - [IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT}, - [IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT}, - [IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT}, - [IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT}, - [IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT}, - [IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT}, - [IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT}, + [IREG_MM0x] = { REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT}, + [IREG_MM1x] = { REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT}, + [IREG_MM2x] = { REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT}, + [IREG_MM3x] = { REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT}, + [IREG_MM4x] = { REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT}, + [IREG_MM5x] = { REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT}, + [IREG_MM6x] = { REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT}, + [IREG_MM7x] = { REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT}, - [IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT}, - [IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT}, + [IREG_NPXCx] = { REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT}, + [IREG_NPXSx] = { REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT}, - [IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT}, - [IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT}, + [IREG_flagsx] = { REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT}, + [IREG_eflagsx] = { REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_limit_low] = {REG_DWORD, &cpu_state.seg_cs.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_limit_low] = {REG_DWORD, &cpu_state.seg_ds.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_limit_low] = {REG_DWORD, &cpu_state.seg_es.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_limit_low] = {REG_DWORD, &cpu_state.seg_fs.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_limit_low] = {REG_DWORD, &cpu_state.seg_gs.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_limit_low] = {REG_DWORD, &cpu_state.seg_ss.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_CS_limit_low] = { REG_DWORD, &cpu_state.seg_cs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_limit_low] = { REG_DWORD, &cpu_state.seg_ds.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_limit_low] = { REG_DWORD, &cpu_state.seg_es.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_limit_low] = { REG_DWORD, &cpu_state.seg_fs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_limit_low] = { REG_DWORD, &cpu_state.seg_gs.limit_low, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_limit_low] = { REG_DWORD, &cpu_state.seg_ss.limit_low, REG_INTEGER, REG_PERMANENT}, - [IREG_CS_limit_high] = {REG_DWORD, &cpu_state.seg_cs.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_DS_limit_high] = {REG_DWORD, &cpu_state.seg_ds.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_ES_limit_high] = {REG_DWORD, &cpu_state.seg_es.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_FS_limit_high] = {REG_DWORD, &cpu_state.seg_fs.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_GS_limit_high] = {REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT}, - [IREG_SS_limit_high] = {REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_CS_limit_high] = { REG_DWORD, &cpu_state.seg_cs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_DS_limit_high] = { REG_DWORD, &cpu_state.seg_ds.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_ES_limit_high] = { REG_DWORD, &cpu_state.seg_es.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_FS_limit_high] = { REG_DWORD, &cpu_state.seg_fs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_GS_limit_high] = { REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT}, + [IREG_SS_limit_high] = { REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT}, - /*Temporary registers are stored on the stack, and are not guaranteed to - be preserved across uOPs. They will not be written back if they will - not be read again.*/ - [IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER, REG_VOLATILE}, - [IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER, REG_VOLATILE}, - [IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER, REG_VOLATILE}, - [IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER, REG_VOLATILE}, + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + [IREG_temp0] = { REG_DWORD, (void *) 16, REG_INTEGER, REG_VOLATILE }, + [IREG_temp1] = { REG_DWORD, (void *) 20, REG_INTEGER, REG_VOLATILE }, + [IREG_temp2] = { REG_DWORD, (void *) 24, REG_INTEGER, REG_VOLATILE }, + [IREG_temp3] = { REG_DWORD, (void *) 28, REG_INTEGER, REG_VOLATILE }, - [IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP, REG_VOLATILE}, - [IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE}, + [IREG_temp0d] = { REG_DOUBLE, (void *) 40, REG_FP, REG_VOLATILE }, + [IREG_temp1d] = { REG_DOUBLE, (void *) 48, REG_FP, REG_VOLATILE }, }; -void codegen_reg_mark_as_required(void) +void +codegen_reg_mark_as_required(void) { - int reg; + int reg; - for (reg = 0; reg < IREG_COUNT; reg++) - { - int last_version = reg_last_version[reg]; + for (reg = 0; reg < IREG_COUNT; reg++) { + int last_version = reg_last_version[reg]; - if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT) - reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED; - } + if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT) + reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED; + } } -int reg_is_native_size(ir_reg_t ir_reg) +int +reg_is_native_size(ir_reg_t ir_reg) { - int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; - int requested_size = IREG_GET_SIZE(ir_reg.reg); + int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; + int requested_size = IREG_GET_SIZE(ir_reg.reg); - switch (native_size) - { - case REG_BYTE: case REG_FPU_ST_BYTE: - return (requested_size == IREG_SIZE_B); - case REG_WORD: - return (requested_size == IREG_SIZE_W); - case REG_DWORD: + switch (native_size) { + case REG_BYTE: + case REG_FPU_ST_BYTE: + return (requested_size == IREG_SIZE_B); + case REG_WORD: + return (requested_size == IREG_SIZE_W); + case REG_DWORD: + return (requested_size == IREG_SIZE_L); + case REG_QWORD: + case REG_FPU_ST_QWORD: + case REG_DOUBLE: + case REG_FPU_ST_DOUBLE: + return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q)); + case REG_POINTER: + if (sizeof(void *) == 4) return (requested_size == IREG_SIZE_L); - case REG_QWORD: case REG_FPU_ST_QWORD: case REG_DOUBLE: case REG_FPU_ST_DOUBLE: - return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q)); - case REG_POINTER: - if (sizeof(void *) == 4) - return (requested_size == IREG_SIZE_L); - return (requested_size == IREG_SIZE_Q); + return (requested_size == IREG_SIZE_Q); - default: - fatal("get_reg_is_native_size: unknown native size %i\n", native_size); - } + default: + fatal("get_reg_is_native_size: unknown native size %i\n", native_size); + } - return 0; + return 0; } -void codegen_reg_reset(void) +void +codegen_reg_reset(void) { - int c; + int c; - host_reg_set.regs = _host_regs; - host_reg_set.dirty = _host_reg_dirty; - host_reg_set.reg_list = codegen_host_reg_list; - host_reg_set.locked = 0; - host_reg_set.nr_regs = CODEGEN_HOST_REGS; - host_fp_reg_set.regs = host_fp_regs; - host_fp_reg_set.dirty = host_fp_reg_dirty; - host_fp_reg_set.reg_list = codegen_host_fp_reg_list; - host_fp_reg_set.locked = 0; - host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS; + host_reg_set.regs = _host_regs; + host_reg_set.dirty = _host_reg_dirty; + host_reg_set.reg_list = codegen_host_reg_list; + host_reg_set.locked = 0; + host_reg_set.nr_regs = CODEGEN_HOST_REGS; + host_fp_reg_set.regs = host_fp_regs; + host_fp_reg_set.dirty = host_fp_reg_dirty; + host_fp_reg_set.reg_list = codegen_host_fp_reg_list; + host_fp_reg_set.locked = 0; + host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS; - for (c = 0; c < IREG_COUNT; c++) - { - reg_last_version[c] = 0; - reg_version[c][0].refcount = 0; - } - for (c = 0; c < CODEGEN_HOST_REGS; c++) - { - host_reg_set.regs[c] = invalid_ir_reg; - host_reg_set.dirty[c] = 0; - } - for (c = 0; c < CODEGEN_HOST_FP_REGS; c++) - { - host_fp_reg_set.regs[c] = invalid_ir_reg; - host_fp_reg_set.dirty[c] = 0; - } + for (c = 0; c < IREG_COUNT; c++) { + reg_last_version[c] = 0; + reg_version[c][0].refcount = 0; + } + for (c = 0; c < CODEGEN_HOST_REGS; c++) { + host_reg_set.regs[c] = invalid_ir_reg; + host_reg_set.dirty[c] = 0; + } + for (c = 0; c < CODEGEN_HOST_FP_REGS; c++) { + host_fp_reg_set.regs[c] = invalid_ir_reg; + host_fp_reg_set.dirty[c] = 0; + } - reg_dead_list = 0; - max_version_refcount = 0; + reg_dead_list = 0; + max_version_refcount = 0; } -static inline int ir_get_refcount(ir_reg_t ir_reg) +static inline int +ir_get_refcount(ir_reg_t ir_reg) { - return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount; + return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount; } -static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg) +static inline host_reg_set_t * +get_reg_set(ir_reg_t ir_reg) { - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER) - return &host_reg_set; - else - return &host_fp_reg_set; + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER) + return &host_reg_set; + else + return &host_fp_reg_set; } -static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg) +static void +codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg) { - switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) - { - case REG_WORD: + switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size) { + case REG_WORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_16_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_16(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_16_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_16(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_DWORD: + case REG_DWORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_32_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_32(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_32_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_32(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_QWORD: + case REG_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_QWORD !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_QWORD !REG_FP\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_64_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_64(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_64_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_64(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_POINTER: + case REG_POINTER: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_pointer_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_pointer(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_pointer_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_pointer(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_DOUBLE: + case REG_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n"); #endif - if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) - codegen_direct_read_double_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p); - else - codegen_direct_read_double(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); - break; + if ((uintptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256) + codegen_direct_read_double_stack(block, reg_set->reg_list[c].reg, (intptr_t) ireg_data[IREG_GET_REG(ir_reg.reg)].p); + else + codegen_direct_read_double(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p); + break; - case REG_FPU_ST_BYTE: + case REG_FPU_ST_BYTE: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) - fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER) + fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_read_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[ir_reg.reg & 7]); - else - codegen_direct_read_st_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[0], ir_reg.reg & 7); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[ir_reg.reg & 7]); + else + codegen_direct_read_st_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[0], ir_reg.reg & 7); + break; - case REG_FPU_ST_QWORD: + case REG_FPU_ST_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_read_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[ir_reg.reg & 7]); - else - codegen_direct_read_st_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[0], ir_reg.reg & 7); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[ir_reg.reg & 7]); + else + codegen_direct_read_st_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[0], ir_reg.reg & 7); + break; - case REG_FPU_ST_DOUBLE: + case REG_FPU_ST_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) - fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n"); + if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP) + fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_read_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[ir_reg.reg & 7]); - else - codegen_direct_read_st_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[0], ir_reg.reg & 7); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_read_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[ir_reg.reg & 7]); + else + codegen_direct_read_st_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[0], ir_reg.reg & 7); + break; - default: - fatal("codegen_reg_load - native_size=%i reg=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size, IREG_GET_REG(ir_reg.reg)); - } + default: + fatal("codegen_reg_load - native_size=%i reg=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size, IREG_GET_REG(ir_reg.reg)); + } - reg_set->regs[c] = ir_reg; + reg_set->regs[c] = ir_reg; } -static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate) +static void +codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate) { - int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); - void *p = ireg_data[ir_reg].p; + int ir_reg = IREG_GET_REG(reg_set->regs[c].reg); + void *p = ireg_data[ir_reg].p; - if (!reg_version[ir_reg][reg_set->regs[c].version].refcount && - ireg_data[ir_reg].is_volatile) - return; + if (!reg_version[ir_reg][reg_set->regs[c].version].refcount && ireg_data[ir_reg].is_volatile) + return; - switch (ireg_data[ir_reg].native_size) - { - case REG_BYTE: + switch (ireg_data[ir_reg].native_size) { + case REG_BYTE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n"); - if ((uintptr_t)p < 256) - fatal("codegen_reg_writeback - REG_BYTE %p\n", p); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n"); + if ((uintptr_t) p < 256) + fatal("codegen_reg_writeback - REG_BYTE %p\n", p); #endif - codegen_direct_write_8(block, p, reg_set->reg_list[c].reg); - break; + codegen_direct_write_8(block, p, reg_set->reg_list[c].reg); + break; - case REG_WORD: + case REG_WORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n"); - if ((uintptr_t)p < 256) - fatal("codegen_reg_writeback - REG_WORD %p\n", p); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n"); + if ((uintptr_t) p < 256) + fatal("codegen_reg_writeback - REG_WORD %p\n", p); #endif - codegen_direct_write_16(block, p, reg_set->reg_list[c].reg); - break; + codegen_direct_write_16(block, p, reg_set->reg_list[c].reg); + break; - case REG_DWORD: + case REG_DWORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n"); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n"); #endif - if ((uintptr_t)p < 256) - codegen_direct_write_32_stack(block, (intptr_t)p, reg_set->reg_list[c].reg); - else - codegen_direct_write_32(block, p, reg_set->reg_list[c].reg); - break; + if ((uintptr_t) p < 256) + codegen_direct_write_32_stack(block, (intptr_t) p, reg_set->reg_list[c].reg); + else + codegen_direct_write_32(block, p, reg_set->reg_list[c].reg); + break; - case REG_QWORD: + case REG_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n"); #endif - if ((uintptr_t)p < 256) - codegen_direct_write_64_stack(block, (intptr_t)p, reg_set->reg_list[c].reg); - else - codegen_direct_write_64(block, p, reg_set->reg_list[c].reg); - break; + if ((uintptr_t) p < 256) + codegen_direct_write_64_stack(block, (intptr_t) p, reg_set->reg_list[c].reg); + else + codegen_direct_write_64(block, p, reg_set->reg_list[c].reg); + break; - case REG_POINTER: + case REG_POINTER: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); - if ((uintptr_t)p < 256) - fatal("codegen_reg_writeback - REG_POINTER %p\n", p); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n"); + if ((uintptr_t) p < 256) + fatal("codegen_reg_writeback - REG_POINTER %p\n", p); #endif - codegen_direct_write_ptr(block, p, reg_set->reg_list[c].reg); - break; + codegen_direct_write_ptr(block, p, reg_set->reg_list[c].reg); + break; - case REG_DOUBLE: + case REG_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n"); #endif - if ((uintptr_t)p < 256) - codegen_direct_write_double_stack(block, (intptr_t)p, reg_set->reg_list[c].reg); - else - codegen_direct_write_double(block, p, reg_set->reg_list[c].reg); - break; + if ((uintptr_t) p < 256) + codegen_direct_write_double_stack(block, (intptr_t) p, reg_set->reg_list[c].reg); + else + codegen_direct_write_double(block, p, reg_set->reg_list[c].reg); + break; - case REG_FPU_ST_BYTE: + case REG_FPU_ST_BYTE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_INTEGER) - fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n"); + if (ireg_data[ir_reg].type != REG_INTEGER) + fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); - else - codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); + else + codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); + break; - case REG_FPU_ST_QWORD: + case REG_FPU_ST_QWORD: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); - else - codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); + else + codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); + break; - case REG_FPU_ST_DOUBLE: + case REG_FPU_ST_DOUBLE: #ifndef RELEASE_BUILD - if (ireg_data[ir_reg].type != REG_FP) - fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n"); + if (ireg_data[ir_reg].type != REG_FP) + fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n"); #endif - if (block->flags & CODEBLOCK_STATIC_TOP) - codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); - else - codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); - break; + if (block->flags & CODEBLOCK_STATIC_TOP) + codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg); + else + codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg); + break; - default: - fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); - } + default: + fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size); + } - if (invalidate) - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; + if (invalidate) + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } #ifdef CODEGEN_BACKEND_HAS_MOV_IMM -void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data) +void +codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data) { - int reg_idx = IREG_GET_REG(ir_reg.reg); - void *p = ireg_data[reg_idx].p; + int reg_idx = IREG_GET_REG(ir_reg.reg); + void *p = ireg_data[reg_idx].p; - switch (ireg_data[reg_idx].native_size) - { - case REG_BYTE: -#ifndef RELEASE_BUILD - if ((uintptr_t)p < 256) - fatal("codegen_reg_write_imm - REG_BYTE %p\n", p); -#endif - codegen_direct_write_8_imm(block, p, imm_data); - break; + switch (ireg_data[reg_idx].native_size) { + case REG_BYTE: +# ifndef RELEASE_BUILD + if ((uintptr_t) p < 256) + fatal("codegen_reg_write_imm - REG_BYTE %p\n", p); +# endif + codegen_direct_write_8_imm(block, p, imm_data); + break; - case REG_WORD: -#ifndef RELEASE_BUILD - if ((uintptr_t)p < 256) - fatal("codegen_reg_write_imm - REG_WORD %p\n", p); -#endif - codegen_direct_write_16_imm(block, p, imm_data); - break; + case REG_WORD: +# ifndef RELEASE_BUILD + if ((uintptr_t) p < 256) + fatal("codegen_reg_write_imm - REG_WORD %p\n", p); +# endif + codegen_direct_write_16_imm(block, p, imm_data); + break; - case REG_DWORD: - if ((uintptr_t)p < 256) - codegen_direct_write_32_imm_stack(block, (int)((uintptr_t) p), imm_data); - else - codegen_direct_write_32_imm(block, p, imm_data); - break; + case REG_DWORD: + if ((uintptr_t) p < 256) + codegen_direct_write_32_imm_stack(block, (int) ((uintptr_t) p), imm_data); + else + codegen_direct_write_32_imm(block, p, imm_data); + break; - case REG_POINTER: - case REG_QWORD: - case REG_DOUBLE: - case REG_FPU_ST_BYTE: - case REG_FPU_ST_QWORD: - case REG_FPU_ST_DOUBLE: - default: - fatal("codegen_reg_write_imm - native_size=%i\n", ireg_data[reg_idx].native_size); - } + case REG_POINTER: + case REG_QWORD: + case REG_DOUBLE: + case REG_FPU_ST_BYTE: + case REG_FPU_ST_QWORD: + case REG_FPU_ST_DOUBLE: + default: + fatal("codegen_reg_write_imm - native_size=%i\n", ireg_data[reg_idx].native_size); + } } #endif -static void alloc_reg(ir_reg_t ir_reg) +static void +alloc_reg(ir_reg_t ir_reg) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; - int c; + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; + int c; - for (c = 0; c < nr_regs; c++) - { - if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { + for (c = 0; c < nr_regs; c++) { + if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { #ifndef RELEASE_BUILD - if (reg_set->regs[c].version != ir_reg.version) - fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg); + if (reg_set->regs[c].version != ir_reg.version) + fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg); #endif + reg_set->locked |= (1 << c); + return; + } + } +} + +static void +alloc_dest_reg(ir_reg_t ir_reg, int dest_reference) +{ + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; + int c; + + for (c = 0; c < nr_regs; c++) { + if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { + if (reg_set->regs[c].version == ir_reg.version) { + reg_set->locked |= (1 << c); + } else { + /*The immediate prior version may have been + optimised out, so search backwards to find the + last valid version*/ + int prev_version = ir_reg.version - 1; + while (prev_version >= 0) { + reg_version_t *regv = ®_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version]; + + if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference) { reg_set->locked |= (1 << c); return; + } + prev_version--; } + fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference); + } + return; } + } } -static void alloc_dest_reg(ir_reg_t ir_reg, int dest_reference) +void +codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS; - int c; + int dest_reference = 0; - for (c = 0; c < nr_regs; c++) - { - if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { - if (reg_set->regs[c].version == ir_reg.version) - { - reg_set->locked |= (1 << c); - } - else - { - /*The immediate prior version may have been - optimised out, so search backwards to find the - last valid version*/ - int prev_version = ir_reg.version-1; - while (prev_version >= 0) - { - reg_version_t *regv = ®_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version]; + host_reg_set.locked = 0; + host_fp_reg_set.locked = 0; - if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference) - { - reg_set->locked |= (1 << c); - return; - } - prev_version--; - } - fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference); - } - return; - } - } + if (!ir_reg_is_invalid(dest_reg_a)) { + if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version - 1) + dest_reference++; + if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version - 1) + dest_reference++; + if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version - 1) + dest_reference++; + } + if (!ir_reg_is_invalid(src_reg_a)) + alloc_reg(src_reg_a); + if (!ir_reg_is_invalid(src_reg_b)) + alloc_reg(src_reg_b); + if (!ir_reg_is_invalid(src_reg_c)) + alloc_reg(src_reg_c); + if (!ir_reg_is_invalid(dest_reg_a)) + alloc_dest_reg(dest_reg_a, dest_reference); } -void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c) +ir_host_reg_t +codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) { - int dest_reference = 0; + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int c; - host_reg_set.locked = 0; - host_fp_reg_set.locked = 0; + /*Search for required register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version) + break; - if (!ir_reg_is_invalid(dest_reg_a)) - { - if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version-1) - dest_reference++; - if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1) - dest_reference++; - if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version-1) - dest_reference++; + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version) { + reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++; + break; } - if (!ir_reg_is_invalid(src_reg_a)) - alloc_reg(src_reg_a); - if (!ir_reg_is_invalid(src_reg_b)) - alloc_reg(src_reg_b); - if (!ir_reg_is_invalid(src_reg_c)) - alloc_reg(src_reg_c); - if (!ir_reg_is_invalid(dest_reg_a)) - alloc_dest_reg(dest_reg_a, dest_reference); + +#ifndef RELEASE_BUILD + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount) + fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); +#endif + } + + if (c == reg_set->nr_regs) { + /*No unused registers. Search for an unlocked register with no pending reads*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c])) + break; + } + if (c == reg_set->nr_regs) { + /*Search for any unlocked register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!(reg_set->locked & (1 << c))) + break; + } +#ifndef RELEASE_BUILD + if (c == reg_set->nr_regs) + fatal("codegen_reg_alloc_read_reg - out of registers\n"); +#endif + } + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, c, 1); + codegen_reg_load(reg_set, block, c, ir_reg); + reg_set->locked |= (1 << c); + reg_set->dirty[c] = 0; + } + + reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--; +#ifndef RELEASE_BUILD + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t) -1) + fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); +#endif + + if (host_reg_idx) + *host_reg_idx = c; + return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); } -ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx) +ir_host_reg_t +codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int c; + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int c; - /*Search for required register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version) - break; + if (!reg_is_native_size(ir_reg)) { + /*Read in parent register so we can do partial accesses to it*/ + ir_reg_t parent_reg; - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version) - { - reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++; - break; - } + parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; + parent_reg.version = ir_reg.version - 1; + reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++; + + codegen_reg_alloc_read_reg(block, parent_reg, &c); #ifndef RELEASE_BUILD - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount) - fatal("codegen_reg_alloc_read_reg - version mismatch!\n"); -#endif - } - - if (c == reg_set->nr_regs) - { - /*No unused registers. Search for an unlocked register with no pending reads*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c])) - break; - } - if (c == reg_set->nr_regs) - { - /*Search for any unlocked register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!(reg_set->locked & (1 << c))) - break; - } -#ifndef RELEASE_BUILD - if (c == reg_set->nr_regs) - fatal("codegen_reg_alloc_read_reg - out of registers\n"); -#endif - } - if (reg_set->dirty[c]) - codegen_reg_writeback(reg_set, block, c, 1); - codegen_reg_load(reg_set, block, c, ir_reg); - reg_set->locked |= (1 << c); - reg_set->dirty[c] = 0; - } - - reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--; -#ifndef RELEASE_BUILD - if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t)-1) - fatal("codegen_reg_alloc_read_reg - refcount < 0\n"); + if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version - 1) + fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, + reg_set->regs[c].reg, reg_set->regs[c].version, + ir_reg.reg, ir_reg.version); #endif - if (host_reg_idx) - *host_reg_idx = c; - return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); -} - -ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg) -{ - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int c; - - if (!reg_is_native_size(ir_reg)) - { - /*Read in parent register so we can do partial accesses to it*/ - ir_reg_t parent_reg; - - parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L; - parent_reg.version = ir_reg.version - 1; - reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++; - - codegen_reg_alloc_read_reg(block, parent_reg, &c); - -#ifndef RELEASE_BUILD - if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version-1) - fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c, - reg_set->regs[c].reg,reg_set->regs[c].version, - ir_reg.reg,ir_reg.version); -#endif - - reg_set->regs[c].reg = ir_reg.reg; - reg_set->regs[c].version = ir_reg.version; - reg_set->dirty[c] = 1; - return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); - } - - /*Search for previous version in host register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { - if (reg_set->regs[c].version <= ir_reg.version-1) - { -#ifndef RELEASE_BUILD - if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) - fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); -#endif - break; - } - } - } - - if (c == reg_set->nr_regs) - { - /*Search for unused registers*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (ir_reg_is_invalid(reg_set->regs[c])) - break; - } - - if (c == reg_set->nr_regs) - { - /*No unused registers. Search for an unlocked register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!(reg_set->locked & (1 << c))) - break; - } -#ifndef RELEASE_BUILD - if (c == reg_set->nr_regs) - fatal("codegen_reg_alloc_write_reg - out of registers\n"); -#endif - if (reg_set->dirty[c]) - codegen_reg_writeback(reg_set, block, c, 1); - } - } - - reg_set->regs[c].reg = ir_reg.reg; + reg_set->regs[c].reg = ir_reg.reg; reg_set->regs[c].version = ir_reg.version; - reg_set->dirty[c] = 1; + reg_set->dirty[c] = 1; return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); + } + + /*Search for previous version in host register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { + if (reg_set->regs[c].version <= ir_reg.version - 1) { +#ifndef RELEASE_BUILD + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) + fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); +#endif + break; + } + } + } + + if (c == reg_set->nr_regs) { + /*Search for unused registers*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (ir_reg_is_invalid(reg_set->regs[c])) + break; + } + + if (c == reg_set->nr_regs) { + /*No unused registers. Search for an unlocked register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!(reg_set->locked & (1 << c))) + break; + } +#ifndef RELEASE_BUILD + if (c == reg_set->nr_regs) + fatal("codegen_reg_alloc_write_reg - out of registers\n"); +#endif + if (reg_set->dirty[c]) + codegen_reg_writeback(reg_set, block, c, 1); + } + } + + reg_set->regs[c].reg = ir_reg.reg; + reg_set->regs[c].version = ir_reg.version; + reg_set->dirty[c] = 1; + return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg); } #ifdef CODEGEN_BACKEND_HAS_MOV_IMM -int codegen_reg_is_loaded(ir_reg_t ir_reg) +int +codegen_reg_is_loaded(ir_reg_t ir_reg) { - host_reg_set_t *reg_set = get_reg_set(ir_reg); - int c; + host_reg_set_t *reg_set = get_reg_set(ir_reg); + int c; - /*Search for previous version in host register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) - { - if (reg_set->regs[c].version <= ir_reg.version-1) - { + /*Search for previous version in host register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg)) { + if (reg_set->regs[c].version <= ir_reg.version - 1) { +# ifndef RELEASE_BUILD + if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) + fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); +# endif + return 1; + } + } + } + return 0; +} +#endif + +void +codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst) +{ + host_reg_set_t *reg_set = get_reg_set(src); + int c; + int target; + + // pclog("rename: %i.%i -> %i.%i\n", src.reg,src.version, dst.reg, dst.version); + /*Search for required register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src.reg) && reg_set->regs[c].version == src.version) + break; + } #ifndef RELEASE_BUILD - if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0) - fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n"); -#endif - return 1; - } - } - } - return 0; -} + if (c == reg_set->nr_regs) + fatal("codegen_reg_rename: Can't find register to rename\n"); #endif + target = c; + if (reg_set->dirty[target]) + codegen_reg_writeback(reg_set, block, target, 0); + reg_set->regs[target] = dst; + reg_set->dirty[target] = 1; + // pclog("renamed reg %i dest=%i.%i\n", target, dst.reg, dst.version); -void codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst) -{ - host_reg_set_t *reg_set = get_reg_set(src); - int c; - int target; - -// pclog("rename: %i.%i -> %i.%i\n", src.reg,src.version, dst.reg, dst.version); - /*Search for required register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src.reg) && reg_set->regs[c].version == src.version) - break; - } -#ifndef RELEASE_BUILD - if (c == reg_set->nr_regs) - fatal("codegen_reg_rename: Can't find register to rename\n"); -#endif - target = c; - if (reg_set->dirty[target]) - codegen_reg_writeback(reg_set, block, target, 0); - reg_set->regs[target] = dst; - reg_set->dirty[target] = 1; -// pclog("renamed reg %i dest=%i.%i\n", target, dst.reg, dst.version); - - /*Invalidate any stale copies of the dest register*/ - for (c = 0; c < reg_set->nr_regs; c++) - { - if (c == target) - continue; - if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dst.reg)) - { - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } + /*Invalidate any stale copies of the dest register*/ + for (c = 0; c < reg_set->nr_regs; c++) { + if (c == target) + continue; + if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dst.reg)) { + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; } + } } -void codegen_reg_flush(ir_data_t *ir, codeblock_t *block) +void +codegen_reg_flush(ir_data_t *ir, codeblock_t *block) { - host_reg_set_t *reg_set; - int c; + host_reg_set_t *reg_set; + int c; - reg_set = &host_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 0); - } - if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) - { - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } + reg_set = &host_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 0); } + if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) { + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } + } - reg_set = &host_fp_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 0); - } - if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) - { - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; - } + reg_set = &host_fp_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 0); } + if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE) { + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } + } } -void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) +void +codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block) { - host_reg_set_t *reg_set; - int c; + host_reg_set_t *reg_set; + int c; - reg_set = &host_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 1); - } - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; + reg_set = &host_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 1); } + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } - reg_set = &host_fp_reg_set; - for (c = 0; c < reg_set->nr_regs; c++) - { - if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) - { - codegen_reg_writeback(reg_set, block, c, 1); - } - reg_set->regs[c] = invalid_ir_reg; - reg_set->dirty[c] = 0; + reg_set = &host_fp_reg_set; + for (c = 0; c < reg_set->nr_regs; c++) { + if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c]) { + codegen_reg_writeback(reg_set, block, c, 1); } + reg_set->regs[c] = invalid_ir_reg; + reg_set->dirty[c] = 0; + } } /*Process dead register list, and optimise out register versions and uOPs where possible*/ -void codegen_reg_process_dead_list(ir_data_t *ir) +void +codegen_reg_process_dead_list(ir_data_t *ir) { - while (reg_dead_list) - { - int version = reg_dead_list & 0xff; - int reg = reg_dead_list >> 8; - reg_version_t *regv = ®_version[reg][version]; - uop_t *uop = &ir->uops[regv->parent_uop]; + while (reg_dead_list) { + int version = reg_dead_list & 0xff; + int reg = reg_dead_list >> 8; + reg_version_t *regv = ®_version[reg][version]; + uop_t *uop = &ir->uops[regv->parent_uop]; - /*Barrier uOPs should be preserved*/ - if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))) - { - uop->type = UOP_INVALID; - /*Adjust refcounts on source registers. If these drop to - zero then those registers can be considered for removal*/ - if (uop->src_reg_a.reg != IREG_INVALID) - { - reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version]; - src_regv->refcount--; - if (!src_regv->refcount) - add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version); - } - if (uop->src_reg_b.reg != IREG_INVALID) - { - reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version]; - src_regv->refcount--; - if (!src_regv->refcount) - add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version); - } - if (uop->src_reg_c.reg != IREG_INVALID) - { - reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version]; - src_regv->refcount--; - if (!src_regv->refcount) - add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version); - } - regv->flags |= REG_FLAGS_DEAD; - } - - reg_dead_list = regv->next; + /*Barrier uOPs should be preserved*/ + if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))) { + uop->type = UOP_INVALID; + /*Adjust refcounts on source registers. If these drop to + zero then those registers can be considered for removal*/ + if (uop->src_reg_a.reg != IREG_INVALID) { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version); + } + if (uop->src_reg_b.reg != IREG_INVALID) { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version); + } + if (uop->src_reg_c.reg != IREG_INVALID) { + reg_version_t *src_regv = ®_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version]; + src_regv->refcount--; + if (!src_regv->refcount) + add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version); + } + regv->flags |= REG_FLAGS_DEAD; } + + reg_dead_list = regv->next; + } } diff --git a/src/codegen_new/codegen_reg.h b/src/codegen_new/codegen_reg.h index fb8789474..c106349f5 100644 --- a/src/codegen_new/codegen_reg.h +++ b/src/codegen_new/codegen_reg.h @@ -1,276 +1,278 @@ #ifndef _CODEGEN_REG_H_ #define _CODEGEN_REG_H_ -#define IREG_REG_MASK 0xff -#define IREG_SIZE_SHIFT 8 -#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT) +#define IREG_REG_MASK 0xff +#define IREG_SIZE_SHIFT 8 +#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT) -#define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK) -#define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK) +#define IREG_GET_REG(reg) ((reg) &IREG_REG_MASK) +#define IREG_GET_SIZE(reg) ((reg) &IREG_SIZE_MASK) -#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT) -#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) -#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) -#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) -#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) -#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) +#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT) +#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT) +#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT) +#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT) +#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT) +#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) -enum -{ - IREG_EAX = 0, - IREG_ECX = 1, - IREG_EDX = 2, - IREG_EBX = 3, - IREG_ESP = 4, - IREG_EBP = 5, - IREG_ESI = 6, - IREG_EDI = 7, +enum { + IREG_EAX = 0, + IREG_ECX = 1, + IREG_EDX = 2, + IREG_EBX = 3, + IREG_ESP = 4, + IREG_EBP = 5, + IREG_ESI = 6, + IREG_EDI = 7, - IREG_flags_op = 8, - IREG_flags_res = 9, - IREG_flags_op1 = 10, - IREG_flags_op2 = 11, + IREG_flags_op = 8, + IREG_flags_res = 9, + IREG_flags_op1 = 10, + IREG_flags_op2 = 11, - IREG_pc = 12, - IREG_oldpc = 13, + IREG_pc = 12, + IREG_oldpc = 13, - IREG_eaaddr = 14, - IREG_ea_seg = 15, - IREG_op32 = 16, - IREG_ssegsx = 17, + IREG_eaaddr = 14, + IREG_ea_seg = 15, + IREG_op32 = 16, + IREG_ssegsx = 17, - IREG_rm_mod_reg = 18, + IREG_rm_mod_reg = 18, - IREG_acycs = 19, - IREG_cycles = 20, + IREG_acycs = 19, + IREG_cycles = 20, - IREG_CS_base = 21, - IREG_DS_base = 22, - IREG_ES_base = 23, - IREG_FS_base = 24, - IREG_GS_base = 25, - IREG_SS_base = 26, + IREG_CS_base = 21, + IREG_DS_base = 22, + IREG_ES_base = 23, + IREG_FS_base = 24, + IREG_GS_base = 25, + IREG_SS_base = 26, - IREG_CS_seg = 27, - IREG_DS_seg = 28, - IREG_ES_seg = 29, - IREG_FS_seg = 30, - IREG_GS_seg = 31, - IREG_SS_seg = 32, + IREG_CS_seg = 27, + IREG_DS_seg = 28, + IREG_ES_seg = 29, + IREG_FS_seg = 30, + IREG_GS_seg = 31, + IREG_SS_seg = 32, - /*Temporary registers are stored on the stack, and are not guaranteed to - be preserved across uOPs. They will not be written back if they will - not be read again.*/ - IREG_temp0 = 33, - IREG_temp1 = 34, - IREG_temp2 = 35, - IREG_temp3 = 36, + /*Temporary registers are stored on the stack, and are not guaranteed to + be preserved across uOPs. They will not be written back if they will + not be read again.*/ + IREG_temp0 = 33, + IREG_temp1 = 34, + IREG_temp2 = 35, + IREG_temp3 = 36, - IREG_FPU_TOP = 37, + IREG_FPU_TOP = 37, - IREG_temp0d = 38, - IREG_temp1d = 39, + IREG_temp0d = 38, + IREG_temp1d = 39, - /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() - to access. - When CODEBLOCK_STATIC_TOP is set, the physical register number will be - used directly to index the stack. When it is clear, the difference - between the current value of TOP and the value when the block was - first compiled will be added to adjust for any changes in TOP.*/ - IREG_ST0 = 40, - IREG_ST1 = 41, - IREG_ST2 = 42, - IREG_ST3 = 43, - IREG_ST4 = 44, - IREG_ST5 = 45, - IREG_ST6 = 46, - IREG_ST7 = 47, + /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() + to access. + When CODEBLOCK_STATIC_TOP is set, the physical register number will be + used directly to index the stack. When it is clear, the difference + between the current value of TOP and the value when the block was + first compiled will be added to adjust for any changes in TOP.*/ + IREG_ST0 = 40, + IREG_ST1 = 41, + IREG_ST2 = 42, + IREG_ST3 = 43, + IREG_ST4 = 44, + IREG_ST5 = 45, + IREG_ST6 = 46, + IREG_ST7 = 47, - IREG_tag0 = 48, - IREG_tag1 = 49, - IREG_tag2 = 50, - IREG_tag3 = 51, - IREG_tag4 = 52, - IREG_tag5 = 53, - IREG_tag6 = 54, - IREG_tag7 = 55, + IREG_tag0 = 48, + IREG_tag1 = 49, + IREG_tag2 = 50, + IREG_tag3 = 51, + IREG_tag4 = 52, + IREG_tag5 = 53, + IREG_tag6 = 54, + IREG_tag7 = 55, - IREG_ST0_i64 = 56, - IREG_ST1_i64 = 57, - IREG_ST2_i64 = 58, - IREG_ST3_i64 = 59, - IREG_ST4_i64 = 60, - IREG_ST5_i64 = 61, - IREG_ST6_i64 = 62, - IREG_ST7_i64 = 63, + IREG_ST0_i64 = 56, + IREG_ST1_i64 = 57, + IREG_ST2_i64 = 58, + IREG_ST3_i64 = 59, + IREG_ST4_i64 = 60, + IREG_ST5_i64 = 61, + IREG_ST6_i64 = 62, + IREG_ST7_i64 = 63, - IREG_MM0x = 64, - IREG_MM1x = 65, - IREG_MM2x = 66, - IREG_MM3x = 67, - IREG_MM4x = 68, - IREG_MM5x = 69, - IREG_MM6x = 70, - IREG_MM7x = 71, + IREG_MM0x = 64, + IREG_MM1x = 65, + IREG_MM2x = 66, + IREG_MM3x = 67, + IREG_MM4x = 68, + IREG_MM5x = 69, + IREG_MM6x = 70, + IREG_MM7x = 71, - IREG_NPXCx = 72, - IREG_NPXSx = 73, + IREG_NPXCx = 72, + IREG_NPXSx = 73, - IREG_flagsx = 74, - IREG_eflagsx = 75, + IREG_flagsx = 74, + IREG_eflagsx = 75, - IREG_CS_limit_low = 76, - IREG_DS_limit_low = 77, - IREG_ES_limit_low = 78, - IREG_FS_limit_low = 79, - IREG_GS_limit_low = 80, - IREG_SS_limit_low = 81, + IREG_CS_limit_low = 76, + IREG_DS_limit_low = 77, + IREG_ES_limit_low = 78, + IREG_FS_limit_low = 79, + IREG_GS_limit_low = 80, + IREG_SS_limit_low = 81, - IREG_CS_limit_high = 82, - IREG_DS_limit_high = 83, - IREG_ES_limit_high = 84, - IREG_FS_limit_high = 85, - IREG_GS_limit_high = 86, - IREG_SS_limit_high = 87, + IREG_CS_limit_high = 82, + IREG_DS_limit_high = 83, + IREG_ES_limit_high = 84, + IREG_FS_limit_high = 85, + IREG_GS_limit_high = 86, + IREG_SS_limit_high = 87, - IREG_COUNT = 88, + IREG_COUNT = 88, - IREG_INVALID = 255, + IREG_INVALID = 255, - IREG_AX = IREG_EAX + IREG_SIZE_W, - IREG_CX = IREG_ECX + IREG_SIZE_W, - IREG_DX = IREG_EDX + IREG_SIZE_W, - IREG_BX = IREG_EBX + IREG_SIZE_W, - IREG_SP = IREG_ESP + IREG_SIZE_W, - IREG_BP = IREG_EBP + IREG_SIZE_W, - IREG_SI = IREG_ESI + IREG_SIZE_W, - IREG_DI = IREG_EDI + IREG_SIZE_W, + IREG_AX = IREG_EAX + IREG_SIZE_W, + IREG_CX = IREG_ECX + IREG_SIZE_W, + IREG_DX = IREG_EDX + IREG_SIZE_W, + IREG_BX = IREG_EBX + IREG_SIZE_W, + IREG_SP = IREG_ESP + IREG_SIZE_W, + IREG_BP = IREG_EBP + IREG_SIZE_W, + IREG_SI = IREG_ESI + IREG_SIZE_W, + IREG_DI = IREG_EDI + IREG_SIZE_W, - IREG_AL = IREG_EAX + IREG_SIZE_B, - IREG_CL = IREG_ECX + IREG_SIZE_B, - IREG_DL = IREG_EDX + IREG_SIZE_B, - IREG_BL = IREG_EBX + IREG_SIZE_B, + IREG_AL = IREG_EAX + IREG_SIZE_B, + IREG_CL = IREG_ECX + IREG_SIZE_B, + IREG_DL = IREG_EDX + IREG_SIZE_B, + IREG_BL = IREG_EBX + IREG_SIZE_B, - IREG_AH = IREG_EAX + IREG_SIZE_BH, - IREG_CH = IREG_ECX + IREG_SIZE_BH, - IREG_DH = IREG_EDX + IREG_SIZE_BH, - IREG_BH = IREG_EBX + IREG_SIZE_BH, + IREG_AH = IREG_EAX + IREG_SIZE_BH, + IREG_CH = IREG_ECX + IREG_SIZE_BH, + IREG_DH = IREG_EDX + IREG_SIZE_BH, + IREG_BH = IREG_EBX + IREG_SIZE_BH, - IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, - IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W, - IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W, + IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W, + IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W, + IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W, - IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, - IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B, - IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B, + IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B, + IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B, + IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B, - IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, - IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, - IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, - IREG_temp3_W = IREG_temp3 + IREG_SIZE_W, + IREG_temp0_W = IREG_temp0 + IREG_SIZE_W, + IREG_temp1_W = IREG_temp1 + IREG_SIZE_W, + IREG_temp2_W = IREG_temp2 + IREG_SIZE_W, + IREG_temp3_W = IREG_temp3 + IREG_SIZE_W, - IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, - IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, - IREG_temp2_B = IREG_temp2 + IREG_SIZE_B, - IREG_temp3_B = IREG_temp3 + IREG_SIZE_B, + IREG_temp0_B = IREG_temp0 + IREG_SIZE_B, + IREG_temp1_B = IREG_temp1 + IREG_SIZE_B, + IREG_temp2_B = IREG_temp2 + IREG_SIZE_B, + IREG_temp3_B = IREG_temp3 + IREG_SIZE_B, - IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, - IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, + IREG_temp0_D = IREG_temp0d + IREG_SIZE_D, + IREG_temp1_D = IREG_temp1d + IREG_SIZE_D, - IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q, - IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q, + IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q, + IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q, - IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, + IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W, - IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, - IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W, - IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W, - IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W, - IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, - IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, + IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W, + IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W, + IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W, + IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W, + IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W, + IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W, - IREG_MM0 = IREG_MM0x + IREG_SIZE_Q, - IREG_MM1 = IREG_MM1x + IREG_SIZE_Q, - IREG_MM2 = IREG_MM2x + IREG_SIZE_Q, - IREG_MM3 = IREG_MM3x + IREG_SIZE_Q, - IREG_MM4 = IREG_MM4x + IREG_SIZE_Q, - IREG_MM5 = IREG_MM5x + IREG_SIZE_Q, - IREG_MM6 = IREG_MM6x + IREG_SIZE_Q, - IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, + IREG_MM0 = IREG_MM0x + IREG_SIZE_Q, + IREG_MM1 = IREG_MM1x + IREG_SIZE_Q, + IREG_MM2 = IREG_MM2x + IREG_SIZE_Q, + IREG_MM3 = IREG_MM3x + IREG_SIZE_Q, + IREG_MM4 = IREG_MM4x + IREG_SIZE_Q, + IREG_MM5 = IREG_MM5x + IREG_SIZE_Q, + IREG_MM6 = IREG_MM6x + IREG_SIZE_Q, + IREG_MM7 = IREG_MM7x + IREG_SIZE_Q, - IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, - IREG_NPXS = IREG_NPXSx + IREG_SIZE_W, + IREG_NPXC = IREG_NPXCx + IREG_SIZE_W, + IREG_NPXS = IREG_NPXSx + IREG_SIZE_W, - IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, + IREG_ssegs = IREG_ssegsx + IREG_SIZE_B, - IREG_flags = IREG_flagsx + IREG_SIZE_W, - IREG_eflags = IREG_eflagsx + IREG_SIZE_W + IREG_flags = IREG_flagsx + IREG_SIZE_W, + IREG_eflags = IREG_eflagsx + IREG_SIZE_W }; -#define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL)) -#define IREG_16(reg) ((reg) + IREG_AX) -#define IREG_32(reg) ((reg) + IREG_EAX) +#define IREG_8(reg) (((reg) &4) ? (((reg) &3) + IREG_AH) : ((reg) + IREG_AL)) +#define IREG_16(reg) ((reg) + IREG_AX) +#define IREG_32(reg) ((reg) + IREG_EAX) -#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) -#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) -#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) -#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) +#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D) +#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q) +#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7)) +#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B) -#define IREG_MM(reg) ((reg) + IREG_MM0) +#define IREG_MM(reg) ((reg) + IREG_MM0) #define IREG_TOP_diff_stack_offset 32 -static inline int ireg_seg_base(x86seg *seg) +static inline int +ireg_seg_base(x86seg *seg) { - if (seg == &cpu_state.seg_cs) - return IREG_CS_base; - if (seg == &cpu_state.seg_ds) - return IREG_DS_base; - if (seg == &cpu_state.seg_es) - return IREG_ES_base; - if (seg == &cpu_state.seg_fs) - return IREG_FS_base; - if (seg == &cpu_state.seg_gs) - return IREG_GS_base; - if (seg == &cpu_state.seg_ss) - return IREG_SS_base; - fatal("ireg_seg_base : unknown segment\n"); - return 0; + if (seg == &cpu_state.seg_cs) + return IREG_CS_base; + if (seg == &cpu_state.seg_ds) + return IREG_DS_base; + if (seg == &cpu_state.seg_es) + return IREG_ES_base; + if (seg == &cpu_state.seg_fs) + return IREG_FS_base; + if (seg == &cpu_state.seg_gs) + return IREG_GS_base; + if (seg == &cpu_state.seg_ss) + return IREG_SS_base; + fatal("ireg_seg_base : unknown segment\n"); + return 0; } -static inline int ireg_seg_limit_low(x86seg *seg) +static inline int +ireg_seg_limit_low(x86seg *seg) { - if (seg == &cpu_state.seg_cs) - return IREG_CS_limit_low; - if (seg == &cpu_state.seg_ds) - return IREG_DS_limit_low; - if (seg == &cpu_state.seg_es) - return IREG_ES_limit_low; - if (seg == &cpu_state.seg_fs) - return IREG_FS_limit_low; - if (seg == &cpu_state.seg_gs) - return IREG_GS_limit_low; - if (seg == &cpu_state.seg_ss) - return IREG_SS_limit_low; - fatal("ireg_seg_limit_low : unknown segment\n"); - return 0; + if (seg == &cpu_state.seg_cs) + return IREG_CS_limit_low; + if (seg == &cpu_state.seg_ds) + return IREG_DS_limit_low; + if (seg == &cpu_state.seg_es) + return IREG_ES_limit_low; + if (seg == &cpu_state.seg_fs) + return IREG_FS_limit_low; + if (seg == &cpu_state.seg_gs) + return IREG_GS_limit_low; + if (seg == &cpu_state.seg_ss) + return IREG_SS_limit_low; + fatal("ireg_seg_limit_low : unknown segment\n"); + return 0; } -static inline int ireg_seg_limit_high(x86seg *seg) +static inline int +ireg_seg_limit_high(x86seg *seg) { - if (seg == &cpu_state.seg_cs) - return IREG_CS_limit_high; - if (seg == &cpu_state.seg_ds) - return IREG_DS_limit_high; - if (seg == &cpu_state.seg_es) - return IREG_ES_limit_high; - if (seg == &cpu_state.seg_fs) - return IREG_FS_limit_high; - if (seg == &cpu_state.seg_gs) - return IREG_GS_limit_high; - if (seg == &cpu_state.seg_ss) - return IREG_SS_limit_high; - fatal("ireg_seg_limit_high : unknown segment\n"); - return 0; + if (seg == &cpu_state.seg_cs) + return IREG_CS_limit_high; + if (seg == &cpu_state.seg_ds) + return IREG_DS_limit_high; + if (seg == &cpu_state.seg_es) + return IREG_ES_limit_high; + if (seg == &cpu_state.seg_fs) + return IREG_FS_limit_high; + if (seg == &cpu_state.seg_gs) + return IREG_GS_limit_high; + if (seg == &cpu_state.seg_ss) + return IREG_SS_limit_high; + fatal("ireg_seg_limit_high : unknown segment\n"); + return 0; } extern uint8_t reg_last_version[IREG_COUNT]; @@ -279,18 +281,18 @@ extern uint8_t reg_last_version[IREG_COUNT]; apparently required or not. Do not optimise out.*/ #define REG_FLAGS_REQUIRED (1 << 0) /*This register and the parent uOP have been optimised out.*/ -#define REG_FLAGS_DEAD (1 << 1) +#define REG_FLAGS_DEAD (1 << 1) typedef struct { - /*Refcount of pending reads on this register version*/ - uint8_t refcount; - /*Flags*/ - uint8_t flags; - /*uOP that generated this register version*/ - uint16_t parent_uop; - /*Pointer to next register version in dead register list*/ - uint16_t next; + /*Refcount of pending reads on this register version*/ + uint8_t refcount; + /*Flags*/ + uint8_t flags; + /*uOP that generated this register version*/ + uint16_t parent_uop; + /*Pointer to next register version in dead register list*/ + uint16_t next; } reg_version_t; extern reg_version_t reg_version[IREG_COUNT][256]; @@ -299,16 +301,17 @@ extern reg_version_t reg_version[IREG_COUNT][256]; can be optimised out*/ extern uint16_t reg_dead_list; -static inline void add_to_dead_list(reg_version_t *regv, int reg, int version) +static inline void +add_to_dead_list(reg_version_t *regv, int reg, int version) { - regv->next = reg_dead_list; - reg_dead_list = version | (reg << 8); + regv->next = reg_dead_list; + reg_dead_list = version | (reg << 8); } typedef struct { - uint16_t reg; - uint16_t version; + uint16_t reg; + uint16_t version; } ir_reg_t; extern ir_reg_t invalid_ir_reg; @@ -317,80 +320,81 @@ typedef uint16_t ir_host_reg_t; extern int max_version_refcount; -#define REG_VERSION_MAX 250 +#define REG_VERSION_MAX 250 #define REG_REFCOUNT_MAX 250 -static inline ir_reg_t codegen_reg_read(int reg) +static inline ir_reg_t +codegen_reg_read(int reg) { - ir_reg_t ireg; - reg_version_t *version; + ir_reg_t ireg; + reg_version_t *version; #ifndef RELEASE_BUILD - if (IREG_GET_REG(reg) == IREG_INVALID) - fatal("codegen_reg_read - IREG_INVALID\n"); + if (IREG_GET_REG(reg) == IREG_INVALID) + fatal("codegen_reg_read - IREG_INVALID\n"); #endif - ireg.reg = reg; - ireg.version = reg_last_version[IREG_GET_REG(reg)]; - version = ®_version[IREG_GET_REG(ireg.reg)][ireg.version]; - version->flags = 0; - version->refcount++; + ireg.reg = reg; + ireg.version = reg_last_version[IREG_GET_REG(reg)]; + version = ®_version[IREG_GET_REG(ireg.reg)][ireg.version]; + version->flags = 0; + version->refcount++; #ifndef RELEASE_BUILD - if (!version->refcount) - fatal("codegen_reg_read - refcount overflow\n"); - else + if (!version->refcount) + fatal("codegen_reg_read - refcount overflow\n"); + else #endif if (version->refcount > REG_REFCOUNT_MAX) - CPU_BLOCK_END(); - if (version->refcount > max_version_refcount) - max_version_refcount = version->refcount; -// pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]); - return ireg; + CPU_BLOCK_END(); + if (version->refcount > max_version_refcount) + max_version_refcount = version->refcount; + // pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]); + return ireg; } int reg_is_native_size(ir_reg_t ir_reg); -static inline ir_reg_t codegen_reg_write(int reg, int uop_nr) +static inline ir_reg_t +codegen_reg_write(int reg, int uop_nr) { - ir_reg_t ireg; - int last_version = reg_last_version[IREG_GET_REG(reg)]; - reg_version_t *version; + ir_reg_t ireg; + int last_version = reg_last_version[IREG_GET_REG(reg)]; + reg_version_t *version; #ifndef RELEASE_BUILD - if (IREG_GET_REG(reg) == IREG_INVALID) - fatal("codegen_reg_write - IREG_INVALID\n"); + if (IREG_GET_REG(reg) == IREG_INVALID) + fatal("codegen_reg_write - IREG_INVALID\n"); #endif - ireg.reg = reg; - ireg.version = last_version + 1; + ireg.reg = reg; + ireg.version = last_version + 1; - if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount && - !(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED)) - { - if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/ - add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version); - } + if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount && !(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED)) { + if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/ + add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version); + } - reg_last_version[IREG_GET_REG(reg)]++; + reg_last_version[IREG_GET_REG(reg)]++; #ifndef RELEASE_BUILD - if (!reg_last_version[IREG_GET_REG(reg)]) - fatal("codegen_reg_write - version overflow\n"); - else + if (!reg_last_version[IREG_GET_REG(reg)]) + fatal("codegen_reg_write - version overflow\n"); + else #endif if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) - CPU_BLOCK_END(); - if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount) - max_version_refcount = reg_last_version[IREG_GET_REG(reg)]; + CPU_BLOCK_END(); + if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount) + max_version_refcount = reg_last_version[IREG_GET_REG(reg)]; - version = ®_version[IREG_GET_REG(reg)][ireg.version]; - version->refcount = 0; - version->flags = 0; - version->parent_uop = uop_nr; -// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK); - return ireg; + version = ®_version[IREG_GET_REG(reg)][ireg.version]; + version->refcount = 0; + version->flags = 0; + version->parent_uop = uop_nr; + // pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK); + return ireg; } -static inline int ir_reg_is_invalid(ir_reg_t ir_reg) +static inline int +ir_reg_is_invalid(ir_reg_t ir_reg) { - return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); + return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID); } struct ir_data_t; @@ -405,7 +409,7 @@ void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block); void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c); #ifdef CODEGEN_BACKEND_HAS_MOV_IMM -int codegen_reg_is_loaded(ir_reg_t ir_reg); +int codegen_reg_is_loaded(ir_reg_t ir_reg); void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data); #endif