Renamed the three CPU folders to their final names.

This commit is contained in:
OBattler
2020-06-13 10:53:11 +02:00
parent dc7983902e
commit 395537070b
36 changed files with 32685 additions and 0 deletions

36
src/codegen/codegen.c Normal file
View File

@@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include "cpu.h"
#include "x86_ops.h"
#include "codegen.h"
void (*codegen_timing_start)();
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*codegen_timing_block_start)();
void (*codegen_timing_block_end)();
int (*codegen_timing_jump_cycles)();
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;
}
int codegen_in_recompile;
/* This is for compatibility with new x87 code. */
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);
}

413
src/codegen/codegen.h Normal file
View File

@@ -0,0 +1,413 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Definitions for the code generator.
*
*
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef _CODEGEN_H_
#define _CODEGEN_H_
#include <86box/mem.h>
#include "x86_ops.h"
#ifdef __amd64__
#include "codegen_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64
#include "codegen_x86.h"
#else
#error Dynamic recompiler not implemented on your platform
#endif
/*Handling self-modifying code (of which there is a lot on x86) :
PCem tracks a 'dirty mask' for each physical page, in which each bit
represents 64 bytes. This is only tracked for pages that have code in - when a
page first has a codeblock generated, it is evicted from the writelookup and
added to the page_lookup for this purpose. When in the page_lookup, each write
will go through the mem_write_ram*_page() functions and set the dirty mask
appropriately.
Each codeblock also contains a code mask (actually two masks, one for each
page the block is/may be in), again with each bit representing 64 bytes.
Each page has a list of codeblocks present in it. As each codeblock can span
up to two pages, two lists are present.
When a codeblock is about to be executed, the code masks are compared with the
dirty masks for the relevant pages. If either intersect, then
codegen_check_flush() is called on the affected page(s), and all affected
blocks are evicted.
The 64 byte granularity appears to work reasonably well for most cases,
avoiding most unnecessary evictions (eg when code & data are stored in the
same page).
*/
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;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
struct codeblock_t *parent, *left, *right;
int pnt;
int ins;
int valid;
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;
uint8_t data[2048];
} codeblock_t;
/*Code block uses FPU*/
#define CODEBLOCK_HAS_FPU 1
/*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)
{
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;
}
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
old_block->right = new_block;
new_block->parent = old_block;
new_block->left = new_block->right = NULL;
}
}
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
extern codeblock_t *codeblock;
extern codeblock_t **codeblock_hash;
void codegen_init();
void codegen_reset();
void codegen_block_init(uint32_t phys_addr);
void codegen_block_remove();
void codegen_block_start_recompile(codeblock_t *block);
void codegen_block_end_recompile(codeblock_t *block);
void codegen_block_end();
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
void codegen_generate_seg_restore();
void codegen_set_op32();
void codegen_flush();
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr);
extern int cpu_block_end;
extern uint32_t codegen_endpc;
extern int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
extern int cpu_recomp_flushes, cpu_recomp_flushes_latched;
extern int cpu_recomp_evicted, cpu_recomp_evicted_latched;
extern int cpu_recomp_reuse, cpu_recomp_reuse_latched;
extern int cpu_recomp_removed, cpu_recomp_removed_latched;
extern int codegen_block_cycles;
extern void (*codegen_timing_start)();
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
extern void (*codegen_timing_block_start)();
extern void (*codegen_timing_block_end)();
extern int (*codegen_timing_jump_cycles)();
typedef struct codegen_timing_t
{
void (*start)();
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 (*block_end)();
int (*jump_cycles)();
} codegen_timing_t;
extern codegen_timing_t codegen_timing_pentium;
extern codegen_timing_t codegen_timing_686;
extern codegen_timing_t codegen_timing_486;
extern codegen_timing_t codegen_timing_winchip;
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;
extern int block_pos;
#define CPU_BLOCK_END() cpu_block_end = 1
static inline void addbyte(uint8_t val)
{
codeblock[block_current].data[block_pos++] = val;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
}
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();
}
}
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();
}
}
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();
}
}
/*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 uint32_t op_old_pc;
/*Set to 1 if flags have been changed in the block being recompiled, and hence
flags_op is known and can be relied on */
extern int codegen_flags_changed;
extern int codegen_fpu_entered;
extern int codegen_mmx_entered;
extern int codegen_fpu_loaded_iq[8];
extern int codegen_reg_loaded[8];
extern int codegen_in_recompile;
#endif

View File

@@ -0,0 +1,13 @@
enum
{
ACCREG_ins = 0,
ACCREG_cycles = 1,
ACCREG_COUNT
};
struct ir_data_t;
void codegen_accumulate(int acc_reg, int delta);
void codegen_accumulate_flush(void);
void codegen_accumulate_reset();

View File

@@ -0,0 +1,50 @@
#include <stdint.h>
#include <stdio.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "codegen.h"
#include "codegen_accumulate.h"
static struct
{
int count;
uintptr_t dest_reg;
} acc_regs[] =
{
[ACCREG_ins] = {0, (uintptr_t) &(ins)},
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)},
};
void codegen_accumulate(int acc_reg, int delta)
{
acc_regs[acc_reg].count += delta;
}
void codegen_accumulate_flush(void)
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
{
if (acc_regs[c].count)
{
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t) acc_regs[c].dest_reg);
addlong(acc_regs[c].count);
}
acc_regs[c].count = 0;
}
}
void codegen_accumulate_reset()
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
acc_regs[c].count = 0;
}

View File

@@ -0,0 +1,49 @@
#include <stdint.h>
#include <stdio.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "codegen.h"
#include "codegen_accumulate.h"
static struct
{
int count;
uintptr_t dest_reg;
} acc_regs[] =
{
[ACCREG_ins] = {0, (uintptr_t) &(ins)},
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)},
};
void codegen_accumulate(int acc_reg, int delta)
{
acc_regs[acc_reg].count += delta;
}
void codegen_accumulate_flush(void)
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
{
if (acc_regs[c].count)
{
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
addbyte(0x05);
addlong((uint32_t) acc_regs[c].dest_reg);
addlong(acc_regs[c].count);
}
acc_regs[c].count = 0;
}
}
void codegen_accumulate_reset()
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
acc_regs[c].count = 0;
}

598
src/codegen/codegen_ops.c Normal file
View File

@@ -0,0 +1,598 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x86_flags.h"
#include "x87.h"
#include "386_common.h"
#include "cpu.h"
#include "codegen.h"
#include "codegen_ops.h"
#ifdef __amd64__
#include "codegen_ops_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64
#include "codegen_ops_x86.h"
#endif
#include "codegen_ops_arith.h"
#include "codegen_ops_fpu.h"
#include "codegen_ops_jump.h"
#include "codegen_ops_logic.h"
#include "codegen_ops_misc.h"
#include "codegen_ops_mmx.h"
#include "codegen_ops_mov.h"
#include "codegen_ops_shift.h"
#include "codegen_ops_stack.h"
#include "codegen_ops_xchg.h"
RecompOpFn recomp_opcodes[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16,
/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL,
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
/*40*/ ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw,
/*50*/ ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_w, ropMOV_seg_w, NULL,
/*90*/ ropNOP, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES, ropLDS, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32,
/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL,
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
/*40*/ ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl,
/*50*/ ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_w_seg, ropLEA_l, ropMOV_seg_w, NULL,
/*90*/ ropNOP, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES, ropLDS, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32
};
RecompOpFn recomp_opcodes_0f[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_mm_l, ropMOVQ_mm_q,
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm,
/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
};
RecompOpFn recomp_opcodes_d8[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
};
RecompOpFn recomp_opcodes_d9[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_da[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_db[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_dc[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
};
RecompOpFn recomp_opcodes_dd[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_de[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
};
RecompOpFn recomp_opcodes_df[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_REPE[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_REPNE[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};

46
src/codegen/codegen_ops.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef _CODEGEN_OPS_H_
#define _CODEGEN_OPS_H_
#include "codegen.h"
typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block);
extern RecompOpFn recomp_opcodes[512];
extern RecompOpFn recomp_opcodes_0f[512];
extern RecompOpFn recomp_opcodes_d8[512];
extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_da[512];
extern RecompOpFn recomp_opcodes_db[512];
extern RecompOpFn recomp_opcodes_dc[512];
extern RecompOpFn recomp_opcodes_dd[512];
extern RecompOpFn recomp_opcodes_de[512];
extern RecompOpFn recomp_opcodes_df[512];
extern RecompOpFn recomp_opcodes_REPE[512];
extern RecompOpFn recomp_opcodes_REPNE[512];
#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_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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,645 @@
static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FXCH(opcode & 7);
return op_pc;
}
static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FLD(opcode & 7);
return op_pc;
}
static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FST(opcode & 7);
return op_pc;
}
static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FST(opcode & 7);
FP_POP();
return op_pc;
}
static uint32_t ropFLDs(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);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_LOAD_S();
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)
{
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);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_D();
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)
{
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);
MEM_LOAD_ADDR_EA_W(target_seg);
FP_LOAD_IW();
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)
{
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);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_LOAD_IL();
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)
{
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);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_IQ();
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 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)
{
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG(0);
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);
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)
{
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_LOAD_REG_D(0, &host_reg1, &host_reg2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
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)
{
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
return new_pc;
}
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);
FP_POP();
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; \
}
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(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(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(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(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(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(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(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; \
}
ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S);
ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D);
ropFcompare(COM, iw, MEM_LOAD_ADDR_EA_W, FP_COMPARE_IW);
ropFcompare(COM, il, MEM_LOAD_ADDR_EA_L, FP_COMPARE_IL);
/*static uint32_t ropFADDs(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);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_ADD);
return op_pc + 1;
}
static uint32_t ropFDIVs(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);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_DIV);
return op_pc + 1;
}
static uint32_t ropFMULs(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);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_MUL);
return op_pc + 1;
}
static uint32_t ropFSUBs(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);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_SUB);
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)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, 0, opcode & 7);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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);
return op_pc;
}
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();
return op_pc;
}
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();
return op_pc;
}
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();
return op_pc;
}
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();
return op_pc;
}
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();
return op_pc;
}
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();
return op_pc;
}
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();
return op_pc;
}
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();
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)
{
int host_reg;
FP_ENTER();
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
return op_pc;
}
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;
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);
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);
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)
{
x86seg *target_seg;
int host_reg;
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);
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);
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)
{
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
return new_pc;
}
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);
FP_POP();
return new_pc;
}
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;
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);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
FP_POP();
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)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
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_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
UPDATE_NPXC(0);
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)
{
int host_reg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
CHECK_SEG_WRITE(target_seg);
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
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)
{
FP_ENTER();
FP_FCHS();
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(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)
{
FP_ENTER();
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
return op_pc;
}

View File

@@ -0,0 +1,270 @@
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
return -1;
}
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
return -1;
}
static uint32_t ropJMP_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);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
return -1;
}
static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
if (op_32 & 0x200)
{
int host_reg = LOAD_REG_L(REG_ECX);
TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
}
else
{
int host_reg = LOAD_REG_W(REG_CX);
TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
}
return op_pc+1;
}
static uint32_t ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
if (op_32 & 0x200)
{
int host_reg = LOAD_REG_L(REG_ECX);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_REG_L_RELEASE(host_reg);
TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
}
else
{
int host_reg = LOAD_REG_W(REG_CX);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_REG_W_RELEASE(host_reg);
TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
}
return op_pc+1;
}
static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC((uintptr_t)CF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static void BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
int host_reg;
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
if (not)
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_UNKNOWN:
CALL_FUNC((uintptr_t)ZF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
break;
}
}
static void BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC((uintptr_t)VF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static void BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC((uintptr_t)PF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static void BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
int host_reg;
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:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x80);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
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:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x8000);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
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:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x80000000);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_UNKNOWN:
CALL_FUNC((uintptr_t)NF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
break;
}
}
#define ropBRANCH(name, func, not) \
static uint32_t rop ## name(uint8_t opcode, uint32_t fetchdat, \
uint32_t op_32, uint32_t op_pc, \
codeblock_t *block) \
{ \
uint32_t offset = fetchdat & 0xff; \
\
if (offset & 0x80) \
offset |= 0xffffff00; \
\
func(1, op_pc, offset, not); \
\
return op_pc+1; \
} \
static uint32_t rop ## name ## _w(uint8_t opcode, \
uint32_t fetchdat, uint32_t op_32, \
uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t offset = fetchdat & 0xffff; \
\
if (offset & 0x8000) \
offset |= 0xffff0000; \
\
func(2, op_pc, offset, not); \
\
return op_pc+2; \
} \
static uint32_t rop ## name ## _l(uint8_t opcode, \
uint32_t fetchdat, uint32_t op_32, \
uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t offset = fastreadl(cs + op_pc); \
\
func(4, op_pc, offset, not); \
\
return op_pc+4; \
}
ropBRANCH(JB, BRANCH_COND_B, 0)
ropBRANCH(JNB, BRANCH_COND_B, 1)
ropBRANCH(JE, BRANCH_COND_E, 0)
ropBRANCH(JNE, BRANCH_COND_E, 1)
ropBRANCH(JO, BRANCH_COND_O, 0)
ropBRANCH(JNO, BRANCH_COND_O, 1)
ropBRANCH(JP, BRANCH_COND_P, 0)
ropBRANCH(JNP, BRANCH_COND_P, 1)
ropBRANCH(JS, BRANCH_COND_S, 0)
ropBRANCH(JNS, BRANCH_COND_S, 1)
ropBRANCH(JL, BRANCH_COND_L, 0)
ropBRANCH(JNL, BRANCH_COND_L, 1)
ropBRANCH(JLE, BRANCH_COND_LE, 0)
ropBRANCH(JNLE, BRANCH_COND_LE, 1)
ropBRANCH(JBE, BRANCH_COND_BE, 0)
ropBRANCH(JNBE, BRANCH_COND_BE, 1)

View File

@@ -0,0 +1,564 @@
#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)
{
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);
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);
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;
}

View File

@@ -0,0 +1,269 @@
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
return op_pc;
}
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;
}
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;
}
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);
return op_pc;
}
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;
}
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;
if ((fetchdat & 0x30) != 0x00)
return 0;
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);
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;
}
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;
}
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)
{
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;
}
return 0;
}
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;
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;
}

View File

@@ -0,0 +1,277 @@
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;
MMX_ENTER();
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);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
}
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)
{
MMX_ENTER();
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);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
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);
}
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)
{
int host_reg;
MMX_ENTER();
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);
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);
}
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)
{
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);
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_MMX_LQ((fetchdat >> 3) & 7, 0);
}
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) \
{ \
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); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
\
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); \
} \
xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \
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(ropPANDN, MMX_ANDN)
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(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(ropPUNPCKHBW, MMX_PUNPCKHBW);
MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD);
MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ);
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
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(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)
{
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;
}

View File

@@ -0,0 +1,656 @@
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);
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)
{
STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff);
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)
{
fetchdat = fastreadl(cs + op_pc);
STORE_IMM_REG_L(opcode & 7, fetchdat);
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)
{
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);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
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);
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
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; \
}
ropLseg(DS, cpu_state.seg_ds)
ropLseg(ES, cpu_state.seg_es)
ropLseg(FS, cpu_state.seg_fs)
ropLseg(GS, cpu_state.seg_gs)
ropLseg(SS, cpu_state.seg_ss)

View File

@@ -0,0 +1,125 @@
#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)
{
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
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)
{
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
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)
{
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
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)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
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)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
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)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
return op_pc + 1;
}

View File

@@ -0,0 +1,269 @@
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;
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;
}
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;
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;
}
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;
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;
}
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;
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;
}
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;
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);
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)
{
uint32_t imm = fetchdat & 0xff;
int host_reg;
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);
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)
{
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;
}
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);
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)
{
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;
}
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);
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)
{
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);
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)
{
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);
return -1;
}
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;
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;
}
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;
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;
}
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;
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;
}
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;
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;
}
#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)
ROP_PUSH_SEG(ES)
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; \
}
ROP_POP_SEG(DS, cpu_state.seg_ds)
ROP_POP_SEG(ES, cpu_state.seg_es)
ROP_POP_SEG(FS, cpu_state.seg_fs)
ROP_POP_SEG(GS, cpu_state.seg_gs)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
#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)
OP_XCHG_AX_(DX)
OP_XCHG_AX_(SI)
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; \
}
OP_XCHG_EAX_(EBX)
OP_XCHG_EAX_(ECX)
OP_XCHG_EAX_(EDX)
OP_XCHG_EAX_(ESI)
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)
{
/* #ifdef __amd64__
return 0;
#else */
int src_reg, dst_reg, temp_reg;
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);
return op_pc + 1;
/* #endif */
}
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;
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);
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)
{
int src_reg, dst_reg, temp_reg;
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);
return op_pc + 1;
}

View File

@@ -0,0 +1,421 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ops.h"
#include "codegen_timing_common.h"
#define CYCLES(c) (int *)c
#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8))
static int *opcode_timings[256] =
{
/*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm, &timing_rm, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_mod3[256] =
{
/*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_0f[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, &timing_rm,
/*70*/ NULL, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rm, &timing_rm,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL,
};
static int *opcode_timings_0f_mod3[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, &timing_rr,
/*70*/ NULL, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rr, &timing_rr,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL,
};
static int *opcode_timings_shift[8] =
{
CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
};
static int *opcode_timings_shift_mod3[8] =
{
CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
};
static int *opcode_timings_f6[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f6_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f7[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_f7_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_ff[8] =
{
&timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_ff_mod3[8] =
{
&timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_d8[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/
CYCLES(8), CYCLES(16), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_d9[8] =
{
/* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/
CYCLES(3), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3)
};
static int *opcode_timings_d9_mod3[64] =
{
/*FLD*/
CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4),
/*FXCH*/
CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4),
/*FNOP*/
CYCLES(3), NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*FSTP*/
CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/* opFCHS opFABS opFTST opFXAM*/
CYCLES(6), CYCLES(3), NULL, NULL, CYCLES(4), CYCLES(8), NULL, NULL,
/* opFLD1 opFLDL2T opFLDL2E opFLDPI opFLDEG2 opFLDLN2 opFLDZ*/
CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(8), CYCLES(8), CYCLES(8), CYCLES(4), NULL,
/* opF2XM1 opFYL2X opFPTAN opFPATAN opFDECSTP opFINCSTP,*/
CYCLES(140), CYCLES(196), CYCLES(200), CYCLES(218), NULL, NULL, CYCLES(3), CYCLES(3),
/* opFPREM opFSQRT opFSINCOS opFRNDINT opFSCALE opFSIN opFCOS*/
CYCLES(70), NULL, CYCLES(83), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(257), CYCLES(257)
};
static int *opcode_timings_da[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_da_mod3[8] =
{
NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL
};
static int *opcode_timings_db[8] =
{
/* FLDil FSTil FSTPil FLDe FSTPe*/
CYCLES(9), NULL, CYCLES(28), CYCLES(28), NULL, CYCLES(5), NULL, CYCLES(6)
};
static int *opcode_timings_db_mod3[64] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* opFNOP opFCLEX opFINIT opFNOP opFNOP*/
NULL, CYCLES(3), CYCLES(7), CYCLES(17), CYCLES(3), CYCLES(3), NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static int *opcode_timings_dc[8] =
{
/* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_dc_mod3[8] =
{
/* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/
CYCLES(8), CYCLES(16), NULL, NULL, CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_dd[8] =
{
/* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/
CYCLES(3), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(3)
};
static int *opcode_timings_dd_mod3[8] =
{
/* FFFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL
};
static int *opcode_timings_de[8] =
{
/* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_de_mod3[8] =
{
/* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/
CYCLES(8), CYCLES(16), NULL, CYCLES(5), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_df[8] =
{
/* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/
CYCLES(13), NULL, CYCLES(29), CYCLES(29), NULL, CYCLES(10), CYCLES(172), CYCLES(28)
};
static int *opcode_timings_df_mod3[8] =
{
/* FFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL
};
static int *opcode_timings_8x[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_8x_mod3[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_81[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_81_mod3[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int timing_count;
static uint8_t last_prefix;
static uint32_t regmask_modified;
static inline int COUNT(int *c, int op_32)
{
if ((uintptr_t)c <= 10000)
return (int)(uintptr_t)c;
if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff))
{
if (op_32 & 0x100)
return ((uintptr_t)c >> 8) & 0xff;
return (uintptr_t)c & 0xff;
}
return *c;
}
void codegen_timing_486_block_start()
{
regmask_modified = 0;
}
void codegen_timing_486_start()
{
timing_count = 0;
last_prefix = 0;
}
void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat)
{
timing_count += COUNT(opcode_timings[prefix], 0);
last_prefix = prefix;
}
void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc)
{
int **timings;
uint64_t *deps;
int mod3 = ((fetchdat & 0xc0) == 0xc0);
int bit8 = !(opcode & 1);
switch (last_prefix)
{
case 0x0f:
timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f;
break;
case 0xd8:
timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8;
opcode = (opcode >> 3) & 7;
break;
case 0xd9:
timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xda:
timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da;
opcode = (opcode >> 3) & 7;
break;
case 0xdb:
timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xdc:
timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc;
opcode = (opcode >> 3) & 7;
break;
case 0xdd:
timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd;
opcode = (opcode >> 3) & 7;
break;
case 0xde:
timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de;
opcode = (opcode >> 3) & 7;
break;
case 0xdf:
timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df;
opcode = (opcode >> 3) & 7;
break;
default:
switch (opcode)
{
case 0x80: case 0x82: case 0x83:
timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x;
deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x;
opcode = (fetchdat >> 3) & 7;
break;
case 0x81:
timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81;
deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81;
opcode = (fetchdat >> 3) & 7;
break;
case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3:
timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf6:
timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf7:
timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7;
opcode = (fetchdat >> 3) & 7;
break;
case 0xff:
timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff;
opcode = (fetchdat >> 3) & 7;
break;
default:
timings = mod3 ? opcode_timings_mod3 : opcode_timings;
deps = mod3 ? opcode_deps_mod3 : opcode_deps;
break;
}
}
timing_count += COUNT(timings[opcode], op_32);
if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32))
timing_count++; /*AGI stall*/
codegen_block_cycles += timing_count;
regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8);
}
void codegen_timing_486_block_end()
{
}
codegen_timing_t codegen_timing_486 =
{
codegen_timing_486_start,
codegen_timing_486_prefix,
codegen_timing_486_opcode,
codegen_timing_486_block_start,
codegen_timing_486_block_end,
NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,850 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "codegen_timing_common.h"
uint64_t opcode_deps[256] =
{
/* ADD ADD ADD ADD*/
/*00*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* ADD ADD PUSH ES POP ES*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
/* OR OR OR OR*/
SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* OR OR PUSH CS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, 0,
/* ADC ADC ADC ADC*/
/*10*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* ADC ADC PUSH SS POP SS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
/* SBB SBB SBB SBB*/
SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* SBB SBB PUSH DS POP DS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
/* AND AND AND AND*/
/*20*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* AND AND DAA*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
/* SUB SUB SUB SUB*/
SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* SUB SUB DAS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
/* XOR XOR XOR XOR*/
/*30*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* XOR XOR AAA*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
/* CMP CMP CMP CMP*/
SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM,
/* CMP CMP AAS*/
SRCDEP_EAX, SRCDEP_EAX, 0, SRCDEP_EAX | DSTDEP_EAX,
/* INC EAX INC ECX INC EDX INC EBX*/
/*40*/ SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX,
/* INC ESP INC EBP INC ESI INC EDI*/
SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI,
/* DEC EAX DEC ECX DEC EDX DEC EBX*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX,
/* DEC ESP DEC EBP DEC ESI DEC EDI*/
SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI,
/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/
/*50*/ SRCDEP_EAX | IMPL_ESP, SRCDEP_ECX | IMPL_ESP, SRCDEP_EDX | IMPL_ESP, SRCDEP_EBX | IMPL_ESP,
/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/
SRCDEP_ESP | IMPL_ESP, SRCDEP_EBP | IMPL_ESP, SRCDEP_ESI | IMPL_ESP, SRCDEP_EDI | IMPL_ESP,
/* POP EAX POP ECX POP EDX POP EBX*/
DSTDEP_EAX | IMPL_ESP, DSTDEP_ECX | IMPL_ESP, DSTDEP_EDX | IMPL_ESP, DSTDEP_EBX | IMPL_ESP,
/* POP ESP POP EBP POP ESI POP EDI*/
DSTDEP_ESP | IMPL_ESP, DSTDEP_EBP | IMPL_ESP, DSTDEP_ESI | IMPL_ESP, DSTDEP_EDI | IMPL_ESP,
/* PUSHA POPA BOUND ARPL*/
/*60*/ IMPL_ESP, IMPL_ESP, 0, 0,
0, 0, 0, 0,
/* PUSH imm IMUL PUSH imm IMUL*/
IMPL_ESP, DSTDEP_REG | MODRM, IMPL_ESP, DSTDEP_REG | MODRM,
/* INSB INSW OUTSB OUTSW*/
0, 0, 0, 0,
/* Jxx*/
/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*80*/ 0, 0, 0, 0,
/* TEST TEST XCHG XCHG*/
SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
/* MOV MOV MOV MOV*/
SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_REG | MODRM,
/* MOV from seg LEA MOV to seg POP*/
MODRM, DSTDEP_REG | MODRM, MODRM, IMPL_ESP | MODRM,
/* NOP XCHG XCHG XCHG*/
/*90*/ 0, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBX | DSTDEP_EBX,
/* XCHG XCHG XCHG XCHG*/
SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBP | DSTDEP_EBP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDI | DSTDEP_EDI,
/* CBW CWD CALL far WAIT*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EDX, 0, 0,
/* PUSHF POPF SAHF LAHF*/
IMPL_ESP, IMPL_ESP, SRCDEP_EAX, DSTDEP_EAX,
/* MOV MOV MOV MOV*/
/*a0*/ DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX,
/* MOVSB MOVSW CMPSB CMPSW*/
0, 0, 0, 0,
/* TEST TEST STOSB STOSW*/
SRCDEP_EAX, SRCDEP_EAX, 0, 0,
/* LODSB LODSW SCASB SCASW*/
0, 0, 0, 0,
/* MOV*/
/*b0*/ DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
DSTDEP_ESP, DSTDEP_EBP, DSTDEP_ESI, DSTDEP_EDI,
/* RET imm RET*/
/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP,
/* LES LDS MOV MOV*/
DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, MODRM, MODRM,
/* ENTER LEAVE RETF RETF*/
IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP,
/* INT3 INT INTO IRET*/
0, 0, 0, 0,
/*d0*/ 0, 0, 0, 0,
/* AAM AAD SETALC XLAT*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX | SRCDEP_EBX,
0, 0, 0, 0,
0, 0, 0, 0,
/* LOOPNE LOOPE LOOP JCXZ*/
/*e0*/ SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX,
/* IN AL IN AX OUT_AL OUT_AX*/
DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX,
/* CALL JMP JMP JMP*/
IMPL_ESP, 0, 0, 0,
/* IN AL IN AX OUT_AL OUT_AX*/
SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | SRCDEP_EAX, SRCDEP_EDX | SRCDEP_EAX,
/* REPNE REPE*/
/*f0*/ 0, 0, 0, 0,
/* HLT CMC*/
0, 0, 0, 0,
/* CLC STC CLI STI*/
0, 0, 0, 0,
/* CLD STD INCDEC*/
0, 0, MODRM, 0
};
uint64_t opcode_deps_mod3[256] =
{
/* ADD ADD ADD ADD*/
/*00*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* ADD ADD PUSH ES POP ES*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
/* OR OR OR OR*/
SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* OR OR PUSH CS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, 0,
/* ADC ADC ADC ADC*/
/*10*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* ADC ADC PUSH SS POP SS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
/* SBB SBB SBB SBB*/
SRCDEP_REG |SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* SBB SBB PUSH DS POP DS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
/* AND AND AND AND*/
/*20*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* AND AND DAA*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
/* SUB SUB SUB SUB*/
SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* SUB SUB DAS*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
/* XOR XOR XOR XOR*/
/*30*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* XOR XOR AAA*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
/* CMP CMP CMP CMP*/
SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM,
/* CMP CMP AAS*/
SRCDEP_EAX, SRCDEP_EAX, 0, SRCDEP_EAX | DSTDEP_EAX,
/* INC EAX INC ECX INC EDX INC EBX*/
/*40*/ SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX,
/* INC ESP INC EBP INC ESI INC EDI*/
SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI,
/* DEC EAX DEC ECX DEC EDX DEC EBX*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX,
/* DEC ESP DEC EBP DEC ESI DEC EDI*/
SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EBP | DSTDEP_EBP, SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EDI | DSTDEP_EDI,
/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/
/*50*/ SRCDEP_EAX | IMPL_ESP, SRCDEP_ECX | IMPL_ESP, SRCDEP_EDX | IMPL_ESP, SRCDEP_EBX | IMPL_ESP,
/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/
SRCDEP_ESP | IMPL_ESP, SRCDEP_EBP | IMPL_ESP, SRCDEP_ESI | IMPL_ESP, SRCDEP_EDI | IMPL_ESP,
/* POP EAX POP ECX POP EDX POP EBX*/
DSTDEP_EAX | IMPL_ESP, DSTDEP_ECX | IMPL_ESP, DSTDEP_EDX | IMPL_ESP, DSTDEP_EBX | IMPL_ESP,
/* POP ESP POP EBP POP ESI POP EDI*/
DSTDEP_ESP | IMPL_ESP, DSTDEP_EBP | IMPL_ESP, DSTDEP_ESI | IMPL_ESP, DSTDEP_EDI | IMPL_ESP,
/* PUSHA POPA BOUND ARPL*/
/*60*/ IMPL_ESP, IMPL_ESP, 0, 0,
0, 0, 0, 0,
/* PUSH imm IMUL PUSH imm IMUL*/
IMPL_ESP, DSTDEP_REG | SRCDEP_RM | MODRM, IMPL_ESP, DSTDEP_REG | SRCDEP_RM | MODRM,
/* INSB INSW OUTSB OUTSW*/
0, 0, 0, 0,
/* Jxx*/
/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*80*/ 0, 0, 0, 0,
/* TEST TEST XCHG XCHG*/
SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM,
/* MOV MOV MOV MOV*/
SRCDEP_REG | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_REG | MODRM, SRCDEP_RM | DSTDEP_REG | MODRM,
/* MOV from seg LEA MOV to seg POP*/
DSTDEP_RM | MODRM, DSTDEP_REG | MODRM, SRCDEP_RM | MODRM, IMPL_ESP | DSTDEP_RM | MODRM,
/* NOP XCHG XCHG XCHG*/
/*90*/ 0, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBX | DSTDEP_EBX,
/* XCHG XCHG XCHG XCHG*/
SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESP | DSTDEP_ESP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EBP | DSTDEP_EBP, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_ESI | DSTDEP_ESI, SRCDEP_EAX | DSTDEP_EAX | SRCDEP_EDI | DSTDEP_EDI,
/* CBW CWD CALL far WAIT*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EDX, 0, 0,
/* PUSHF POPF SAHF LAHF*/
IMPL_ESP, IMPL_ESP, SRCDEP_EAX, DSTDEP_EAX,
/* MOV MOV MOV MOV*/
/*a0*/ DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX,
/* MOVSB MOVSW CMPSB CMPSW*/
0, 0, 0, 0,
/* TEST TEST STOSB STOSW*/
SRCDEP_EAX, SRCDEP_EAX, 0, 0,
/* LODSB LODSW SCASB SCASW*/
0, 0, 0, 0,
/* MOV*/
/*b0*/ DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
DSTDEP_ESP, DSTDEP_EBP, DSTDEP_ESI, DSTDEP_EDI,
/* RET imm RET*/
/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP,
/* LES LDS MOV MOV*/
DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_RM | MODRM, DSTDEP_RM | MODRM,
/* ENTER LEAVE RETF RETF*/
IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP,
/* INT3 INT INTO IRET*/
0, 0, 0, 0,
/*d0*/ 0, 0, 0, 0,
/* AAM AAD SETALC XLAT*/
SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX | SRCDEP_EBX,
0, 0, 0, 0,
0, 0, 0, 0,
/* LOOPNE LOOPE LOOP JCXZ*/
/*e0*/ SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_ECX,
/* IN AL IN AX OUT_AL OUT_AX*/
DSTDEP_EAX, DSTDEP_EAX, SRCDEP_EAX, SRCDEP_EAX,
/* CALL JMP JMP JMP*/
IMPL_ESP, 0, 0, 0,
/* IN AL IN AX OUT_AL OUT_AX*/
SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | DSTDEP_EAX, SRCDEP_EDX | SRCDEP_EAX, SRCDEP_EDX | SRCDEP_EAX,
/* REPNE REPE*/
/*f0*/ 0, 0, 0, 0,
/* HLT CMC*/
0, 0, 0, 0,
/* CLC STC CLI STI*/
0, 0, 0, 0,
/* CLD STD INCDEC*/
0, 0, SRCDEP_RM | DSTDEP_RM | MODRM, 0
};
uint64_t opcode_deps_0f[256] =
{
/*00*/ MODRM, MODRM, MODRM, MODRM,
0, 0, 0, 0,
0, 0, 0, 0,
0, MODRM, 0, MODRM,
/*10*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*20*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, 0, 0,
0, 0, 0, 0,
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, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*60*/ MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
MODRM, MODRM, MODRM, MODRM,
MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
0, 0, MODRM, MODRM,
/*70*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
MODRM, MODRM, MODRM, 0,
0, 0, 0, 0,
0, 0, MODRM, MODRM,
/*80*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*90*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
/*a0*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, 0, 0,
MODRM, MODRM, 0, MODRM,
MODRM, MODRM, 0, MODRM,
/*b0*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
0, 0, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
/*c0*/ MODRM, MODRM, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*d0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
0, MODRM | MMX_MULTIPLY, 0, 0,
MODRM, MODRM, 0, MODRM,
MODRM, MODRM, 0, MODRM,
/*e0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0,
0, MODRM | MMX_MULTIPLY, 0, 0,
MODRM, MODRM, 0, MODRM,
MODRM, MODRM, 0, MODRM,
/*f0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
0, MODRM | MMX_MULTIPLY, 0, 0,
MODRM, MODRM, MODRM, 0,
MODRM, MODRM, MODRM, 0,
};
uint64_t opcode_deps_0f_mod3[256] =
{
/*00*/ MODRM, MODRM, MODRM, MODRM,
0, 0, 0, 0,
0, 0, 0, 0,
0, MODRM, 0, MODRM,
/*10*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*20*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, 0, 0,
0, 0, 0, 0,
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, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*60*/ MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
MODRM, MODRM, MODRM, MODRM,
MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
0, 0, MODRM, MODRM,
/*70*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
MODRM, MODRM, MODRM, 0,
0, 0, 0, 0,
0, 0, MODRM, MODRM,
/*80*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*90*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
/*a0*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, 0, 0,
MODRM, MODRM, 0, MODRM,
MODRM, MODRM, 0, MODRM,
/*b0*/ MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
0, 0, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
/*c0*/ MODRM, MODRM, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*d0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
0, MODRM | MMX_MULTIPLY, 0, 0,
MODRM, MODRM, 0, MODRM,
MODRM, MODRM, 0, MODRM,
/*e0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, 0,
0, MODRM | MMX_MULTIPLY, 0, 0,
MODRM, MODRM, 0, MODRM,
MODRM, MODRM, 0, MODRM,
/*f0*/ 0, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK, MODRM | MMX_SHIFTPACK,
0, MODRM | MMX_MULTIPLY, 0, 0,
MODRM, MODRM, MODRM, 0,
MODRM, MODRM, MODRM, 0,
};
uint64_t opcode_deps_0f0f[256] =
{
/*00*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, MODRM, 0, 0,
/*10*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, MODRM, 0, 0,
/*20*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
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, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
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,
/*80*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*90*/ MODRM, 0, 0, 0,
MODRM, 0, MODRM, MODRM,
0, 0, MODRM, 0,
0, 0, MODRM, 0,
/*a0*/ MODRM, 0, 0, 0,
MODRM, 0, MODRM, MODRM,
0, 0, 0, 0,
0, 0, 0, 0,
/*b0*/ MODRM, 0, 0, 0,
MODRM, 0, MODRM, MODRM,
0, 0, 0, 0,
0, 0, 0, MODRM,
/*c0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*d0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*e0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*f0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
};
uint64_t opcode_deps_0f0f_mod3[256] =
{
/*00*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, MODRM, 0, 0,
/*10*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, MODRM, 0, 0,
/*20*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
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, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
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,
/*80*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*90*/ MODRM, 0, 0, 0,
MODRM, 0, MODRM, MODRM,
0, 0, MODRM, 0,
0, 0, MODRM, 0,
/*a0*/ MODRM, 0, 0, 0,
MODRM, 0, MODRM, MODRM,
0, 0, 0, 0,
0, 0, 0, 0,
/*b0*/ MODRM, 0, 0, 0,
MODRM, 0, MODRM, MODRM,
0, 0, 0, 0,
0, 0, 0, MODRM,
/*c0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*d0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*e0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/*f0*/ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
};
uint64_t opcode_deps_shift[8] =
{
MODRM, MODRM, MODRM, MODRM,
MODRM, MODRM, MODRM, MODRM,
};
uint64_t opcode_deps_shift_mod3[8] =
{
SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM,
SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM,
};
uint64_t opcode_deps_shift_cl[8] =
{
MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX,
MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX, MODRM | SRCDEP_ECX,
};
uint64_t opcode_deps_shift_cl_mod3[8] =
{
SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX,
SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX, SRCDEP_RM | DSTDEP_RM | MODRM | SRCDEP_ECX,
};
uint64_t opcode_deps_f6[8] =
{
/* TST NOT NEG*/
MODRM, 0, MODRM, MODRM,
/* MUL IMUL DIV IDIV*/
SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM
};
uint64_t opcode_deps_f6_mod3[8] =
{
/* TST NOT NEG*/
SRCDEP_RM | MODRM, 0, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM,
/* MUL IMUL DIV IDIV*/
SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM
};
uint64_t opcode_deps_f7[8] =
{
/* TST NOT NEG*/
MODRM, 0, MODRM, MODRM,
/* MUL IMUL DIV IDIV*/
SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM
};
uint64_t opcode_deps_f7_mod3[8] =
{
/* TST NOT NEG*/
SRCDEP_RM | MODRM, 0, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM,
/* MUL IMUL DIV IDIV*/
SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | SRCDEP_RM | MODRM, SRCDEP_EAX | SRCDEP_EDX | DSTDEP_EAX | DSTDEP_EDX | MODRM
};
uint64_t opcode_deps_ff[8] =
{
/* INC DEC CALL CALL far*/
MODRM, MODRM, MODRM | IMPL_ESP, MODRM,
/* JMP JMP far PUSH*/
MODRM, MODRM, MODRM | IMPL_ESP, 0
};
uint64_t opcode_deps_ff_mod3[8] =
{
/* INC DEC CALL CALL far*/
SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM | IMPL_ESP, MODRM,
/* JMP JMP far PUSH*/
SRCDEP_RM | MODRM, MODRM, SRCDEP_RM | MODRM | IMPL_ESP, 0
};
uint64_t opcode_deps_d8[8] =
{
/* FADDs FMULs FCOMs FCOMPs*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_POP | FPU_READ_ST0 | MODRM,
/* FSUBs FSUBRs FDIVs FDIVRs*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM
};
uint64_t opcode_deps_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP*/
FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_READ_ST0 | FPU_READ_STREG, FPU_POP | FPU_READ_ST0 | FPU_READ_STREG,
/* FSUB FSUBR FDIV FDIVR*/
FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG, FPU_RW_ST0 | FPU_READ_STREG
};
uint64_t opcode_deps_d9[8] =
{
/* FLDs FSTs FSTPs*/
FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_POP | MODRM,
/* FLDENV FLDCW FSTENV FSTCW*/
MODRM, MODRM, MODRM, MODRM
};
uint64_t opcode_deps_d9_mod3[64] =
{
/*FLD*/
FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG,
FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG, FPU_PUSH | FPU_READ_STREG,
/*FXCH*/
FPU_FXCH, FPU_FXCH, FPU_FXCH, FPU_FXCH,
FPU_FXCH, FPU_FXCH, FPU_FXCH, FPU_FXCH,
/*FNOP*/
0, 0, 0, 0, 0, 0, 0, 0,
/*FSTP*/
FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP,
FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP,
/* opFCHS opFABS*/
0, 0, 0, 0,
/* opFTST opFXAM*/
0, 0, 0, 0,
/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/
FPU_PUSH, FPU_PUSH, FPU_PUSH, FPU_PUSH,
/* opFLDEG2 opFLDLN2 opFLDZ*/
FPU_PUSH, FPU_PUSH, FPU_PUSH, 0,
/* opF2XM1 opFYL2X opFPTAN opFPATAN*/
0, 0, 0, 0,
/* opFDECSTP opFINCSTP,*/
0, 0, 0, 0,
/* opFPREM opFSQRT opFSINCOS*/
0, 0, 0, 0,
/* opFRNDINT opFSCALE opFSIN opFCOS*/
0, 0, 0, 0
};
uint64_t opcode_deps_da[8] =
{
/* FIADDl FIMULl FICOMl FICOMPl*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM,
/* FISUBl FISUBRl FIDIVl FIDIVRl*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM
};
uint64_t opcode_deps_da_mod3[8] =
{
0, 0, 0, 0,
/* FCOMPP*/
0, FPU_POP2, 0, 0
};
uint64_t opcode_deps_db[8] =
{
/* FLDil FSTil FSTPil*/
FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM,
/* FLDe FSTPe*/
0, FPU_PUSH | MODRM, 0, FPU_READ_ST0 | FPU_POP | MODRM
};
uint64_t opcode_deps_db_mod3[64] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* opFNOP opFCLEX opFINIT*/
0, 0, 0, 0,
/* opFNOP opFNOP*/
0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
uint64_t opcode_deps_dc[8] =
{
/* FADDd FMULd FCOMd FCOMPd*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM,
/* FSUBd FSUBRd FDIVd FDIVRd*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM
};
uint64_t opcode_deps_dc_mod3[8] =
{
/* opFADDr opFMULr*/
FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, 0, 0,
/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/
FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG, FPU_READ_ST0 | FPU_RW_STREG
};
uint64_t opcode_deps_dd[8] =
{
/* FLDd FSTd FSTPd*/
FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM,
/* FRSTOR FSAVE FSTSW*/
MODRM, 0, MODRM, MODRM
};
uint64_t opcode_deps_dd_mod3[8] =
{
/* FFFREE FST FSTP*/
0, 0, FPU_READ_ST0 | FPU_WRITE_STREG, FPU_READ_ST0 | FPU_WRITE_STREG | FPU_POP,
/* FUCOM FUCOMP*/
FPU_READ_ST0 | FPU_READ_STREG, FPU_READ_ST0 | FPU_READ_STREG | FPU_POP, 0, 0
};
uint64_t opcode_deps_de[8] =
{
/* FIADDw FIMULw FICOMw FICOMPw*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM,
/* FISUBw FISUBRw FIDIVw FIDIVRw*/
FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM, FPU_RW_ST0 | MODRM
};
uint64_t opcode_deps_de_mod3[8] =
{
/* FADDP FMULP FCOMPP*/
FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, 0, FPU_READ_ST0 | FPU_READ_ST1 | FPU_POP2,
/* FSUBP FSUBRP FDIVP FDIVRP*/
FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP, FPU_READ_ST0 | FPU_RW_STREG | FPU_POP
};
uint64_t opcode_deps_df[8] =
{
/* FILDiw FISTiw FISTPiw*/
FPU_PUSH | MODRM, 0, FPU_READ_ST0 | MODRM, FPU_READ_ST0 | FPU_POP | MODRM,
/* FILDiq FBSTP FISTPiq*/
0, FPU_PUSH | MODRM, FPU_READ_ST0 | FPU_POP | MODRM, FPU_READ_ST0 | FPU_POP | MODRM
};
uint64_t opcode_deps_df_mod3[8] =
{
0, 0, 0, 0,
/* FSTSW AX*/
0, 0, 0, 0
};
uint64_t opcode_deps_81[8] =
{
MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632,
MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632
};
uint64_t opcode_deps_81_mod3[8] =
{
SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632,
SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | MODRM | HAS_IMM1632
};
uint64_t opcode_deps_8x[8] =
{
MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8,
MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8
};
uint64_t opcode_deps_8x_mod3[8] =
{
SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8,
SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | MODRM | HAS_IMM8
};

View File

@@ -0,0 +1,232 @@
#include "codegen_ops.h"
/*Instruction has input dependency on register in REG field*/
#define SRCDEP_REG (1ull << 0)
/*Instruction has input dependency on register in R/M field*/
#define SRCDEP_RM (1ull << 1)
/*Instruction modifies register in REG field*/
#define DSTDEP_REG (1ull << 2)
/*Instruction modifies register in R/M field*/
#define DSTDEP_RM (1ull << 3)
#define SRCDEP_SHIFT 4
#define DSTDEP_SHIFT 12
/*Instruction has input dependency on given register*/
#define SRCDEP_EAX (1ull << 4)
#define SRCDEP_ECX (1ull << 5)
#define SRCDEP_EDX (1ull << 6)
#define SRCDEP_EBX (1ull << 7)
#define SRCDEP_ESP (1ull << 8)
#define SRCDEP_EBP (1ull << 9)
#define SRCDEP_ESI (1ull << 10)
#define SRCDEP_EDI (1ull << 11)
/*Instruction modifies given register*/
#define DSTDEP_EAX (1ull << 12)
#define DSTDEP_ECX (1ull << 13)
#define DSTDEP_EDX (1ull << 14)
#define DSTDEP_EBX (1ull << 15)
#define DSTDEP_ESP (1ull << 16)
#define DSTDEP_EBP (1ull << 17)
#define DSTDEP_ESI (1ull << 18)
#define DSTDEP_EDI (1ull << 19)
/*Instruction has ModR/M byte*/
#define MODRM (1ull << 20)
/*Instruction implicitly uses ESP*/
#define IMPL_ESP (1ull << 21)
/*Instruction is MMX shift or pack/unpack instruction*/
#define MMX_SHIFTPACK (1ull << 22)
/*Instruction is MMX multiply instruction*/
#define MMX_MULTIPLY (1ull << 23)
/*Instruction pops the FPU stack*/
#define FPU_POP (1ull << 24)
/*Instruction pops the FPU stack twice*/
#define FPU_POP2 (1ull << 25)
/*Instruction pushes onto the FPU stack*/
#define FPU_PUSH (1ull << 26)
/*Instruction writes to ST(0)*/
#define FPU_WRITE_ST0 (1ull << 27)
/*Instruction reads from ST(0)*/
#define FPU_READ_ST0 (1ull << 28)
/*Instruction reads from and writes to ST(0)*/
#define FPU_RW_ST0 (3ull << 27)
/*Instruction reads from ST(1)*/
#define FPU_READ_ST1 (1ull << 29)
/*Instruction writes to ST(1)*/
#define FPU_WRITE_ST1 (1ull << 30)
/*Instruction reads from and writes to ST(1)*/
#define FPU_RW_ST1 (3ull << 29)
/*Instruction reads from ST(reg)*/
#define FPU_READ_STREG (1ull << 31)
/*Instruction writes to ST(reg)*/
#define FPU_WRITE_STREG (1ull << 32)
/*Instruction reads from and writes to ST(reg)*/
#define FPU_RW_STREG (3ull << 30)
#define FPU_FXCH (1ull << 33)
#define HAS_IMM8 (1ull << 34)
#define HAS_IMM1632 (1ull << 35)
#define REGMASK_IMPL_ESP (1 << 8)
#define REGMASK_SHIFTPACK (1 << 9)
#define REGMASK_MULTIPLY (1 << 9)
extern uint64_t opcode_deps[256];
extern uint64_t opcode_deps_mod3[256];
extern uint64_t opcode_deps_0f[256];
extern uint64_t opcode_deps_0f_mod3[256];
extern uint64_t opcode_deps_0f0f[256];
extern uint64_t opcode_deps_0f0f_mod3[256];
extern uint64_t opcode_deps_shift[8];
extern uint64_t opcode_deps_shift_mod3[8];
extern uint64_t opcode_deps_shift_cl[8];
extern uint64_t opcode_deps_shift_cl_mod3[8];
extern uint64_t opcode_deps_f6[8];
extern uint64_t opcode_deps_f6_mod3[8];
extern uint64_t opcode_deps_f7[8];
extern uint64_t opcode_deps_f7_mod3[8];
extern uint64_t opcode_deps_ff[8];
extern uint64_t opcode_deps_ff_mod3[8];
extern uint64_t opcode_deps_d8[8];
extern uint64_t opcode_deps_d8_mod3[8];
extern uint64_t opcode_deps_d9[8];
extern uint64_t opcode_deps_d9_mod3[64];
extern uint64_t opcode_deps_da[8];
extern uint64_t opcode_deps_da_mod3[8];
extern uint64_t opcode_deps_db[8];
extern uint64_t opcode_deps_db_mod3[64];
extern uint64_t opcode_deps_dc[8];
extern uint64_t opcode_deps_dc_mod3[8];
extern uint64_t opcode_deps_dd[8];
extern uint64_t opcode_deps_dd_mod3[8];
extern uint64_t opcode_deps_de[8];
extern uint64_t opcode_deps_de_mod3[8];
extern uint64_t opcode_deps_df[8];
extern uint64_t opcode_deps_df_mod3[8];
extern uint64_t opcode_deps_81[8];
extern uint64_t opcode_deps_81_mod3[8];
extern uint64_t opcode_deps_8x[8];
extern uint64_t opcode_deps_8x_mod3[8];
static inline uint32_t get_addr_regmask(uint64_t data, uint32_t fetchdat, int op_32)
{
uint32_t addr_regmask = 0;
if (data & MODRM)
{
uint8_t modrm = fetchdat & 0xff;
if ((modrm & 0xc0) != 0xc0)
{
if (op_32 & 0x200)
{
if ((modrm & 0x7) == 4)
{
uint8_t sib = (fetchdat >> 8) & 0xff;
if ((modrm & 0xc0) != 0xc0 && (sib & 7) != 5)
{
addr_regmask = 1 << (sib & 7);
if ((sib & 0x38) != 0x20)
addr_regmask |= 1 << ((sib >> 3) & 7);
}
}
else if ((modrm & 0xc7) != 5)
{
addr_regmask = 1 << (modrm & 7);
}
}
else
{
if ((modrm & 0xc7) != 0x06)
{
switch (modrm & 7)
{
case 0: addr_regmask = REG_BX | REG_SI; break;
case 1: addr_regmask = REG_BX | REG_DI; break;
case 2: addr_regmask = REG_BP | REG_SI; break;
case 3: addr_regmask = REG_BP | REG_DI; break;
case 4: addr_regmask = REG_SI; break;
case 5: addr_regmask = REG_DI; break;
case 6: addr_regmask = REG_BP; break;
case 7: addr_regmask = REG_BX; break;
}
}
}
}
}
if (data & IMPL_ESP)
addr_regmask |= REGMASK_IMPL_ESP;
return addr_regmask;
}
static inline uint32_t get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit8, int op_32)
{
uint32_t mask = 0;
if (data & SRCDEP_REG)
{
int reg = (fetchdat >> 3) & 7;
if (bit8)
reg &= 3;
mask |= (1 << reg);
}
if (data & SRCDEP_RM)
{
int reg = fetchdat & 7;
if (bit8)
reg &= 3;
mask |= (1 << reg);
}
mask |= ((data >> SRCDEP_SHIFT) & 0xff);
if (data & MMX_SHIFTPACK)
mask |= REGMASK_SHIFTPACK;
if (data & MMX_MULTIPLY)
mask |= REGMASK_MULTIPLY;
mask |= get_addr_regmask(data, fetchdat, op_32);
return mask;
}
static inline uint32_t get_dstdep_mask(uint64_t data, uint32_t fetchdat, int bit8)
{
uint32_t mask = 0;
if (data & DSTDEP_REG)
{
int reg = (fetchdat >> 3) & 7;
if (bit8)
reg &= 3;
mask |= (1 << reg);
}
if (data & DSTDEP_RM)
{
int reg = fetchdat & 7;
if (bit8)
reg &= 3;
mask |= (1 << reg);
}
mask |= ((data >> DSTDEP_SHIFT) & 0xff);
if (data & MMX_SHIFTPACK)
mask |= REGMASK_SHIFTPACK;
if (data & MMX_MULTIPLY)
mask |= REGMASK_MULTIPLY;
if (data & IMPL_ESP)
mask |= REGMASK_IMPL_ESP | (1 << REG_ESP);
return mask;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,421 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include <86box/mem.h>
#include "codegen.h"
#include "codegen_ops.h"
#include "codegen_timing_common.h"
#define CYCLES(c) (int *)c
#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8))
static int *opcode_timings[256] =
{
/*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm, &timing_rm, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_mod3[256] =
{
/*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_0f[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, &timing_rm,
/*70*/ NULL, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rm, &timing_rm,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL,
};
static int *opcode_timings_0f_mod3[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, &timing_rr,
/*70*/ NULL, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rr, &timing_rr,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL,
};
static int *opcode_timings_shift[8] =
{
CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
};
static int *opcode_timings_shift_mod3[8] =
{
CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
};
static int *opcode_timings_f6[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f6_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f7[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_f7_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_ff[8] =
{
&timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_ff_mod3[8] =
{
&timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_d8[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/
CYCLES(4), CYCLES(6), CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_d9[8] =
{
/* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/
CYCLES(2), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3)
};
static int *opcode_timings_d9_mod3[64] =
{
/*FLD*/
CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*FXCH*/
CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4),
/*FNOP*/
CYCLES(7), NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*FSTP*/
CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/* opFCHS opFABS opFTST opFXAM*/
CYCLES(2), CYCLES(2), NULL, NULL, CYCLES(5), CYCLES(7), NULL, NULL,
/* opFLD1 opFLDL2T opFLDL2E opFLDPI opFLDEG2 opFLDLN2 opFLDZ*/
CYCLES(5), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(5), NULL,
/* opF2XM1 opFYL2X opFPTAN opFPATAN opFDECSTP opFINCSTP,*/
CYCLES(300), CYCLES(58), CYCLES(676), CYCLES(355), NULL, NULL, CYCLES(3), CYCLES(3),
/* opFPREM opFSQRT opFSINCOS opFRNDINT opFSCALE opFSIN opFCOS*/
CYCLES(70), NULL, CYCLES(72), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(474), CYCLES(474)
};
static int *opcode_timings_da[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_da_mod3[8] =
{
NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL
};
static int *opcode_timings_db[8] =
{
/* FLDil FSTil FSTPil FLDe FSTPe*/
CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), NULL, CYCLES(8)
};
static int *opcode_timings_db_mod3[64] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* opFNOP opFCLEX opFINIT opFNOP opFNOP*/
NULL, CYCLES(7), CYCLES(18), CYCLES(27), CYCLES(7), CYCLES(7), NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static int *opcode_timings_dc[8] =
{
/* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/
CYCLES(6), CYCLES(8), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(74), CYCLES(74)
};
static int *opcode_timings_dc_mod3[8] =
{
/* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/
CYCLES(4), CYCLES(6), NULL, NULL, CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_dd[8] =
{
/* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/
CYCLES(2), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(5)
};
static int *opcode_timings_dd_mod3[8] =
{
/* FFFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL
};
static int *opcode_timings_de[8] =
{
/* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_de_mod3[8] =
{
/* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/
CYCLES(4), CYCLES(6), NULL, CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_df[8] =
{
/* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/
CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), CYCLES(172), CYCLES(8)
};
static int *opcode_timings_df_mod3[8] =
{
/* FFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL
};
static int *opcode_timings_8x[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_8x_mod3[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_81[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int *opcode_timings_81_mod3[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int timing_count;
static uint8_t last_prefix;
static uint32_t regmask_modified;
static inline int COUNT(int *c, int op_32)
{
if ((uintptr_t)c <= 10000)
return (int)(uintptr_t)c;
if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff))
{
if (op_32 & 0x100)
return ((uintptr_t)c >> 8) & 0xff;
return (uintptr_t)c & 0xff;
}
return *c;
}
void codegen_timing_winchip_block_start()
{
regmask_modified = 0;
}
void codegen_timing_winchip_start()
{
timing_count = 0;
last_prefix = 0;
}
void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat)
{
timing_count += COUNT(opcode_timings[prefix], 0);
last_prefix = prefix;
}
void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc)
{
int **timings;
uint64_t *deps;
int mod3 = ((fetchdat & 0xc0) == 0xc0);
int bit8 = !(opcode & 1);
switch (last_prefix)
{
case 0x0f:
timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f;
break;
case 0xd8:
timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8;
opcode = (opcode >> 3) & 7;
break;
case 0xd9:
timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xda:
timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da;
opcode = (opcode >> 3) & 7;
break;
case 0xdb:
timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xdc:
timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc;
opcode = (opcode >> 3) & 7;
break;
case 0xdd:
timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd;
opcode = (opcode >> 3) & 7;
break;
case 0xde:
timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de;
opcode = (opcode >> 3) & 7;
break;
case 0xdf:
timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df;
opcode = (opcode >> 3) & 7;
break;
default:
switch (opcode)
{
case 0x80: case 0x82: case 0x83:
timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x;
deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x;
opcode = (fetchdat >> 3) & 7;
break;
case 0x81:
timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81;
deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81;
opcode = (fetchdat >> 3) & 7;
break;
case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3:
timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf6:
timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf7:
timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7;
opcode = (fetchdat >> 3) & 7;
break;
case 0xff:
timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff;
opcode = (fetchdat >> 3) & 7;
break;
default:
timings = mod3 ? opcode_timings_mod3 : opcode_timings;
deps = mod3 ? opcode_deps_mod3 : opcode_deps;
break;
}
}
timing_count += COUNT(timings[opcode], op_32);
if (regmask_modified & get_addr_regmask(deps[opcode], fetchdat, op_32))
timing_count++; /*AGI stall*/
codegen_block_cycles += timing_count;
regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8);
}
void codegen_timing_winchip_block_end()
{
}
codegen_timing_t codegen_timing_winchip =
{
codegen_timing_winchip_start,
codegen_timing_winchip_prefix,
codegen_timing_winchip_opcode,
codegen_timing_winchip_block_start,
codegen_timing_winchip_block_end,
NULL
};

View File

@@ -0,0 +1,743 @@
/*Since IDT/Centaur didn't document cycle timings in the WinChip datasheets, and
I don't currently own a WinChip 2 to test against, most of the timing here is
a guess. This code makes the current (probably wrong) assumptions :
- FPU uses same timings as a Pentium, except for FXCH (which doesn't pair)
- 3DNow! instructions perfectly pair
- MMX follows mostly Pentium rules - one pipeline has shift/pack, one has
multiply, and other instructions can execute in either pipeline
- Instructions with prefixes can pair if both instructions are fully decoded
when the first instruction starts execution.*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ops.h"
#include "codegen_timing_common.h"
/*Instruction has different execution time for 16 and 32 bit data. Does not pair */
#define CYCLES_HAS_MULTI (1 << 31)
#define CYCLES_FPU (1 << 30)
#define CYCLES_IS_MMX_MUL (1 << 29)
#define CYCLES_IS_MMX_SHIFT (1 << 28)
#define CYCLES_IS_MMX_ANY (1 << 27)
#define CYCLES_IS_3DNOW (1 << 26)
#define CYCLES_MMX_MUL(c) (CYCLES_IS_MMX_MUL | c)
#define CYCLES_MMX_SHIFT(c) (CYCLES_IS_MMX_SHIFT | c)
#define CYCLES_MMX_ANY(c) (CYCLES_IS_MMX_ANY | c)
#define CYCLES_3DNOW(c) (CYCLES_IS_3DNOW | c)
#define CYCLES_IS_MMX (CYCLES_IS_MMX_MUL | CYCLES_IS_MMX_SHIFT | CYCLES_IS_MMX_ANY | CYCLES_IS_3DNOW)
#define GET_CYCLES(c) (c & ~(CYCLES_HAS_MULTI | CYCLES_FPU | CYCLES_IS_MMX))
#define CYCLES(c) c
#define CYCLES2(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8))
/*comp_time = cycles until instruction complete
i_overlap = cycles that overlap with integer
f_overlap = cycles that overlap with subsequent FPU*/
#define FPU_CYCLES(comp_time, i_overlap, f_overlap) (comp_time) | (i_overlap << 8) | (f_overlap << 16) | CYCLES_FPU
#define FPU_COMP_TIME(timing) (timing & 0xff)
#define FPU_I_OVERLAP(timing) ((timing >> 8) & 0xff)
#define FPU_F_OVERLAP(timing) ((timing >> 16) & 0xff)
#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing))
#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing))
#define FPU_RESULT_LATENCY(timing) ((timing >> 8) & 0xff)
#define INVALID 0
static uint32_t opcode_timings[256] =
{
/*00*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), INVALID,
/*10*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3),
/*20*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3),
/*30*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2),
/*40*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*80*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID
};
static uint32_t opcode_timings_mod3[256] =
{
/*00*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), INVALID,
/*10*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3),
/*20*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3),
/*30*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2),
/*40*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID,
};
static uint32_t opcode_timings_0f[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1),
/*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*60*/ CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2),
/*70*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES(100), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2),
/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), INVALID, INVALID, CYCLES(3), CYCLES(3), INVALID, CYCLES(13), CYCLES(3), CYCLES(3), INVALID, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), INVALID, INVALID, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2),
/*e0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2),
/*f0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID,
};
static uint32_t opcode_timings_0f_mod3[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1),
/*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
/*60*/ CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1),
/*70*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES(100), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1),
/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), INVALID, INVALID, CYCLES(3), CYCLES(3), INVALID, CYCLES(13), CYCLES(3), CYCLES(3), INVALID, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), INVALID, INVALID, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1),
/*e0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1),
/*f0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID,
};
static uint32_t opcode_timings_shift[8] =
{
CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
};
static uint32_t opcode_timings_shift_mod3[8] =
{
CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
};
static uint32_t opcode_timings_f6[8] =
{
CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static uint32_t opcode_timings_f6_mod3[8] =
{
CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static uint32_t opcode_timings_f7[8] =
{
CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static uint32_t opcode_timings_f7_mod3[8] =
{
CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static uint32_t opcode_timings_ff[8] =
{
CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID
};
static uint32_t opcode_timings_ff_mod3[8] =
{
CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID
};
static uint32_t opcode_timings_d8[8] =
{
/* FADDs FMULs FCOMs FCOMPs*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/* FSUBs FSUBRs FDIVs FDIVRs*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
};
static uint32_t opcode_timings_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/* FSUB FSUBR FDIV FDIVR*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
};
static uint32_t opcode_timings_d9[8] =
{
/* FLDs FSTs FSTPs*/
FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
/* FLDENV FLDCW FSTENV FSTCW*/
FPU_CYCLES(32,0,0), FPU_CYCLES(8,0,0), FPU_CYCLES(48,0,0), FPU_CYCLES(2,0,0)
};
static uint32_t opcode_timings_d9_mod3[64] =
{
/*FLD*/
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/*FXCH*/
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/*FNOP*/
FPU_CYCLES(3,0,0), INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
/*FSTP*/
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/* opFCHS opFABS*/
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), INVALID, INVALID,
/* opFTST opFXAM*/
FPU_CYCLES(1,0,0), FPU_CYCLES(21,4,0), INVALID, INVALID,
/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/
FPU_CYCLES(2,0,0), FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2),
/* opFLDEG2 opFLDLN2 opFLDZ*/
FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), FPU_CYCLES(2,0,0), INVALID,
/* opF2XM1 opFYL2X opFPTAN opFPATAN*/
FPU_CYCLES(53,2,2), FPU_CYCLES(103,2,2),FPU_CYCLES(120,36,0),FPU_CYCLES(112,2,2),
/* opFDECSTP opFINCSTP,*/
INVALID, INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
/* opFPREM opFSQRT opFSINCOS*/
FPU_CYCLES(64,2,2), INVALID, FPU_CYCLES(70,69,2),FPU_CYCLES(89,2,2),
/* opFRNDINT opFSCALE opFSIN opFCOS*/
FPU_CYCLES(9,0,0), FPU_CYCLES(20,5,0), FPU_CYCLES(65,2,2), FPU_CYCLES(65,2,2)
};
static uint32_t opcode_timings_da[8] =
{
/* FIADDl FIMULl FICOMl FICOMPl*/
FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0),
/* FISUBl FISUBRl FIDIVl FIDIVRl*/
FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2)
};
static uint32_t opcode_timings_da_mod3[8] =
{
INVALID, INVALID, INVALID, INVALID,
/* FCOMPP*/
INVALID, FPU_CYCLES(1,0,0), INVALID, INVALID
};
static uint32_t opcode_timings_db[8] =
{
/* FLDil FSTil FSTPil*/
FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0),
/* FLDe FSTPe*/
INVALID, FPU_CYCLES(3,0,0), INVALID, FPU_CYCLES(3,0,0)
};
static uint32_t opcode_timings_db_mod3[64] =
{
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
/* opFNOP opFCLEX opFINIT*/
INVALID, FPU_CYCLES(1,0,0), FPU_CYCLES(7,0,0), FPU_CYCLES(17,0,0),
/* opFNOP opFNOP*/
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
INVALID, INVALID, INVALID, INVALID,
};
static uint32_t opcode_timings_dc[8] =
{
/* FADDd FMULd FCOMd FCOMPd*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/* FSUBd FSUBRd FDIVd FDIVRd*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
};
static uint32_t opcode_timings_dc_mod3[8] =
{
/* opFADDr opFMULr*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),INVALID, INVALID,
/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
};
static uint32_t opcode_timings_dd[8] =
{
/* FLDd FSTd FSTPd*/
FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
/* FRSTOR FSAVE FSTSW*/
FPU_CYCLES(70,0,0), INVALID, FPU_CYCLES(127,0,0), FPU_CYCLES(6,0,0)
};
static uint32_t opcode_timings_dd_mod3[8] =
{
/* FFFREE FST FSTP*/
FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),
/* FUCOM FUCOMP*/
FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0),INVALID, INVALID
};
static uint32_t opcode_timings_de[8] =
{
/* FIADDw FIMULw FICOMw FICOMPw*/
FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0),
/* FISUBw FISUBRw FIDIVw FIDIVRw*/
FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2)
};
static uint32_t opcode_timings_de_mod3[8] =
{
/* FADDP FMULP FCOMPP*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(1,0,0),
/* FSUBP FSUBRP FDIVP FDIVRP*/
FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
};
static uint32_t opcode_timings_df[8] =
{
/* FILDiw FISTiw FISTPiw*/
FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0),
/* FILDiq FBSTP FISTPiq*/
INVALID, FPU_CYCLES(3,2,2), FPU_CYCLES(148,0,0), FPU_CYCLES(6,0,0)
};
static uint32_t opcode_timings_df_mod3[8] =
{
INVALID, INVALID, INVALID, INVALID,
/* FSTSW AX*/
FPU_CYCLES(6,0,0), INVALID, INVALID, INVALID
};
static uint32_t opcode_timings_8x[8] =
{
CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
};
static uint32_t opcode_timings_8x_mod3[8] =
{
CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
};
static uint32_t opcode_timings_81[8] =
{
CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
};
static uint32_t opcode_timings_81_mod3[8] =
{
CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
};
static int timing_count;
static uint8_t last_prefix;
static uint32_t regmask_modified;
static int decode_delay, decode_delay_offset;
static int fpu_latency;
static int fpu_st_latency[8];
static int u_pipe_full;
static uint32_t u_pipe_opcode;
static uint32_t *u_pipe_timings;
static uint32_t u_pipe_op_32;
static uint32_t u_pipe_regmask;
static uint32_t u_pipe_fetchdat;
static int u_pipe_decode_delay_offset;
static uint64_t *u_pipe_deps;
int can_pair(uint32_t timing_a, uint32_t timing_b, uint8_t regmask_b)
{
/*Only MMX/3DNow instructions can pair*/
if (!(timing_b & CYCLES_IS_MMX))
return 0;
/*Only one MMX multiply per cycle*/
if ((timing_a & CYCLES_IS_MMX_MUL) && (timing_b & CYCLES_IS_MMX_MUL))
return 0;
/*Only one MMX shift/pack per cycle*/
if ((timing_a & CYCLES_IS_MMX_SHIFT) && (timing_b & CYCLES_IS_MMX_SHIFT))
return 0;
/*Second instruction can not access registers written by first*/
if (u_pipe_regmask & regmask_b)
return 0;
/*Must have had enough time to decode prefixes*/
if ((decode_delay+decode_delay_offset+u_pipe_decode_delay_offset) > 0)
return 0;
return 1;
}
static inline int COUNT(uint32_t c, int op_32)
{
if (c & CYCLES_FPU)
return FPU_I_LATENCY(c);
if (c & CYCLES_HAS_MULTI)
{
if (op_32 & 0x100)
return (c >> 8) & 0xff;
return c & 0xff;
}
return GET_CYCLES(c);
}
static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32)
{
uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32);
/*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not
cause AGIs with each other, but do with instructions that use it explicitly*/
if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP))
addr_regmask |= (1 << REG_ESP);
return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP;
}
static int codegen_fpu_latencies(uint64_t deps, int reg)
{
int latency = fpu_latency;
if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency)
latency = fpu_st_latency[0];
if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency)
latency = fpu_st_latency[1];
if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency)
latency = fpu_st_latency[reg];
return latency;
}
#define SUB_AND_CLAMP(latency, count) \
latency -= count; \
if (latency < 0) \
latency = 0
static void codegen_fpu_latency_clock(int count)
{
SUB_AND_CLAMP(fpu_latency, count);
SUB_AND_CLAMP(fpu_st_latency[0], count);
SUB_AND_CLAMP(fpu_st_latency[1], count);
SUB_AND_CLAMP(fpu_st_latency[2], count);
SUB_AND_CLAMP(fpu_st_latency[3], count);
SUB_AND_CLAMP(fpu_st_latency[4], count);
SUB_AND_CLAMP(fpu_st_latency[5], count);
SUB_AND_CLAMP(fpu_st_latency[6], count);
SUB_AND_CLAMP(fpu_st_latency[7], count);
}
static void codegen_instruction(uint32_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay)
{
int instr_cycles, latency = 0;
if ((timings[opcode] & CYCLES_FPU) && !(deps[opcode] & FPU_FXCH))
instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7);
else
instr_cycles = 0;
if ((decode_delay + decode_delay_offset) > 0)
codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles);
else
codegen_fpu_latency_clock(instr_cycles);
instr_cycles += COUNT(timings[opcode], op_32);
instr_cycles += exec_delay;
if ((decode_delay + decode_delay_offset) > 0)
codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset;
else
codegen_block_cycles += instr_cycles;
decode_delay = (-instr_cycles) + 1;
if (deps[opcode] & FPU_POP)
{
int c;
for (c = 0; c < 7; c++)
fpu_st_latency[c] = fpu_st_latency[c+1];
fpu_st_latency[7] = 0;
}
if (deps[opcode] & FPU_POP2)
{
int c;
for (c = 0; c < 6; c++)
fpu_st_latency[c] = fpu_st_latency[c+2];
fpu_st_latency[6] = fpu_st_latency[7] = 0;
}
if (timings[opcode] & CYCLES_FPU)
{
/* if (fpu_latency)
fatal("Bad latency FPU\n");*/
fpu_latency = FPU_F_LATENCY(timings[opcode]);
}
if (deps[opcode] & FPU_PUSH)
{
int c;
for (c = 0; c < 7; c++)
fpu_st_latency[c+1] = fpu_st_latency[c];
fpu_st_latency[0] = 0;
}
if (deps[opcode] & FPU_WRITE_ST0)
{
/* if (fpu_st_latency[0])
fatal("Bad latency ST0\n");*/
fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]);
}
if (deps[opcode] & FPU_WRITE_ST1)
{
/* if (fpu_st_latency[1])
fatal("Bad latency ST1\n");*/
fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]);
}
if (deps[opcode] & FPU_WRITE_STREG)
{
int reg = fetchdat & 7;
if (deps[opcode] & FPU_POP)
reg--;
if (reg >= 0 &&
!(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) &&
!(reg == 1 && (deps[opcode] & FPU_WRITE_ST1)))
{
/* if (fpu_st_latency[reg])
fatal("Bad latency STREG %i %08x %i %016llx %02x\n",fpu_st_latency[reg], fetchdat, reg, timings[opcode], opcode);*/
fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]);
}
}
}
static void codegen_timing_winchip2_block_start()
{
regmask_modified = 0;
decode_delay = decode_delay_offset = 0;
u_pipe_full = 0;
}
static void codegen_timing_winchip2_start()
{
timing_count = 0;
last_prefix = 0;
}
static void codegen_timing_winchip2_prefix(uint8_t prefix, uint32_t fetchdat)
{
if (prefix == 0x0f)
{
/*0fh prefix is 'free'*/
last_prefix = prefix;
return;
}
/*On WinChip all prefixes take 1 cycle to decode. Decode may be shadowed
by execution of previous instructions*/
decode_delay_offset++;
last_prefix = prefix;
}
static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc)
{
uint32_t *timings;
uint64_t *deps;
int mod3 = ((fetchdat & 0xc0) == 0xc0);
int bit8 = !(opcode & 1);
int agi_stall = 0;
switch (last_prefix)
{
case 0x0f:
timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f;
break;
case 0xd8:
timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8;
opcode = (opcode >> 3) & 7;
break;
case 0xd9:
timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xda:
timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da;
opcode = (opcode >> 3) & 7;
break;
case 0xdb:
timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xdc:
timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc;
opcode = (opcode >> 3) & 7;
break;
case 0xdd:
timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd;
opcode = (opcode >> 3) & 7;
break;
case 0xde:
timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de;
opcode = (opcode >> 3) & 7;
break;
case 0xdf:
timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df;
opcode = (opcode >> 3) & 7;
break;
default:
switch (opcode)
{
case 0x80: case 0x82: case 0x83:
timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x;
deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x;
opcode = (fetchdat >> 3) & 7;
break;
case 0x81:
timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81;
deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81;
opcode = (fetchdat >> 3) & 7;
break;
case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3:
timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf6:
timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf7:
timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7;
opcode = (fetchdat >> 3) & 7;
break;
case 0xff:
timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff;
opcode = (fetchdat >> 3) & 7;
break;
default:
timings = mod3 ? opcode_timings_mod3 : opcode_timings;
deps = mod3 ? opcode_deps_mod3 : opcode_deps;
break;
}
}
if (u_pipe_full)
{
uint8_t regmask = get_srcdep_mask(deps[opcode], fetchdat, bit8, u_pipe_op_32);
if (can_pair(u_pipe_timings[u_pipe_opcode], timings[opcode], regmask))
{
int cycles_a = u_pipe_timings[u_pipe_opcode] & 0xff;
int cycles_b = timings[opcode] & 0xff;
uint32_t timing = (cycles_a > cycles_b) ? u_pipe_timings[u_pipe_opcode] : timings[opcode];
uint64_t temp_deps = 0;
if (check_agi(deps, opcode, fetchdat, op_32) || check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32))
agi_stall = 1;
codegen_instruction(&timing, &temp_deps, 0, 0, 0, 0, agi_stall);
u_pipe_full = 0;
decode_delay_offset = 0;
regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | u_pipe_regmask;
return;
}
else
{
/*No pairing, run first instruction now*/
if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32))
agi_stall = 1;
codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall);
u_pipe_full = 0;
regmask_modified = u_pipe_regmask;
}
}
if (timings[opcode] & CYCLES_IS_MMX)
{
/*Might pair with next instruction*/
u_pipe_full = 1;
u_pipe_opcode = opcode;
u_pipe_timings = timings;
u_pipe_op_32 = op_32;
u_pipe_regmask = get_dstdep_mask(deps[opcode], fetchdat, bit8);
u_pipe_fetchdat = fetchdat;
u_pipe_decode_delay_offset = decode_delay_offset;
u_pipe_deps = deps;
decode_delay_offset = 0;
return;
}
if (check_agi(deps, opcode, fetchdat, op_32))
agi_stall = 1;
codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall);
decode_delay_offset = 0;
regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8);
}
static void codegen_timing_winchip2_block_end()
{
if (u_pipe_full)
{
int agi_stall = 0;
if (check_agi(u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_op_32))
agi_stall = 1;
codegen_instruction(u_pipe_timings, u_pipe_deps, u_pipe_opcode, u_pipe_fetchdat, u_pipe_decode_delay_offset, u_pipe_op_32, agi_stall);
u_pipe_full = 0;
}
}
codegen_timing_t codegen_timing_winchip2 =
{
codegen_timing_winchip2_start,
codegen_timing_winchip2_prefix,
codegen_timing_winchip2_opcode,
codegen_timing_winchip2_block_start,
codegen_timing_winchip2_block_end,
NULL
};

1178
src/codegen/codegen_x86-64.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_EXIT_OFFSET 0x7e0
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
#define BLOCK_MAX 1620
enum
{
OP_RET = 0xc3
};
#define NR_HOST_REGS 4
extern int host_reg_mapping[NR_HOST_REGS];
#define NR_HOST_XMM_REGS 8
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];

2156
src/codegen/codegen_x86.c Normal file

File diff suppressed because it is too large Load Diff

42
src/codegen/codegen_x86.h Normal file
View File

@@ -0,0 +1,42 @@
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_EXIT_OFFSET 0x7f0
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
#define BLOCK_MAX 1720
enum
{
OP_RET = 0xc3
};
#define NR_HOST_REGS 4
extern int host_reg_mapping[NR_HOST_REGS];
#define NR_HOST_XMM_REGS 8
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
extern uint32_t mem_load_addr_ea_b;
extern uint32_t mem_load_addr_ea_w;
extern uint32_t mem_load_addr_ea_l;
extern uint32_t mem_load_addr_ea_q;
extern uint32_t mem_store_addr_ea_b;
extern uint32_t mem_store_addr_ea_w;
extern uint32_t mem_store_addr_ea_l;
extern uint32_t mem_store_addr_ea_q;
extern uint32_t mem_load_addr_ea_b_no_abrt;
extern uint32_t mem_store_addr_ea_b_no_abrt;
extern uint32_t mem_load_addr_ea_w_no_abrt;
extern uint32_t mem_store_addr_ea_w_no_abrt;
extern uint32_t mem_load_addr_ea_l_no_abrt;
extern uint32_t mem_store_addr_ea_l_no_abrt;
extern uint32_t mem_check_write;
extern uint32_t mem_check_write_w;
extern uint32_t mem_check_write_l;

526
src/codegen/x86_flags.h Normal file
View File

@@ -0,0 +1,526 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
extern int tempc;
enum
{
FLAGS_UNKNOWN,
FLAGS_ZN8,
FLAGS_ZN16,
FLAGS_ZN32,
FLAGS_ADD8,
FLAGS_ADD16,
FLAGS_ADD32,
FLAGS_SUB8,
FLAGS_SUB16,
FLAGS_SUB32,
FLAGS_SHL8,
FLAGS_SHL16,
FLAGS_SHL32,
FLAGS_SHR8,
FLAGS_SHR16,
FLAGS_SHR32,
FLAGS_SAR8,
FLAGS_SAR16,
FLAGS_SAR32,
FLAGS_INC8,
FLAGS_INC16,
FLAGS_INC32,
FLAGS_DEC8,
FLAGS_DEC16,
FLAGS_DEC32
};
static __inline int ZF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
return !cpu_state.flags_res;
case FLAGS_UNKNOWN:
return cpu_state.flags & Z_FLAG;
default:
return 0;
}
}
static __inline int NF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ADD8:
case FLAGS_SUB8:
case FLAGS_SHL8:
case FLAGS_SHR8:
case FLAGS_SAR8:
case FLAGS_INC8:
case FLAGS_DEC8:
return cpu_state.flags_res & 0x80;
case FLAGS_ZN16:
case FLAGS_ADD16:
case FLAGS_SUB16:
case FLAGS_SHL16:
case FLAGS_SHR16:
case FLAGS_SAR16:
case FLAGS_INC16:
case FLAGS_DEC16:
return cpu_state.flags_res & 0x8000;
case FLAGS_ZN32:
case FLAGS_ADD32:
case FLAGS_SUB32:
case FLAGS_SHL32:
case FLAGS_SHR32:
case FLAGS_SAR32:
case FLAGS_INC32:
case FLAGS_DEC32:
return cpu_state.flags_res & 0x80000000;
case FLAGS_UNKNOWN:
return cpu_state.flags & N_FLAG;
default:
return 0;
}
}
static __inline int PF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
return znptable8[cpu_state.flags_res & 0xff] & P_FLAG;
case FLAGS_UNKNOWN:
return cpu_state.flags & P_FLAG;
default:
return 0;
}
}
static __inline int VF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
return 0;
case FLAGS_ADD8:
case FLAGS_INC8:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80);
case FLAGS_ADD16:
case FLAGS_INC16:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000);
case FLAGS_ADD32:
case FLAGS_INC32:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000);
case FLAGS_SUB8:
case FLAGS_DEC8:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80);
case FLAGS_SUB16:
case FLAGS_DEC16:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000);
case FLAGS_SUB32:
case FLAGS_DEC32:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000);
case FLAGS_SHL8:
return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80);
case FLAGS_SHL16:
return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x8000);
case FLAGS_SHL32:
return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80000000);
case FLAGS_SHR8:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80));
case FLAGS_SHR16:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000));
case FLAGS_SHR32:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000));
case FLAGS_UNKNOWN:
return cpu_state.flags & V_FLAG;
default:
return 0;
}
}
static __inline int AF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
return 0;
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10;
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10;
case FLAGS_UNKNOWN:
return cpu_state.flags & A_FLAG;
default:
return 0;
}
}
static __inline int CF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ADD8:
return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100;
case FLAGS_ADD16:
return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000;
case FLAGS_ADD32:
return (cpu_state.flags_res < cpu_state.flags_op1);
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
return (cpu_state.flags_op1 < cpu_state.flags_op2);
case FLAGS_SHL8:
return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80;
case FLAGS_SHL16:
return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000;
case FLAGS_SHL32:
return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000;
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
return (cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_SAR8:
return ((int8_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_SAR16:
return ((int16_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_SAR32:
return ((int32_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
return 0;
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_UNKNOWN:
return cpu_state.flags & C_FLAG;
default:
return 0;
}
}
static __inline void flags_rebuild()
{
if (cpu_state.flags_op != FLAGS_UNKNOWN)
{
uint16_t tempf = 0;
if (CF_SET()) tempf |= C_FLAG;
if (PF_SET()) tempf |= P_FLAG;
if (AF_SET()) tempf |= A_FLAG;
if (ZF_SET()) tempf |= Z_FLAG;
if (NF_SET()) tempf |= N_FLAG;
if (VF_SET()) tempf |= V_FLAG;
cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf;
cpu_state.flags_op = FLAGS_UNKNOWN;
}
}
static __inline void flags_extract()
{
cpu_state.flags_op = FLAGS_UNKNOWN;
}
static __inline void flags_rebuild_c()
{
if (cpu_state.flags_op != FLAGS_UNKNOWN)
{
if (CF_SET())
cpu_state.flags |= C_FLAG;
else
cpu_state.flags &= ~C_FLAG;
}
}
static __inline void setznp8(uint8_t val)
{
cpu_state.flags_op = FLAGS_ZN8;
cpu_state.flags_res = val;
}
static __inline void setznp16(uint16_t val)
{
cpu_state.flags_op = FLAGS_ZN16;
cpu_state.flags_res = val;
}
static __inline void setznp32(uint32_t val)
{
cpu_state.flags_op = FLAGS_ZN32;
cpu_state.flags_res = val;
}
#define set_flags_shift(op, orig, shift, res) \
cpu_state.flags_op = op; \
cpu_state.flags_res = res; \
cpu_state.flags_op1 = orig; \
cpu_state.flags_op2 = shift;
static __inline void setadd8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xff;
cpu_state.flags_op = FLAGS_ADD8;
}
static __inline void setadd16(uint16_t a, uint16_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xffff;
cpu_state.flags_op = FLAGS_ADD16;
}
static __inline void setadd32(uint32_t a, uint32_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a + b;
cpu_state.flags_op = FLAGS_ADD32;
}
static __inline void setadd8nc(uint8_t a, uint8_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xff;
cpu_state.flags_op = FLAGS_INC8;
}
static __inline void setadd16nc(uint16_t a, uint16_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xffff;
cpu_state.flags_op = FLAGS_INC16;
}
static __inline void setadd32nc(uint32_t a, uint32_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a + b;
cpu_state.flags_op = FLAGS_INC32;
}
static __inline void setsub8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xff;
cpu_state.flags_op = FLAGS_SUB8;
}
static __inline void setsub16(uint16_t a, uint16_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xffff;
cpu_state.flags_op = FLAGS_SUB16;
}
static __inline void setsub32(uint32_t a, uint32_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a - b;
cpu_state.flags_op = FLAGS_SUB32;
}
static __inline void setsub8nc(uint8_t a, uint8_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xff;
cpu_state.flags_op = FLAGS_DEC8;
}
static __inline void setsub16nc(uint16_t a, uint16_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xffff;
cpu_state.flags_op = FLAGS_DEC16;
}
static __inline void setsub32nc(uint32_t a, uint32_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a - b;
cpu_state.flags_op = FLAGS_DEC32;
}
static __inline void setadc8(uint8_t a, uint8_t b)
{
uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
cpu_state.flags_op = FLAGS_UNKNOWN;
cpu_state.flags&=~0x8D5;
cpu_state.flags|=znptable8[c&0xFF];
if (c&0x100) cpu_state.flags|=C_FLAG;
if (!((a^b)&0x80)&&((a^c)&0x80)) cpu_state.flags|=V_FLAG;
if (((a&0xF)+(b&0xF))&0x10) cpu_state.flags|=A_FLAG;
}
static __inline void setadc16(uint16_t a, uint16_t b)
{
uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
cpu_state.flags_op = FLAGS_UNKNOWN;
cpu_state.flags&=~0x8D5;
cpu_state.flags|=znptable16[c&0xFFFF];
if (c&0x10000) cpu_state.flags|=C_FLAG;
if (!((a^b)&0x8000)&&((a^c)&0x8000)) cpu_state.flags|=V_FLAG;
if (((a&0xF)+(b&0xF))&0x10) cpu_state.flags|=A_FLAG;
}
static __inline void setadc32(uint32_t a, uint32_t b)
{
uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
cpu_state.flags_op = FLAGS_UNKNOWN;
cpu_state.flags&=~0x8D5;
cpu_state.flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
cpu_state.flags|=(znptable8[c&0xFF]&P_FLAG);
if ((c<a) || (c==a && tempc)) cpu_state.flags|=C_FLAG;
if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) cpu_state.flags|=V_FLAG;
if (((a&0xF)+(b&0xF)+tempc)&0x10) cpu_state.flags|=A_FLAG;
}
static __inline void setsbc8(uint8_t a, uint8_t b)
{
uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
cpu_state.flags_op = FLAGS_UNKNOWN;
cpu_state.flags&=~0x8D5;
cpu_state.flags|=znptable8[c&0xFF];
if (c&0x100) cpu_state.flags|=C_FLAG;
if ((a^b)&(a^c)&0x80) cpu_state.flags|=V_FLAG;
if (((a&0xF)-(b&0xF))&0x10) cpu_state.flags|=A_FLAG;
}
static __inline void setsbc16(uint16_t a, uint16_t b)
{
uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
cpu_state.flags_op = FLAGS_UNKNOWN;
cpu_state.flags&=~0x8D5;
cpu_state.flags|=(znptable16[c&0xFFFF]&~4);
cpu_state.flags|=(znptable8[c&0xFF]&4);
if (c&0x10000) cpu_state.flags|=C_FLAG;
if ((a^b)&(a^c)&0x8000) cpu_state.flags|=V_FLAG;
if (((a&0xF)-(b&0xF))&0x10) cpu_state.flags|=A_FLAG;
}
static __inline void setsbc32(uint32_t a, uint32_t b)
{
uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
cpu_state.flags_op = FLAGS_UNKNOWN;
cpu_state.flags&=~0x8D5;
cpu_state.flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
cpu_state.flags|=(znptable8[c&0xFF]&P_FLAG);
if ((c>a) || (c==a && tempc)) cpu_state.flags|=C_FLAG;
if ((a^b)&(a^c)&0x80000000) cpu_state.flags|=V_FLAG;
if (((a&0xF)-((b&0xF)+tempc))&0x10) cpu_state.flags|=A_FLAG;
}
extern void cpu_386_flags_extract();
extern void cpu_386_flags_rebuild();

457
src/codegen/x86_ops_call.h Normal file
View File

@@ -0,0 +1,457 @@
#define CALL_FAR_w(new_seg, new_pc) \
old_cs = CS; \
old_pc = cpu_state.pc; \
oxpc = cpu_state.pc; \
cpu_state.pc = new_pc; \
optype = CALL; \
cgate16 = cgate32 = 0; \
if (msw & 1) loadcscall(new_seg); \
else \
{ \
loadcs(new_seg); \
cycles -= timing_call_rm; \
} \
optype = 0; \
if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
oldss = ss; \
if (cgate32) \
{ \
uint32_t old_esp = ESP; \
PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
} \
else \
{ \
uint32_t old_esp = ESP; \
PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
}
#define CALL_FAR_l(new_seg, new_pc) \
old_cs = CS; \
old_pc = cpu_state.pc; \
oxpc = cpu_state.pc; \
cpu_state.pc = new_pc; \
optype = CALL; \
cgate16 = cgate32 = 0; \
if (msw & 1) loadcscall(new_seg); \
else \
{ \
loadcs(new_seg); \
cycles -= timing_call_rm; \
} \
optype = 0; \
if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
oldss = ss; \
if (cgate16) \
{ \
uint32_t old_esp = ESP; \
PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
} \
else \
{ \
uint32_t old_esp = ESP; \
PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
}
static int opCALL_far_w(uint32_t fetchdat)
{
uint32_t old_cs, old_pc;
uint16_t new_cs, new_pc;
int cycles_old = cycles; UN_USED(cycles_old);
new_pc = getwordf();
new_cs = getword(); if (cpu_state.abrt) return 1;
CALL_FAR_w(new_cs, new_pc);
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 5, -1, 0,0,cgate16 ? 2:0,cgate16 ? 0:2, 0);
PREFETCH_FLUSH();
return 0;
}
static int opCALL_far_l(uint32_t fetchdat)
{
uint32_t old_cs, old_pc;
uint32_t new_cs, new_pc;
int cycles_old = cycles; UN_USED(cycles_old);
new_pc = getlong();
new_cs = getword(); if (cpu_state.abrt) return 1;
CALL_FAR_l(new_cs, new_pc);
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 7, -1, 0,0,cgate16 ? 2:0,cgate16 ? 0:2, 0);
PREFETCH_FLUSH();
return 0;
}
static int opFF_w_a16(uint32_t fetchdat)
{
uint16_t old_cs, new_cs;
uint32_t old_pc, new_pc;
int cycles_old = cycles; UN_USED(cycles_old);
uint16_t temp;
fetch_ea_16(fetchdat);
switch (rmdat & 0x38)
{
case 0x00: /*INC w*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + 1); if (cpu_state.abrt) return 1;
setadd16nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
break;
case 0x08: /*DEC w*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp - 1); if (cpu_state.abrt) return 1;
setsub16nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
break;
case 0x10: /*CALL*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(cpu_state.pc);
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 0);
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1;
CALL_FAR_w(new_cs, new_pc);
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,cgate16 ? 2:0,cgate16 ? 0:2, 0);
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
oxpc = cpu_state.pc;
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 0);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH w*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(temp);
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 0);
break;
default:
// fatal("Bad FF opcode %02X\n",rmdat&0x38);
x86illegal();
}
return cpu_state.abrt;
}
static int opFF_w_a32(uint32_t fetchdat)
{
uint16_t old_cs, new_cs;
uint32_t old_pc, new_pc;
int cycles_old = cycles; UN_USED(cycles_old);
uint16_t temp;
fetch_ea_32(fetchdat);
switch (rmdat & 0x38)
{
case 0x00: /*INC w*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + 1); if (cpu_state.abrt) return 1;
setadd16nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
break;
case 0x08: /*DEC w*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp - 1); if (cpu_state.abrt) return 1;
setsub16nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
break;
case 0x10: /*CALL*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(cpu_state.pc);
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 1);
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1;
CALL_FAR_w(new_cs, new_pc);
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,cgate16 ? 2:0,cgate16 ? 0:2, 1);
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,0,0,0, 1);
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
oxpc = cpu_state.pc;
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 1);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH w*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(temp);
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,1,0, 1);
break;
default:
// fatal("Bad FF opcode %02X\n",rmdat&0x38);
x86illegal();
}
return cpu_state.abrt;
}
static int opFF_l_a16(uint32_t fetchdat)
{
uint16_t old_cs, new_cs;
uint32_t old_pc, new_pc;
int cycles_old = cycles; UN_USED(cycles_old);
uint32_t temp;
fetch_ea_16(fetchdat);
switch (rmdat & 0x38)
{
case 0x00: /*INC l*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + 1); if (cpu_state.abrt) return 1;
setadd32nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
break;
case 0x08: /*DEC l*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp - 1); if (cpu_state.abrt) return 1;
setsub32nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
break;
case 0x10: /*CALL*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(cpu_state.pc);
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 0);
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1;
CALL_FAR_l(new_cs, new_pc);
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,cgate16 ? 2:0,cgate16 ? 0:2, 0);
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 0,1,0,0, 0);
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
oxpc = cpu_state.pc;
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 0);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH l*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(temp);
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 0);
break;
default:
// fatal("Bad FF opcode %02X\n",rmdat&0x38);
x86illegal();
}
return cpu_state.abrt;
}
static int opFF_l_a32(uint32_t fetchdat)
{
uint16_t old_cs, new_cs;
uint32_t old_pc, new_pc;
int cycles_old = cycles; UN_USED(cycles_old);
uint32_t temp;
fetch_ea_32(fetchdat);
switch (rmdat & 0x38)
{
case 0x00: /*INC l*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + 1); if (cpu_state.abrt) return 1;
setadd32nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
break;
case 0x08: /*DEC l*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp - 1); if (cpu_state.abrt) return 1;
setsub32nc(temp, 1);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
break;
case 0x10: /*CALL*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(cpu_state.pc); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN((cpu_mod == 3) ? 7 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1);
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1;
CALL_FAR_l(new_cs, new_pc);
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,cgate16 ? 2:0,cgate16 ? 0:2, 1);
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
if (is486) CLOCK_CYCLES(5);
else CLOCK_CYCLES((cpu_mod == 3) ? 7 : 10);
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1);
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
oxpc = cpu_state.pc;
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH l*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(temp);
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1);
break;
default:
// fatal("Bad FF opcode %02X\n",rmdat&0x38);
x86illegal();
}
return cpu_state.abrt;
}

619
src/codegen/x86_ops_shift.h Normal file
View File

@@ -0,0 +1,619 @@
#define OP_SHIFT_b(c, ea32) \
{ \
uint8_t temp_orig = temp; \
if (!c) return 0; \
flags_rebuild(); \
switch (rmdat & 0x38) \
{ \
case 0x00: /*ROL b, c*/ \
temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \
seteab(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp & 1) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 7)) & 1) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x08: /*ROR b,CL*/ \
temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \
seteab(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp & 0x80) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x10: /*RCL b,CL*/ \
temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
tempc = temp2 ? 1 : 0; \
temp2 = temp & 0x80; \
temp = (temp << 1) | tempc; \
c--; \
} \
seteab(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp2) cpu_state.flags |= C_FLAG; \
if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x18: /*RCR b,CL*/ \
temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
tempc = temp2 ? 0x80 : 0; \
temp2 = temp & 1; \
temp = (temp >> 1) | tempc; \
c--; \
} \
seteab(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp2) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x20: case 0x30: /*SHL b,CL*/ \
seteab(temp << c); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SHL8, temp_orig, c, (temp << c) & 0xff); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x28: /*SHR b,CL*/ \
seteab(temp >> c); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x38: /*SAR b,CL*/ \
temp = (int8_t)temp >> c; \
seteab(temp); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SAR8, temp_orig, c, temp); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
} \
}
#define OP_SHIFT_w(c, ea32) \
{ \
uint16_t temp_orig = temp; \
if (!c) return 0; \
flags_rebuild(); \
switch (rmdat & 0x38) \
{ \
case 0x00: /*ROL w, c*/ \
temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \
seteaw(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp & 1) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 15)) & 1) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x08: /*ROR w,CL*/ \
temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \
seteaw(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp & 0x8000) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x10: /*RCL w, c*/ \
temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
tempc = temp2 ? 1 : 0; \
temp2 = temp & 0x8000; \
temp = (temp << 1) | tempc; \
c--; \
} \
seteaw(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp2) cpu_state.flags |= C_FLAG; \
if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x18: /*RCR w, c*/ \
temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
tempc = temp2 ? 0x8000 : 0; \
temp2 = temp & 1; \
temp = (temp >> 1) | tempc; \
c--; \
} \
seteaw(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp2) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x20: case 0x30: /*SHL w, c*/ \
seteaw(temp << c); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SHL16, temp_orig, c, (temp << c) & 0xffff); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x28: /*SHR w, c*/ \
seteaw(temp >> c); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x38: /*SAR w, c*/ \
temp = (int16_t)temp >> c; \
seteaw(temp); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SAR16, temp_orig, c, temp); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
} \
}
#define OP_SHIFT_l(c, ea32) \
{ \
uint32_t temp_orig = temp; \
if (!c) return 0; \
flags_rebuild(); \
switch (rmdat & 0x38) \
{ \
case 0x00: /*ROL l, c*/ \
temp = (temp << c) | (temp >> (32-c)); \
seteal(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp & 1) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 31)) & 1) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x08: /*ROR l,CL*/ \
temp = (temp >> c) | (temp << (32-c)); \
seteal(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp & 0x80000000) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x10: /*RCL l, c*/ \
temp2 = CF_SET(); \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
tempc = temp2 ? 1 : 0; \
temp2 = temp & 0x80000000; \
temp = (temp << 1) | tempc; \
c--; \
} \
seteal(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp2) cpu_state.flags |= C_FLAG; \
if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
case 0x18: /*RCR l, c*/ \
temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
tempc = temp2 ? 0x80000000 : 0; \
temp2 = temp & 1; \
temp = (temp >> 1) | tempc; \
c--; \
} \
seteal(temp); if (cpu_state.abrt) return 1; \
cpu_state.flags &= ~(C_FLAG | V_FLAG); \
if (temp2) cpu_state.flags |= C_FLAG; \
if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
case 0x20: case 0x30: /*SHL l, c*/ \
seteal(temp << c); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
case 0x28: /*SHR l, c*/ \
seteal(temp >> c); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
case 0x38: /*SAR l, c*/ \
temp = (int32_t)temp >> c; \
seteal(temp); if (cpu_state.abrt) return 1; \
set_flags_shift(FLAGS_SAR32, temp_orig, c, temp); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
} \
}
static int opC0_a16(uint32_t fetchdat)
{
int c;
int tempc;
uint8_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 0);
return 0;
}
static int opC0_a32(uint32_t fetchdat)
{
int c;
int tempc;
uint8_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 1);
return 0;
}
static int opC1_w_a16(uint32_t fetchdat)
{
int c;
int tempc;
uint16_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 0);
return 0;
}
static int opC1_w_a32(uint32_t fetchdat)
{
int c;
int tempc;
uint16_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 1);
return 0;
}
static int opC1_l_a16(uint32_t fetchdat)
{
int c;
int tempc;
uint32_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 0);
return 0;
}
static int opC1_l_a32(uint32_t fetchdat)
{
int c;
int tempc;
uint32_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 1);
return 0;
}
static int opD0_a16(uint32_t fetchdat)
{
int c = 1;
int tempc;
uint8_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 0);
return 0;
}
static int opD0_a32(uint32_t fetchdat)
{
int c = 1;
int tempc;
uint8_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 1);
return 0;
}
static int opD1_w_a16(uint32_t fetchdat)
{
int c = 1;
int tempc;
uint16_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 0);
return 0;
}
static int opD1_w_a32(uint32_t fetchdat)
{
int c = 1;
int tempc;
uint16_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 1);
return 0;
}
static int opD1_l_a16(uint32_t fetchdat)
{
int c = 1;
int tempc;
uint32_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 0);
return 0;
}
static int opD1_l_a32(uint32_t fetchdat)
{
int c = 1;
int tempc;
uint32_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 1);
return 0;
}
static int opD2_a16(uint32_t fetchdat)
{
int c;
int tempc;
uint8_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 0);
return 0;
}
static int opD2_a32(uint32_t fetchdat)
{
int c;
int tempc;
uint8_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 1);
return 0;
}
static int opD3_w_a16(uint32_t fetchdat)
{
int c;
int tempc;
uint16_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 0);
return 0;
}
static int opD3_w_a32(uint32_t fetchdat)
{
int c;
int tempc;
uint16_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 1);
return 0;
}
static int opD3_l_a16(uint32_t fetchdat)
{
int c;
int tempc;
uint32_t temp, temp2 = 0;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 0);
return 0;
}
static int opD3_l_a32(uint32_t fetchdat)
{
int c;
int tempc;
uint32_t temp, temp2 = 0;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 1);
return 0;
}
#define SHLD_w() \
if (count) \
{ \
int tempc; \
uint32_t templ; \
uint16_t tempw = geteaw(); if (cpu_state.abrt) return 1; \
tempc = ((tempw << (count - 1)) & (1 << 15)) ? 1 : 0; \
templ = (tempw << 16) | cpu_state.regs[cpu_reg].w; \
if (count <= 16) tempw = templ >> (16 - count); \
else tempw = (templ << count) >> 16; \
seteaw(tempw); if (cpu_state.abrt) return 1; \
setznp16(tempw); \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
}
#define SHLD_l() \
if (count) \
{ \
int tempc; \
uint32_t templ = geteal(); if (cpu_state.abrt) return 1; \
tempc = ((templ << (count - 1)) & (1 << 31)) ? 1 : 0; \
templ = (templ << count) | (cpu_state.regs[cpu_reg].l >> (32 - count)); \
seteal(templ); if (cpu_state.abrt) return 1; \
setznp32(templ); \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
}
#define SHRD_w() \
if (count) \
{ \
int tempc; \
uint32_t templ; \
uint16_t tempw = geteaw(); if (cpu_state.abrt) return 1; \
tempc = (tempw >> (count - 1)) & 1; \
templ = tempw | (cpu_state.regs[cpu_reg].w << 16); \
tempw = templ >> count; \
seteaw(tempw); if (cpu_state.abrt) return 1; \
setznp16(tempw); \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
}
#define SHRD_l() \
if (count) \
{ \
int tempc; \
uint32_t templ = geteal(); if (cpu_state.abrt) return 1; \
tempc = (templ >> (count - 1)) & 1; \
templ = (templ >> count) | (cpu_state.regs[cpu_reg].l << (32 - count)); \
seteal(templ); if (cpu_state.abrt) return 1; \
setznp32(templ); \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
}
#define opSHxD(operation) \
static int op ## operation ## _i_a16(uint32_t fetchdat) \
{ \
int count; \
\
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = getbyte() & 31; \
operation() \
\
CLOCK_CYCLES(3); \
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); \
return 0; \
} \
static int op ## operation ## _CL_a16(uint32_t fetchdat) \
{ \
int count; \
\
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = CL & 31; \
operation() \
\
CLOCK_CYCLES(3); \
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); \
return 0; \
} \
static int op ## operation ## _i_a32(uint32_t fetchdat) \
{ \
int count; \
\
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = getbyte() & 31; \
operation() \
\
CLOCK_CYCLES(3); \
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); \
return 0; \
} \
static int op ## operation ## _CL_a32(uint32_t fetchdat) \
{ \
int count; \
\
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = CL & 31; \
operation() \
\
CLOCK_CYCLES(3); \
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); \
return 0; \
}
opSHxD(SHLD_w)
opSHxD(SHLD_l)
opSHxD(SHRD_w)
opSHxD(SHRD_l)

2607
src/codegen/x86seg.c Normal file

File diff suppressed because it is too large Load Diff