Merge pull request #2878 from jriwanek-forks/formatting

Even more formatting
This commit is contained in:
Jasmine Iwanek
2022-11-19 13:43:08 -05:00
committed by GitHub
378 changed files with 77846 additions and 75590 deletions

View File

@@ -769,7 +769,7 @@ usage:
for (i = 0; i < FDD_NUM; i++) {
if (fn[i] != NULL) {
if (strlen(fn[i]) <= 511)
if (strlen(fn[i]) <= 511)
strncpy(floppyfns[i], fn[i], 511);
free(fn[i]);
fn[i] = NULL;

View File

@@ -135,7 +135,7 @@ static track_file_t *
bin_init(const char *filename, int *error)
{
track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t));
struct stat stats;
struct stat stats;
if (tf == NULL) {
*error = 1;

View File

@@ -15,10 +15,10 @@
* Copyright 2022 RichardG.
*/
#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif
#define __STDC_FORMAT_MACROS
#include <ctype.h>

View File

@@ -35,7 +35,7 @@
typedef struct
{
uint8_t idx, is_pci,
regs[16];
regs[16];
} opti5x7_t;
#ifdef ENABLE_OPTI5X7_LOG

View File

@@ -42,8 +42,8 @@
typedef struct
{
uint8_t irq_convert,
pci_regs[256];
uint8_t irq_convert,
pci_regs[256];
} opti822_t;
// #define ENABLE_OPTI822_LOG 1
@@ -56,13 +56,13 @@ opti822_log(const char *fmt, ...)
va_list ap;
if (opti822_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti822_log(fmt, ...)
# define opti822_log(fmt, ...)
#endif
/* NOTE: We currently cheat and pass all PCI shadow RAM accesses to ISA as well.
@@ -71,13 +71,13 @@ opti822_log(const char *fmt, ...)
static void
opti822_recalc(opti822_t *dev)
{
int i, reg, bit_r, bit_w;
int state;
int i, reg, bit_r, bit_w;
int state;
uint32_t base;
for (i = 0; i < 12; i++) {
base = 0x000c0000 + (i << 14);
reg = 0x44 + ((i >> 2) ^ 3);
base = 0x000c0000 + (i << 14);
reg = 0x44 + ((i >> 2) ^ 3);
bit_w = (i & 3);
bit_r = bit_w + 4;
bit_w = 1 << bit_w;
@@ -99,19 +99,19 @@ static void
opti822_update_irqs(opti822_t *dev, int set)
{
uint8_t val;
int i, reg;
int shift, irq;
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
pic_t *temp_pic;
int i, reg;
int shift, irq;
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
pic_t *temp_pic;
// dev->irq_convert = (dev->pci_regs[0x53] & 0x08);
dev->irq_convert = 1;
for (i = 0; i < 16; i++) {
reg = 0x88 + (i >> 1);
reg = 0x88 + (i >> 1);
shift = (i & 1) << 2;
val = (dev->pci_regs[reg] >> shift) & 0x0f;
irq = irq_map[val & 0x07];
val = (dev->pci_regs[reg] >> shift) & 0x0f;
irq = irq_map[val & 0x07];
if (irq == -1)
continue;
temp_pic = (irq >= 8) ? &pic2 : &pic;
@@ -127,8 +127,8 @@ static void
opti822_pci_write(int func, int addr, uint8_t val, void *priv)
{
opti822_t *dev = (opti822_t *) priv;
int irq, irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
int pin, slot;
int irq, irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
int pin, slot;
opti822_log("opti822_write(%02X, %02X, %02X)\n", func, addr, val);
@@ -144,7 +144,7 @@ opti822_pci_write(int func, int addr, uint8_t val, void *priv)
/* Status Register */
case 0x06:
if (!(dev->pci_regs[0x52] & 0x04))
dev->pci_regs[addr] = (val & 0x80);
dev->pci_regs[addr] = (val & 0x80);
break;
case 0x07:
dev->pci_regs[addr] &= ~(val & 0xf9);
@@ -293,33 +293,33 @@ opti822_pci_write(int func, int addr, uint8_t val, void *priv)
dev->pci_regs[addr] = val;
break;
case 0x88 ... 0x8f:
dev->pci_regs[addr] = val;
opti822_update_irqs(dev, 0);
irq = irq_map[val & 0x07];
pin = 4 - ((addr & 0x01) << 1);
slot = ((addr & 0x06) >> 1);
if (irq >= 0) {
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
pci_set_irq_routing(pin + (slot << 2), irq);
pci_set_irq_level(pin + (slot << 2), !!(val & 0x07));
} else {
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
}
irq = irq_map[(val >> 4) & 0x07];
pin = 3 - ((addr & 0x01) << 1);
slot = ((addr & 0x06) >> 1);
if (irq >= 0) {
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
pci_set_irq_routing(pin + (slot << 2), irq);
pci_set_irq_level(pin + (slot << 2), !!((val >> 4) & 0x07));
} else {
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
}
opti822_update_irqs(dev, 1);
break;
case 0x88 ... 0x8f:
dev->pci_regs[addr] = val;
opti822_update_irqs(dev, 0);
irq = irq_map[val & 0x07];
pin = 4 - ((addr & 0x01) << 1);
slot = ((addr & 0x06) >> 1);
if (irq >= 0) {
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
pci_set_irq_routing(pin + (slot << 2), irq);
pci_set_irq_level(pin + (slot << 2), !!(val & 0x07));
} else {
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
}
irq = irq_map[(val >> 4) & 0x07];
pin = 3 - ((addr & 0x01) << 1);
slot = ((addr & 0x06) >> 1);
if (irq >= 0) {
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
pci_set_irq_routing(pin + (slot << 2), irq);
pci_set_irq_level(pin + (slot << 2), !!((val >> 4) & 0x07));
} else {
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
}
opti822_update_irqs(dev, 1);
break;
}
}
@@ -327,7 +327,7 @@ static uint8_t
opti822_pci_read(int func, int addr, void *priv)
{
opti822_t *dev = (opti822_t *) priv;
uint8_t ret;
uint8_t ret;
ret = 0xff;
@@ -343,12 +343,14 @@ static void
opti822_reset(void *priv)
{
opti822_t *dev = (opti822_t *) priv;
int i;
int i;
memset(dev->pci_regs, 0, 256);
dev->pci_regs[0x00] = 0x45; dev->pci_regs[0x01] = 0x10; /*OPTi*/
dev->pci_regs[0x02] = 0x22; dev->pci_regs[0x03] = 0xc8; /*82C822 PCIB*/
dev->pci_regs[0x00] = 0x45;
dev->pci_regs[0x01] = 0x10; /*OPTi*/
dev->pci_regs[0x02] = 0x22;
dev->pci_regs[0x03] = 0xc8; /*82C822 PCIB*/
dev->pci_regs[0x04] = 0x07;
dev->pci_regs[0x06] = 0x80;
dev->pci_regs[0x07] = 0x02;
@@ -356,7 +358,8 @@ opti822_reset(void *priv)
dev->pci_regs[0x0b] = 0x06;
dev->pci_regs[0x0d] = 0x20;
dev->pci_regs[0x40] = 0x01; dev->pci_regs[0x41] = 0x0c;
dev->pci_regs[0x40] = 0x01;
dev->pci_regs[0x41] = 0x0c;
dev->pci_regs[0x43] = 0x02;
dev->pci_regs[0x52] = 0x06;
dev->pci_regs[0x53] = 0x90;
@@ -370,7 +373,7 @@ opti822_reset(void *priv)
static void
opti822_close(void *p)
{
opti822_t *dev = (opti822_t *)p;
opti822_t *dev = (opti822_t *) p;
free(dev);
}

View File

@@ -16,21 +16,23 @@ void (*codegen_timing_block_start)(void);
void (*codegen_timing_block_end)(void);
int (*codegen_timing_jump_cycles)(void);
void codegen_timing_set(codegen_timing_t *timing)
void
codegen_timing_set(codegen_timing_t *timing)
{
codegen_timing_start = timing->start;
codegen_timing_prefix = timing->prefix;
codegen_timing_opcode = timing->opcode;
codegen_timing_block_start = timing->block_start;
codegen_timing_block_end = timing->block_end;
codegen_timing_jump_cycles = timing->jump_cycles;
codegen_timing_start = timing->start;
codegen_timing_prefix = timing->prefix;
codegen_timing_opcode = timing->opcode;
codegen_timing_block_start = timing->block_start;
codegen_timing_block_end = timing->block_end;
codegen_timing_jump_cycles = timing->jump_cycles;
}
int codegen_in_recompile;
/* This is for compatibility with new x87 code. */
void codegen_set_rounding_mode(int mode)
void
codegen_set_rounding_mode(int mode)
{
/* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10);
/* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10);
}

View File

@@ -41,11 +41,11 @@
#include "x86_ops.h"
#ifdef __amd64__
#include "codegen_x86-64.h"
# include "codegen_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64
#include "codegen_x86.h"
# include "codegen_x86.h"
#else
#error Dynamic recompiler not implemented on your platform
# error Dynamic recompiler not implemented on your platform
#endif
/*Handling self-modifying code (of which there is a lot on x86) :
@@ -73,38 +73,37 @@
same page).
*/
typedef struct codeblock_t
{
uint64_t page_mask, page_mask2;
uint64_t *dirty_mask, *dirty_mask2;
uint64_t cmp;
typedef struct codeblock_t {
uint64_t page_mask, page_mask2;
uint64_t *dirty_mask, *dirty_mask2;
uint64_t cmp;
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
struct codeblock_t *prev, *next;
struct codeblock_t *prev_2, *next_2;
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
struct codeblock_t *prev, *next;
struct codeblock_t *prev_2, *next_2;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
struct codeblock_t *parent, *left, *right;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
struct codeblock_t *parent, *left, *right;
int pnt;
int ins;
int pnt;
int ins;
int valid;
int was_recompiled;
int TOP;
int was_recompiled;
int TOP;
uint32_t pc;
uint32_t _cs;
uint32_t endpc;
uint32_t phys, phys_2;
uint32_t status;
uint32_t flags;
uint32_t pc;
uint32_t _cs;
uint32_t endpc;
uint32_t phys, phys_2;
uint32_t status;
uint32_t flags;
uint8_t data[2048];
uint8_t data[2048];
} codeblock_t;
/*Code block uses FPU*/
@@ -112,181 +111,155 @@ typedef struct codeblock_t
/*Code block is always entered with the same FPU top-of-stack*/
#define CODEBLOCK_STATIC_TOP 2
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
static inline codeblock_t *
codeblock_tree_find(uint32_t phys, uint32_t _cs)
{
codeblock_t *block = pages[phys >> 12].head;
uint64_t a = _cs | ((uint64_t)phys << 32);
codeblock_t *block = pages[phys >> 12].head;
uint64_t a = _cs | ((uint64_t) phys << 32);
while (block)
{
if (a == block->cmp)
{
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
break;
}
if (a < block->cmp)
block = block->left;
else
block = block->right;
}
return block;
}
static inline void codeblock_tree_add(codeblock_t *new_block)
{
codeblock_t *block = pages[new_block->phys >> 12].head;
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
new_block->cmp = a;
if (!block)
{
pages[new_block->phys >> 12].head = new_block;
new_block->parent = new_block->left = new_block->right = NULL;
while (block) {
if (a == block->cmp) {
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
break;
}
if (a < block->cmp)
block = block->left;
else
{
codeblock_t *old_block = NULL;
block = block->right;
}
while (block)
{
old_block = block;
if (a < old_block->cmp)
block = block->left;
else
block = block->right;
}
if (a < old_block->cmp)
old_block->left = new_block;
else
old_block->right = new_block;
new_block->parent = old_block;
new_block->left = new_block->right = NULL;
}
return block;
}
static inline void codeblock_tree_delete(codeblock_t *block)
static inline void
codeblock_tree_add(codeblock_t *new_block)
{
codeblock_t *parent = block->parent;
codeblock_t *block = pages[new_block->phys >> 12].head;
uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32);
new_block->cmp = a;
if (!block->left && !block->right)
{
/*Easy case - remove from parent*/
if (!parent)
pages[block->phys >> 12].head = NULL;
else
{
if (parent->left == block)
parent->left = NULL;
if (parent->right == block)
parent->right = NULL;
}
return;
}
else if (!block->left)
{
/*Only right node*/
if (!parent)
{
pages[block->phys >> 12].head = block->right;
pages[block->phys >> 12].head->parent = NULL;
}
else
{
if (parent->left == block)
{
parent->left = block->right;
parent->left->parent = parent;
}
if (parent->right == block)
{
parent->right = block->right;
parent->right->parent = parent;
}
}
return;
}
else if (!block->right)
{
/*Only left node*/
if (!parent)
{
pages[block->phys >> 12].head = block->left;
pages[block->phys >> 12].head->parent = NULL;
}
else
{
if (parent->left == block)
{
parent->left = block->left;
parent->left->parent = parent;
}
if (parent->right == block)
{
parent->right = block->left;
parent->right->parent = parent;
}
}
return;
if (!block) {
pages[new_block->phys >> 12].head = new_block;
new_block->parent = new_block->left = new_block->right = NULL;
} else {
codeblock_t *old_block = NULL;
while (block) {
old_block = block;
if (a < old_block->cmp)
block = block->left;
else
block = block->right;
}
if (a < old_block->cmp)
old_block->left = new_block;
else
{
/*Difficult case - node has two children. Walk right child to find lowest node*/
codeblock_t *lowest = block->right, *highest;
codeblock_t *old_parent;
old_block->right = new_block;
while (lowest->left)
lowest = lowest->left;
old_parent = lowest->parent;
/*Replace deleted node with lowest node*/
if (!parent)
pages[block->phys >> 12].head = lowest;
else
{
if (parent->left == block)
parent->left = lowest;
if (parent->right == block)
parent->right = lowest;
}
lowest->parent = parent;
lowest->left = block->left;
if (lowest->left)
lowest->left->parent = lowest;
old_parent->left = NULL;
highest = lowest->right;
if (!highest)
{
if (lowest != block->right)
{
lowest->right = block->right;
block->right->parent = lowest;
}
return;
}
while (highest->right)
highest = highest->right;
if (block->right && block->right != lowest)
{
highest->right = block->right;
block->right->parent = highest;
}
}
new_block->parent = old_block;
new_block->left = new_block->right = NULL;
}
}
#define PAGE_MASK_INDEX_MASK 3
static inline void
codeblock_tree_delete(codeblock_t *block)
{
codeblock_t *parent = block->parent;
if (!block->left && !block->right) {
/*Easy case - remove from parent*/
if (!parent)
pages[block->phys >> 12].head = NULL;
else {
if (parent->left == block)
parent->left = NULL;
if (parent->right == block)
parent->right = NULL;
}
return;
} else if (!block->left) {
/*Only right node*/
if (!parent) {
pages[block->phys >> 12].head = block->right;
pages[block->phys >> 12].head->parent = NULL;
} else {
if (parent->left == block) {
parent->left = block->right;
parent->left->parent = parent;
}
if (parent->right == block) {
parent->right = block->right;
parent->right->parent = parent;
}
}
return;
} else if (!block->right) {
/*Only left node*/
if (!parent) {
pages[block->phys >> 12].head = block->left;
pages[block->phys >> 12].head->parent = NULL;
} else {
if (parent->left == block) {
parent->left = block->left;
parent->left->parent = parent;
}
if (parent->right == block) {
parent->right = block->left;
parent->right->parent = parent;
}
}
return;
} else {
/*Difficult case - node has two children. Walk right child to find lowest node*/
codeblock_t *lowest = block->right, *highest;
codeblock_t *old_parent;
while (lowest->left)
lowest = lowest->left;
old_parent = lowest->parent;
/*Replace deleted node with lowest node*/
if (!parent)
pages[block->phys >> 12].head = lowest;
else {
if (parent->left == block)
parent->left = lowest;
if (parent->right == block)
parent->right = lowest;
}
lowest->parent = parent;
lowest->left = block->left;
if (lowest->left)
lowest->left->parent = lowest;
old_parent->left = NULL;
highest = lowest->right;
if (!highest) {
if (lowest != block->right) {
lowest->right = block->right;
block->right->parent = lowest;
}
return;
}
while (highest->right)
highest = highest->right;
if (block->right && block->right != lowest) {
highest->right = block->right;
block->right->parent = highest;
}
}
}
#define PAGE_MASK_INDEX_MASK 3
#define PAGE_MASK_INDEX_SHIFT 10
#define PAGE_MASK_MASK 63
#define PAGE_MASK_SHIFT 4
#define PAGE_MASK_MASK 63
#define PAGE_MASK_SHIFT 4
extern codeblock_t *codeblock;
@@ -305,7 +278,7 @@ extern void codegen_set_op32(void);
extern void codegen_flush(void);
extern void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr);
extern int cpu_block_end;
extern int cpu_block_end;
extern uint32_t codegen_endpc;
extern int codegen_block_cycles;
@@ -317,14 +290,13 @@ extern void (*codegen_timing_block_start)(void);
extern void (*codegen_timing_block_end)(void);
extern int (*codegen_timing_jump_cycles)(void);
typedef struct codegen_timing_t
{
void (*start)(void);
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)(void);
void (*block_end)(void);
int (*jump_cycles)(void);
typedef struct codegen_timing_t {
void (*start)(void);
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)(void);
void (*block_end)(void);
int (*jump_cycles)(void);
} codegen_timing_t;
extern codegen_timing_t codegen_timing_pentium;
@@ -342,53 +314,53 @@ extern int block_pos;
#define CPU_BLOCK_END() cpu_block_end = 1
static inline void addbyte(uint8_t val)
static inline void
addbyte(uint8_t val)
{
codeblock[block_current].data[block_pos++] = val;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
codeblock[block_current].data[block_pos++] = val;
if (block_pos >= BLOCK_MAX) {
CPU_BLOCK_END();
}
}
static inline void addword(uint16_t val)
static inline void
addword(uint16_t val)
{
uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos];
*p = val;
block_pos += 2;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
*p = val;
block_pos += 2;
if (block_pos >= BLOCK_MAX) {
CPU_BLOCK_END();
}
}
static inline void addlong(uint32_t val)
static inline void
addlong(uint32_t val)
{
uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos];
*p = val;
block_pos += 4;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
*p = val;
block_pos += 4;
if (block_pos >= BLOCK_MAX) {
CPU_BLOCK_END();
}
}
static inline void addquad(uint64_t val)
static inline void
addquad(uint64_t val)
{
uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos];
*p = val;
block_pos += 8;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
*p = val;
block_pos += 8;
if (block_pos >= BLOCK_MAX) {
CPU_BLOCK_END();
}
}
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern uint32_t op_old_pc;
/*Set to 1 if flags have been changed in the block being recompiled, and hence

View File

@@ -1,8 +1,7 @@
enum
{
ACCREG_cycles = 0,
enum {
ACCREG_cycles = 0,
ACCREG_COUNT
ACCREG_COUNT
};
struct ir_data_t;

View File

@@ -9,59 +9,61 @@
static struct
{
int count;
uintptr_t dest_reg;
} acc_regs[] =
{
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)},
int count;
uintptr_t dest_reg;
} acc_regs[] = {
[ACCREG_cycles] = {0, (uintptr_t) & (cycles)},
};
void codegen_accumulate(int acc_reg, int delta)
void
codegen_accumulate(int acc_reg, int delta)
{
acc_regs[acc_reg].count += delta;
acc_regs[acc_reg].count += delta;
#ifdef USE_ACYCS
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
if (delta == -1) {
/* -delta = 1 */
addbyte(0xff); /*inc dword ptr[&acycs]*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t) (uintptr_t) &(acycs));
} else if (delta == 1) {
/* -delta = -1 */
addbyte(0xff); /*dec dword ptr[&acycs]*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t) (uintptr_t) &(acycs));
} else {
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t) (uintptr_t) &(acycs));
addlong(-delta);
}
}
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
if (delta == -1) {
/* -delta = 1 */
addbyte(0xff); /*inc dword ptr[&acycs]*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t) (uintptr_t) & (acycs));
} else if (delta == 1) {
/* -delta = -1 */
addbyte(0xff); /*dec dword ptr[&acycs]*/
addbyte(0x0c);
addbyte(0x25);
addlong((uint32_t) (uintptr_t) & (acycs));
} else {
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
addbyte(0x04);
addbyte(0x25);
addlong((uint32_t) (uintptr_t) & (acycs));
addlong(-delta);
}
}
#endif
}
void codegen_accumulate_flush(void)
void
codegen_accumulate_flush(void)
{
if (acc_regs[0].count) {
/* To reduce the size of the generated code, we take advantage of
the fact that the target offset points to _cycles within cpu_state,
so we can just use our existing infrastracture for variables
relative to cpu_state. */
addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/
addbyte(0x45);
addbyte((uint8_t)cpu_state_offset(_cycles));
addlong(acc_regs[0].count);
}
if (acc_regs[0].count) {
/* To reduce the size of the generated code, we take advantage of
the fact that the target offset points to _cycles within cpu_state,
so we can just use our existing infrastracture for variables
relative to cpu_state. */
addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/
addbyte(0x45);
addbyte((uint8_t) cpu_state_offset(_cycles));
addlong(acc_regs[0].count);
}
acc_regs[0].count = 0;
acc_regs[0].count = 0;
}
void codegen_accumulate_reset(void)
void
codegen_accumulate_reset(void)
{
acc_regs[0].count = 0;
acc_regs[0].count = 0;
}

View File

@@ -9,56 +9,58 @@
static struct
{
int count;
uintptr_t dest_reg;
} acc_regs[] =
{
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)}
int count;
uintptr_t dest_reg;
} acc_regs[] = {
[ACCREG_cycles] = {0, (uintptr_t) & (cycles)}
};
void codegen_accumulate(int acc_reg, int delta)
void
codegen_accumulate(int acc_reg, int delta)
{
acc_regs[acc_reg].count += delta;
acc_regs[acc_reg].count += delta;
#ifdef USE_ACYCS
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
if (delta == -1) {
/* -delta = 1 */
addbyte(0xff); /*inc dword ptr[&acycs]*/
addbyte(0x05);
addlong((uint32_t) (uintptr_t) &(acycs));
} else if (delta == 1) {
/* -delta = -1 */
addbyte(0xff); /*dec dword ptr[&acycs]*/
addbyte(0x0d);
addlong((uint32_t) (uintptr_t) &(acycs));
} else {
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
addbyte(0x05);
addlong((uint32_t) (uintptr_t) &(acycs));
addlong((uintptr_t) -delta);
}
}
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
if (delta == -1) {
/* -delta = 1 */
addbyte(0xff); /*inc dword ptr[&acycs]*/
addbyte(0x05);
addlong((uint32_t) (uintptr_t) & (acycs));
} else if (delta == 1) {
/* -delta = -1 */
addbyte(0xff); /*dec dword ptr[&acycs]*/
addbyte(0x0d);
addlong((uint32_t) (uintptr_t) & (acycs));
} else {
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
addbyte(0x05);
addlong((uint32_t) (uintptr_t) & (acycs));
addlong((uintptr_t) -delta);
}
}
#endif
}
void codegen_accumulate_flush(void)
void
codegen_accumulate_flush(void)
{
if (acc_regs[0].count) {
/* To reduce the size of the generated code, we take advantage of
the fact that the target offset points to _cycles within cpu_state,
so we can just use our existing infrastracture for variables
relative to cpu_state. */
addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/
addbyte(0x45);
addbyte((uint8_t)cpu_state_offset(_cycles));
addlong(acc_regs[0].count);
}
if (acc_regs[0].count) {
/* To reduce the size of the generated code, we take advantage of
the fact that the target offset points to _cycles within cpu_state,
so we can just use our existing infrastracture for variables
relative to cpu_state. */
addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/
addbyte(0x45);
addbyte((uint8_t) cpu_state_offset(_cycles));
addlong(acc_regs[0].count);
}
acc_regs[0].count = 0;
acc_regs[0].count = 0;
}
void codegen_accumulate_reset(void)
void
codegen_accumulate_reset(void)
{
acc_regs[0].count = 0;
acc_regs[0].count = 0;
}

View File

@@ -16,9 +16,9 @@
#include "codegen_ops.h"
#if defined __amd64__ || defined _M_X64
#include "codegen_ops_x86-64.h"
# include "codegen_ops_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
#include "codegen_ops_x86.h"
# include "codegen_ops_x86.h"
#endif
#include "codegen_ops_arith.h"
@@ -32,8 +32,8 @@
#include "codegen_ops_stack.h"
#include "codegen_ops_xchg.h"
RecompOpFn recomp_opcodes[512] =
{
RecompOpFn recomp_opcodes[512] = {
// clang-format off
/*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,
@@ -77,10 +77,11 @@ RecompOpFn recomp_opcodes[512] =
/*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
// clang-format on
};
RecompOpFn recomp_opcodes_0f[512] =
{
RecompOpFn recomp_opcodes_0f[512] = {
// clang-format off
/*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,
@@ -124,11 +125,11 @@ RecompOpFn recomp_opcodes_0f[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_d8[512] =
{
RecompOpFn recomp_opcodes_d8[512] = {
// clang-format off
/*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,
@@ -172,10 +173,11 @@ RecompOpFn recomp_opcodes_d8[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_d9[512] =
{
RecompOpFn recomp_opcodes_d9[512] = {
// clang-format off
/*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,
@@ -219,10 +221,11 @@ RecompOpFn recomp_opcodes_d9[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_da[512] =
{
RecompOpFn recomp_opcodes_da[512] = {
// clang-format off
/*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,
@@ -266,10 +269,11 @@ RecompOpFn recomp_opcodes_da[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_db[512] =
{
RecompOpFn recomp_opcodes_db[512] = {
// clang-format off
/*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,
@@ -313,10 +317,11 @@ RecompOpFn recomp_opcodes_db[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_dc[512] =
{
RecompOpFn recomp_opcodes_dc[512] = {
// clang-format off
/*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,
@@ -360,10 +365,11 @@ RecompOpFn recomp_opcodes_dc[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_dd[512] =
{
RecompOpFn recomp_opcodes_dd[512] = {
// clang-format off
/*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,
@@ -407,10 +413,11 @@ RecompOpFn recomp_opcodes_dd[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_de[512] =
{
RecompOpFn recomp_opcodes_de[512] = {
// clang-format off
/*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,
@@ -454,10 +461,11 @@ RecompOpFn recomp_opcodes_de[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_df[512] =
{
RecompOpFn recomp_opcodes_df[512] = {
// clang-format off
/*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,
@@ -501,10 +509,11 @@ RecompOpFn recomp_opcodes_df[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_REPE[512] =
{
RecompOpFn recomp_opcodes_REPE[512] = {
// clang-format off
/*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,
@@ -548,10 +557,11 @@ RecompOpFn recomp_opcodes_REPE[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_REPNE[512] =
{
RecompOpFn recomp_opcodes_REPNE[512] = {
// clang-format off
/*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,
@@ -595,4 +605,5 @@ RecompOpFn recomp_opcodes_REPNE[512] =
/*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,
// clang-format on
};

View File

@@ -26,21 +26,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512];
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AL 0
#define REG_AH 4
#define REG_CL 1
#define REG_CH 5
#define REG_DL 2
#define REG_DH 6
#define REG_BL 3
#define REG_BH 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AL 0
#define REG_AH 4
#define REG_CL 1
#define REG_CH 5
#define REG_DL 2
#define REG_DH 6
#define REG_BL 3
#define REG_BH 7
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,256 +1,268 @@
static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_ENTER();
FP_FXCH(opcode & 7);
FP_FXCH(opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_ENTER();
FP_FLD(opcode & 7);
FP_FLD(opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_ENTER();
FP_FST(opcode & 7);
FP_FST(opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_ENTER();
FP_FST(opcode & 7);
FP_POP();
FP_FST(opcode & 7);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_LOAD_S();
FP_LOAD_S();
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_D();
FP_LOAD_D();
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
FP_LOAD_IW();
FP_LOAD_IW();
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_LOAD_IL();
FP_LOAD_IL();
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_IQ();
FP_LOAD_IQ();
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1;
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1;
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG(0);
host_reg = FP_LOAD_REG(0);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg1, host_reg2 = 0;
x86seg *target_seg;
int host_reg1, host_reg2 = 0;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_LOAD_REG_D(0, &host_reg1, &host_reg2);
FP_LOAD_REG_D(0, &host_reg1, &host_reg2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
FP_POP();
return new_pc;
return new_pc;
}
static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block);
uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
FP_POP();
return new_pc;
return new_pc;
}
#define ropFarith(name, size, load, op) \
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
x86seg *target_seg; \
\
FP_ENTER(); \
op_pc--; \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
load(target_seg); \
\
op(FPU_ ## name); \
\
return op_pc + 1; \
}
#define ropFarith(name, size, load, op) \
static uint32_t ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
x86seg *target_seg; \
\
FP_ENTER(); \
op_pc--; \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
load(target_seg); \
\
op(FPU_##name); \
\
return op_pc + 1; \
}
ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
#define ropFcompare(name, size, load, op) \
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
x86seg *target_seg; \
\
FP_ENTER(); \
op_pc--; \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
load(target_seg); \
\
op(); \
\
return op_pc + 1; \
} \
static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \
\
FP_POP(); \
\
return new_pc; \
}
#define ropFcompare(name, size, load, op) \
static uint32_t ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
x86seg *target_seg; \
\
FP_ENTER(); \
op_pc--; \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
load(target_seg); \
\
op(); \
\
return op_pc + 1; \
} \
static uint32_t ropF##name##P##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t new_pc = ropF##name##size(opcode, fetchdat, op_32, op_pc, block); \
\
FP_POP(); \
\
return new_pc; \
}
ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S);
ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D);
@@ -326,320 +338,346 @@ static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint
return op_pc + 1;
}*/
static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, 0, opcode & 7);
FP_ENTER();
FP_OP_REG(FPU_ADD, 0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_COMPARE_REG(0, opcode & 7);
FP_ENTER();
FP_COMPARE_REG(0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIV, 0, opcode & 7);
FP_ENTER();
FP_OP_REG(FPU_DIV, 0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIVR, 0, opcode & 7);
FP_ENTER();
FP_OP_REG(FPU_DIVR, 0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_MUL, 0, opcode & 7);
FP_ENTER();
FP_OP_REG(FPU_MUL, 0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUB, 0, opcode & 7);
FP_ENTER();
FP_OP_REG(FPU_SUB, 0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUBR, 0, opcode & 7);
FP_ENTER();
FP_OP_REG(FPU_SUBR, 0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, opcode & 7, 0);
FP_ENTER();
FP_OP_REG(FPU_ADD, opcode & 7, 0);
return op_pc;
return op_pc;
}
static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIV, opcode & 7, 0);
FP_ENTER();
FP_OP_REG(FPU_DIV, opcode & 7, 0);
return op_pc;
return op_pc;
}
static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
FP_ENTER();
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
return op_pc;
return op_pc;
}
static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_MUL, opcode & 7, 0);
FP_ENTER();
FP_OP_REG(FPU_MUL, opcode & 7, 0);
return op_pc;
return op_pc;
}
static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUB, opcode & 7, 0);
FP_ENTER();
FP_OP_REG(FPU_SUB, opcode & 7, 0);
return op_pc;
return op_pc;
}
static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
FP_ENTER();
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
return op_pc;
return op_pc;
}
static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, opcode & 7, 0);
FP_POP();
FP_ENTER();
FP_OP_REG(FPU_ADD, opcode & 7, 0);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_COMPARE_REG(0, opcode & 7);
FP_POP();
FP_ENTER();
FP_COMPARE_REG(0, opcode & 7);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIV, opcode & 7, 0);
FP_POP();
FP_ENTER();
FP_OP_REG(FPU_DIV, opcode & 7, 0);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
FP_POP();
FP_ENTER();
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_MUL, opcode & 7, 0);
FP_POP();
FP_ENTER();
FP_OP_REG(FPU_MUL, opcode & 7, 0);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUB, opcode & 7, 0);
FP_POP();
FP_ENTER();
FP_OP_REG(FPU_SUB, opcode & 7, 0);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
FP_POP();
FP_ENTER();
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
FP_POP();
return op_pc;
return op_pc;
}
static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_COMPARE_REG(0, 1);
FP_POP2();
FP_ENTER();
FP_COMPARE_REG(0, 1);
FP_POP2();
return op_pc;
return op_pc;
}
static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
int host_reg;
FP_ENTER();
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
FP_ENTER();
host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxs);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
return op_pc;
return op_pc;
}
static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG_INT_W(0);
host_reg = FP_LOAD_REG_INT_W(0);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG_INT(0);
host_reg = FP_LOAD_REG_INT(0);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
FP_POP();
return new_pc;
return new_pc;
}
static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block);
uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
FP_POP();
return new_pc;
return new_pc;
}
static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg1, host_reg2;
x86seg *target_seg;
int host_reg1, host_reg2;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2);
FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
FP_POP();
FP_POP();
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
CHECK_SEG_READ(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
UPDATE_NPXC(0);
MEM_LOAD_ADDR_EA_W(target_seg);
STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.npxc, 0);
UPDATE_NPXC(0);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
x86seg *target_seg;
int host_reg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_WRITE(target_seg);
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FCHS();
FP_ENTER();
FP_FCHS();
return op_pc;
return op_pc;
}
#define opFLDimm(name, v) \
static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
static double fp_imm = v; \
\
FP_ENTER(); \
FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \
\
return op_pc; \
}
#define opFLDimm(name, v) \
static uint32_t ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
static double fp_imm = v; \
\
FP_ENTER(); \
FP_LOAD_IMM_Q(*(uint64_t *) &fp_imm); \
\
return op_pc; \
}
opFLDimm(1, 1.0)
opFLDimm(L2T, 3.3219280948873623)
opFLDimm(L2E, 1.4426950408889634);
opFLDimm(L2T, 3.3219280948873623)
opFLDimm(L2E, 1.4426950408889634);
opFLDimm(PI, 3.141592653589793);
opFLDimm(EG2, 0.3010299956639812);
opFLDimm(Z, 0.0)
static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
FP_ENTER();
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
return op_pc;
return op_pc;
}

View File

@@ -1,257 +1,258 @@
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
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;
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
if (offset & 0x80)
offset |= 0xffffff00;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 1 + offset);
return -1;
return -1;
}
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
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;
uint16_t offset = fetchdat & 0xffff;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff);
return -1;
return -1;
}
static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
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);
uint32_t offset = fastreadl(cs + op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset);
return -1;
return -1;
}
static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
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;
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
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);
}
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;
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)
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;
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
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);
}
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;
return op_pc + 1;
}
static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
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);
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)
static void
BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
{
int host_reg;
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;
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;
}
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)
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);
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)
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);
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)
static void
BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
{
int host_reg;
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;
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_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_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;
}
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; \
}
#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; \
}
// clang-format off
ropBRANCH(JB, BRANCH_COND_B, 0)
ropBRANCH(JNB, BRANCH_COND_B, 1)
ropBRANCH(JE, BRANCH_COND_E, 0)
@@ -268,3 +269,4 @@ ropBRANCH(JLE, BRANCH_COND_LE, 0)
ropBRANCH(JNLE, BRANCH_COND_LE, 1)
ropBRANCH(JBE, BRANCH_COND_BE, 0)
ropBRANCH(JNBE, BRANCH_COND_BE, 1)
// clang-format on

File diff suppressed because it is too large Load Diff

View File

@@ -1,272 +1,263 @@
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
return op_pc;
return op_pc;
}
static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
CLEAR_BITS((uintptr_t)&cpu_state.flags, D_FLAG);
return op_pc;
CLEAR_BITS((uintptr_t) &cpu_state.flags, D_FLAG);
return op_pc;
}
static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
SET_BITS((uintptr_t)&cpu_state.flags, D_FLAG);
return op_pc;
SET_BITS((uintptr_t) &cpu_state.flags, D_FLAG);
return op_pc;
}
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
CLEAR_BITS((uintptr_t)&cpu_state.flags, I_FLAG);
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
CLEAR_BITS((uintptr_t) &cpu_state.flags, I_FLAG);
#ifdef CHECK_INT
CLEAR_BITS((uintptr_t)&pic_pending, 0xffffffff);
CLEAR_BITS((uintptr_t) &pic_pending, 0xffffffff);
#endif
return op_pc;
return op_pc;
}
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
SET_BITS((uintptr_t)&cpu_state.flags, I_FLAG);
return op_pc;
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
SET_BITS((uintptr_t) &cpu_state.flags, I_FLAG);
return op_pc;
}
static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int host_reg;
x86seg *target_seg = NULL;
int host_reg;
if ((fetchdat & 0x30) != 0x00)
return 0;
if ((fetchdat & 0x30) != 0x00)
return 0;
CALL_FUNC((uintptr_t)flags_rebuild_c);
CALL_FUNC((uintptr_t) flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_B(fetchdat & 7);
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_B(fetchdat & 7);
else {
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
SAVE_EA();
MEM_CHECK_WRITE(target_seg);
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
}
SAVE_EA();
MEM_CHECK_WRITE(target_seg);
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_B(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
break;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_B(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
break;
}
switch (fetchdat & 0x38) {
case 0x00: /*INC*/
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_B(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC8);
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg);
break;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_B(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC8);
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg);
break;
}
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_B_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_B_RELEASE(host_reg);
else {
LOAD_EA();
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
return op_pc + 1;
}
static uint32_t codegen_temp;
static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int host_reg;
x86seg *target_seg = NULL;
int host_reg;
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
return 0;
if ((fetchdat & 0x30) == 0x00)
CALL_FUNC((uintptr_t)flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_W(fetchdat & 7);
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0x30) != 0x00)
{
MEM_LOAD_ADDR_EA_W(target_seg);
host_reg = 0;
}
else
{
SAVE_EA();
MEM_CHECK_WRITE_W(target_seg);
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
}
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_W_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_W_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(op_pc + 1);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp);
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x20: /*JMP*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x30: /*PUSH*/
if (!host_reg)
host_reg = LOAD_HOST_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
return op_pc + 1;
}
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
return 0;
if ((fetchdat & 0x30) == 0x00)
CALL_FUNC((uintptr_t) flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_W(fetchdat & 7);
else {
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0x30) != 0x00) {
MEM_LOAD_ADDR_EA_W(target_seg);
host_reg = 0;
} else {
SAVE_EA();
MEM_CHECK_WRITE_W(target_seg);
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
}
}
switch (fetchdat & 0x38) {
case 0x00: /*INC*/
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC16);
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_W_RELEASE(host_reg);
else {
LOAD_EA();
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC16);
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_W_RELEASE(host_reg);
else {
LOAD_EA();
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(op_pc + 1);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
host_reg = LOAD_VAR_W((uintptr_t) &codegen_temp);
STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.pc, host_reg);
return -1;
case 0x20: /*JMP*/
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg);
return -1;
case 0x30: /*PUSH*/
if (!host_reg)
host_reg = LOAD_HOST_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
return op_pc + 1;
}
return 0;
}
static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int host_reg;
x86seg *target_seg = NULL;
int host_reg;
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
return 0;
if ((fetchdat & 0x30) == 0x00)
CALL_FUNC((uintptr_t)flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_L(fetchdat & 7);
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0x30) != 0x00)
{
MEM_LOAD_ADDR_EA_L(target_seg);
host_reg = 0;
}
else
{
SAVE_EA();
MEM_CHECK_WRITE_L(target_seg);
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
}
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_L_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_L_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(op_pc + 1);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x20: /*JMP*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x30: /*PUSH*/
if (!host_reg)
host_reg = LOAD_HOST_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
return op_pc + 1;
}
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
return 0;
if ((fetchdat & 0x30) == 0x00)
CALL_FUNC((uintptr_t) flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_L(fetchdat & 7);
else {
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0x30) != 0x00) {
MEM_LOAD_ADDR_EA_L(target_seg);
host_reg = 0;
} else {
SAVE_EA();
MEM_CHECK_WRITE_L(target_seg);
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
}
}
switch (fetchdat & 0x38) {
case 0x00: /*INC*/
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC32);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_L_RELEASE(host_reg);
else {
LOAD_EA();
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC32);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_L_RELEASE(host_reg);
else {
LOAD_EA();
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(op_pc + 1);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
host_reg = LOAD_VAR_L((uintptr_t) &codegen_temp);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg);
return -1;
case 0x20: /*JMP*/
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg);
return -1;
case 0x30: /*PUSH*/
if (!host_reg)
host_reg = LOAD_HOST_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
return op_pc + 1;
}
return 0;
}

View File

@@ -1,277 +1,267 @@
static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg1, host_reg2 = 0;
int host_reg1, host_reg2 = 0;
MMX_ENTER();
MMX_ENTER();
LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
if ((fetchdat & 0xc0) == 0xc0) {
STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
} else {
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
}
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
}
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
MMX_ENTER();
MMX_ENTER();
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg1, host_reg2;
if ((fetchdat & 0xc0) == 0xc0) {
int host_reg1, host_reg2;
LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
} else {
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
}
MEM_LOAD_ADDR_EA_Q(target_seg);
STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
}
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
int host_reg;
MMX_ENTER();
MMX_ENTER();
host_reg = LOAD_MMX_D((fetchdat >> 3) & 7);
host_reg = LOAD_MMX_D((fetchdat >> 3) & 7);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
if ((fetchdat & 0xc0) == 0xc0) {
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
} else {
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 3);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 3);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
}
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
}
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
MMX_ENTER();
MMX_ENTER();
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_L(fetchdat & 7);
STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
if ((fetchdat & 0xc0) == 0xc0) {
int host_reg = LOAD_REG_L(fetchdat & 7);
STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
} else {
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
}
MEM_LOAD_ADDR_EA_L(target_seg);
STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
}
return op_pc + 1;
return op_pc + 1;
}
#define MMX_OP(name, func) \
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg1, src_reg2; \
int xmm_src, xmm_dst; \
\
MMX_ENTER(); \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \
} \
else \
{ \
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
if ((fetchdat & 0xc0) == 0xc0) { \
xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \
} else { \
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
CHECK_SEG_READ(target_seg); \
\
MEM_LOAD_ADDR_EA_Q(target_seg); \
src_reg1 = LOAD_Q_REG_1; \
src_reg2 = LOAD_Q_REG_2; \
xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \
MEM_LOAD_ADDR_EA_Q(target_seg); \
src_reg1 = LOAD_Q_REG_1; \
src_reg2 = LOAD_Q_REG_2; \
xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \
} \
xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \
func(xmm_dst, xmm_src); \
func(xmm_dst, xmm_src); \
STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \
\
return op_pc + 1; \
}
}
MMX_OP(ropPAND, MMX_AND)
MMX_OP(ropPAND, MMX_AND)
MMX_OP(ropPANDN, MMX_ANDN)
MMX_OP(ropPOR, MMX_OR)
MMX_OP(ropPXOR, MMX_XOR)
MMX_OP(ropPOR, MMX_OR)
MMX_OP(ropPXOR, MMX_XOR)
MMX_OP(ropPADDB, MMX_ADDB)
MMX_OP(ropPADDW, MMX_ADDW)
MMX_OP(ropPADDD, MMX_ADDD)
MMX_OP(ropPADDSB, MMX_ADDSB)
MMX_OP(ropPADDSW, MMX_ADDSW)
MMX_OP(ropPADDUSB, MMX_ADDUSB)
MMX_OP(ropPADDUSW, MMX_ADDUSW)
MMX_OP(ropPADDB, MMX_ADDB)
MMX_OP(ropPADDW, MMX_ADDW)
MMX_OP(ropPADDD, MMX_ADDD)
MMX_OP(ropPADDSB, MMX_ADDSB)
MMX_OP(ropPADDSW, MMX_ADDSW)
MMX_OP(ropPADDUSB, MMX_ADDUSB)
MMX_OP(ropPADDUSW, MMX_ADDUSW)
MMX_OP(ropPSUBB, MMX_SUBB)
MMX_OP(ropPSUBW, MMX_SUBW)
MMX_OP(ropPSUBD, MMX_SUBD)
MMX_OP(ropPSUBSB, MMX_SUBSB)
MMX_OP(ropPSUBSW, MMX_SUBSW)
MMX_OP(ropPSUBUSB, MMX_SUBUSB)
MMX_OP(ropPSUBUSW, MMX_SUBUSW)
MMX_OP(ropPSUBB, MMX_SUBB)
MMX_OP(ropPSUBW, MMX_SUBW)
MMX_OP(ropPSUBD, MMX_SUBD)
MMX_OP(ropPSUBSB, MMX_SUBSB)
MMX_OP(ropPSUBSW, MMX_SUBSW)
MMX_OP(ropPSUBUSB, MMX_SUBUSB)
MMX_OP(ropPSUBUSW, MMX_SUBUSW)
MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW);
MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD);
MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ);
MMX_OP(ropPACKSSWB, MMX_PACKSSWB);
MMX_OP(ropPCMPGTB, MMX_PCMPGTB);
MMX_OP(ropPCMPGTW, MMX_PCMPGTW);
MMX_OP(ropPCMPGTD, MMX_PCMPGTD);
MMX_OP(ropPACKUSWB, MMX_PACKUSWB);
MMX_OP(ropPACKSSWB, MMX_PACKSSWB);
MMX_OP(ropPCMPGTB, MMX_PCMPGTB);
MMX_OP(ropPCMPGTW, MMX_PCMPGTW);
MMX_OP(ropPCMPGTD, MMX_PCMPGTD);
MMX_OP(ropPACKUSWB, MMX_PACKUSWB);
MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW);
MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD);
MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ);
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
MMX_OP(ropPCMPEQB, MMX_PCMPEQB);
MMX_OP(ropPCMPEQW, MMX_PCMPEQW);
MMX_OP(ropPCMPEQD, MMX_PCMPEQD);
MMX_OP(ropPCMPEQB, MMX_PCMPEQB);
MMX_OP(ropPCMPEQW, MMX_PCMPEQW);
MMX_OP(ropPCMPEQD, MMX_PCMPEQD);
MMX_OP(ropPSRLW, MMX_PSRLW)
MMX_OP(ropPSRLD, MMX_PSRLD)
MMX_OP(ropPSRLQ, MMX_PSRLQ)
MMX_OP(ropPSRAW, MMX_PSRAW)
MMX_OP(ropPSRAD, MMX_PSRAD)
MMX_OP(ropPSLLW, MMX_PSLLW)
MMX_OP(ropPSLLD, MMX_PSLLD)
MMX_OP(ropPSLLQ, MMX_PSLLQ)
MMX_OP(ropPSRLW, MMX_PSRLW)
MMX_OP(ropPSRLD, MMX_PSRLD)
MMX_OP(ropPSRLQ, MMX_PSRLQ)
MMX_OP(ropPSRAW, MMX_PSRAW)
MMX_OP(ropPSRAD, MMX_PSRAD)
MMX_OP(ropPSLLW, MMX_PSLLW)
MMX_OP(ropPSLLD, MMX_PSLLD)
MMX_OP(ropPSLLQ, MMX_PSLLQ)
MMX_OP(ropPMULLW, MMX_PMULLW);
MMX_OP(ropPMULHW, MMX_PMULHW);
MMX_OP(ropPMADDWD, MMX_PMADDWD);
MMX_OP(ropPMULLW, MMX_PMULLW);
MMX_OP(ropPMULHW, MMX_PMULHW);
MMX_OP(ropPMADDWD, MMX_PMADDWD);
static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x10: /*PSRLW*/
MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAW*/
MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLW*/
MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x10: /*PSRLD*/
MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAD*/
MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLD*/
MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x10: /*PSRLQ*/
MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAQ*/
MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLQ*/
MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
codegen_mmx_entered = 0;
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38) {
case 0x10: /*PSRLW*/
MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAW*/
MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLW*/
MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t
ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38) {
case 0x10: /*PSRLD*/
MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAD*/
MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLD*/
MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t
ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38) {
case 0x10: /*PSRLQ*/
MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAQ*/
MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLQ*/
MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t
ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
codegen_mmx_entered = 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +1,129 @@
#define SHIFT(size, size2, res_store, immediate) \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
reg = LOAD_REG_ ## size(fetchdat & 7); \
if (immediate) count = (fetchdat >> 8) & 0x1f; \
} \
else \
{ \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
SAVE_EA(); \
MEM_CHECK_WRITE_ ## size(target_seg); \
reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \
if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \
} \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \
\
res_store((uintptr_t)&cpu_state.flags_op1, reg); \
\
switch (fetchdat & 0x38) \
{ \
case 0x20: case 0x30: /*SHL*/ \
SHL_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \
break; \
\
case 0x28: /*SHR*/ \
SHR_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \
break; \
\
case 0x38: /*SAR*/ \
SAR_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \
break; \
} \
\
res_store((uintptr_t)&cpu_state.flags_res, reg); \
if ((fetchdat & 0xc0) == 0xc0) \
STORE_REG_ ## size ## _RELEASE(reg); \
else \
{ \
LOAD_EA(); \
MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \
}
#define SHIFT(size, size2, res_store, immediate) \
if ((fetchdat & 0xc0) == 0xc0) { \
reg = LOAD_REG_##size(fetchdat & 7); \
if (immediate) \
count = (fetchdat >> 8) & 0x1f; \
} else { \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
SAVE_EA(); \
MEM_CHECK_WRITE_##size(target_seg); \
reg = MEM_LOAD_ADDR_EA_##size##_NO_ABRT(target_seg); \
if (immediate) \
count = fastreadb(cs + op_pc + 1) & 0x1f; \
} \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, count); \
\
res_store((uintptr_t) &cpu_state.flags_op1, reg); \
\
switch (fetchdat & 0x38) { \
case 0x20: \
case 0x30: /*SHL*/ \
SHL_##size##_IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHL##size2); \
break; \
\
case 0x28: /*SHR*/ \
SHR_##size##_IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHR##size2); \
break; \
\
case 0x38: /*SAR*/ \
SAR_##size##_IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SAR##size2); \
break; \
} \
\
res_store((uintptr_t) &cpu_state.flags_res, reg); \
if ((fetchdat & 0xc0) == 0xc0) \
STORE_REG_##size##_RELEASE(reg); \
else { \
LOAD_EA(); \
MEM_STORE_ADDR_EA_##size##_NO_ABRT(target_seg, reg); \
}
static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count;
int reg;
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
return op_pc + 2;
return op_pc + 2;
}
static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count;
int reg;
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
return op_pc + 2;
return op_pc + 2;
}
static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count;
int reg;
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
return op_pc + 2;
return op_pc + 2;
}
static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
return op_pc + 1;
return op_pc + 1;
}

View File

@@ -1,238 +1,254 @@
static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_W(opcode & 7);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_W(opcode & 7);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
return op_pc;
return op_pc;
}
static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_L(opcode & 7);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_L(opcode & 7);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
return op_pc;
return op_pc;
}
static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t imm = fetchdat & 0xffff;
int host_reg;
uint16_t imm = fetchdat & 0xffff;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
return op_pc+2;
return op_pc + 2;
}
static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t imm = fastreadl(cs + op_pc);
int host_reg;
uint32_t imm = fastreadl(cs + op_pc);
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
return op_pc+4;
return op_pc + 4;
}
static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t imm = fetchdat & 0xff;
int host_reg;
uint16_t imm = fetchdat & 0xff;
int host_reg;
if (imm & 0x80)
imm |= 0xff00;
if (imm & 0x80)
imm |= 0xff00;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
return op_pc+1;
return op_pc + 1;
}
static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t imm = fetchdat & 0xff;
int host_reg;
uint32_t imm = fetchdat & 0xff;
int host_reg;
if (imm & 0x80)
imm |= 0xffffff00;
if (imm & 0x80)
imm |= 0xffffff00;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
return op_pc+1;
return op_pc + 1;
}
static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
SP_MODIFY(2);
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
SP_MODIFY(2);
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
SP_MODIFY(4);
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
SP_MODIFY(4);
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
return op_pc;
return op_pc;
}
static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(2);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
SP_MODIFY(2);
return -1;
return -1;
}
static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(4);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
SP_MODIFY(4);
return -1;
return -1;
}
static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
uint16_t offset = fetchdat & 0xffff;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(2+offset);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
SP_MODIFY(2 + offset);
return -1;
return -1;
}
static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
uint16_t offset = fetchdat & 0xffff;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(4+offset);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
SP_MODIFY(4 + offset);
return -1;
return -1;
}
static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
int host_reg;
uint16_t offset = fetchdat & 0xffff;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(op_pc+2);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(op_pc + 2);
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-2);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff);
return -1;
return -1;
}
static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fastreadl(cs + op_pc);
int host_reg;
uint32_t offset = fastreadl(cs + op_pc);
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(op_pc+4);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(op_pc + 4);
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
SP_MODIFY(-4);
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset);
return -1;
return -1;
}
static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_EBP_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
ADD_HOST_REG_IMM_W(host_reg, 2);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_EBP_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
ADD_HOST_REG_IMM_W(host_reg, 2);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
return op_pc;
return op_pc;
}
static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_EBP_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
ADD_HOST_REG_IMM(host_reg, 4);
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
LOAD_EBP_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
ADD_HOST_REG_IMM(host_reg, 4);
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
return op_pc;
return op_pc;
}
#define ROP_PUSH_SEG(seg) \
static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int host_reg; \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(-2); \
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \
SP_MODIFY(-2); \
\
return op_pc; \
} \
static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int host_reg; \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(-4); \
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \
SP_MODIFY(-4); \
\
return op_pc; \
}
#define ROP_PUSH_SEG(seg) \
static uint32_t ropPUSH_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int host_reg; \
\
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(-2); \
host_reg = LOAD_VAR_W((uintptr_t) &seg); \
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \
SP_MODIFY(-2); \
\
return op_pc; \
} \
static uint32_t ropPUSH_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int host_reg; \
\
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(-4); \
host_reg = LOAD_VAR_W((uintptr_t) &seg); \
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \
SP_MODIFY(-4); \
\
return op_pc; \
}
ROP_PUSH_SEG(CS)
ROP_PUSH_SEG(DS)
@@ -241,27 +257,27 @@ ROP_PUSH_SEG(FS)
ROP_PUSH_SEG(GS)
ROP_PUSH_SEG(SS)
#define ROP_POP_SEG(seg, rseg) \
static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(0); \
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
LOAD_SEG(0, &rseg); \
SP_MODIFY(2); \
\
return op_pc; \
} \
static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(0); \
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
LOAD_SEG(0, &rseg); \
SP_MODIFY(4); \
\
return op_pc; \
}
#define ROP_POP_SEG(seg, rseg) \
static uint32_t ropPOP_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(0); \
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
LOAD_SEG(0, &rseg); \
SP_MODIFY(2); \
\
return op_pc; \
} \
static uint32_t ropPOP_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
LOAD_STACK_TO_EA(0); \
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
LOAD_SEG(0, &rseg); \
SP_MODIFY(4); \
\
return op_pc; \
}
ROP_POP_SEG(DS, cpu_state.seg_ds)
ROP_POP_SEG(ES, cpu_state.seg_es)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,16 @@
#define OP_XCHG_AX_(reg) \
static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int ax_reg, host_reg, temp_reg; \
\
ax_reg = LOAD_REG_W(REG_AX); \
host_reg = LOAD_REG_W(REG_ ## reg); \
temp_reg = COPY_REG(host_reg); \
STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \
STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \
\
return op_pc; \
}
#define OP_XCHG_AX_(reg) \
static uint32_t ropXCHG_AX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int ax_reg, host_reg, temp_reg; \
\
ax_reg = LOAD_REG_W(REG_AX); \
host_reg = LOAD_REG_W(REG_##reg); \
temp_reg = COPY_REG(host_reg); \
STORE_REG_TARGET_W_RELEASE(ax_reg, REG_##reg); \
STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \
\
return op_pc; \
}
OP_XCHG_AX_(BX)
OP_XCHG_AX_(CX)
@@ -20,19 +20,19 @@ OP_XCHG_AX_(DI)
OP_XCHG_AX_(SP)
OP_XCHG_AX_(BP)
#define OP_XCHG_EAX_(reg) \
static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int eax_reg, host_reg, temp_reg; \
\
eax_reg = LOAD_REG_L(REG_EAX); \
host_reg = LOAD_REG_L(REG_ ## reg); \
temp_reg = COPY_REG(host_reg); \
STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \
STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \
\
return op_pc; \
}
#define OP_XCHG_EAX_(reg) \
static uint32_t ropXCHG_EAX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int eax_reg, host_reg, temp_reg; \
\
eax_reg = LOAD_REG_L(REG_EAX); \
host_reg = LOAD_REG_L(REG_##reg); \
temp_reg = COPY_REG(host_reg); \
STORE_REG_TARGET_L_RELEASE(eax_reg, REG_##reg); \
STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \
\
return op_pc; \
}
OP_XCHG_EAX_(EBX)
OP_XCHG_EAX_(ECX)
@@ -42,48 +42,51 @@ OP_XCHG_EAX_(EDI)
OP_XCHG_EAX_(ESP)
OP_XCHG_EAX_(EBP)
static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg, temp_reg;
int src_reg, dst_reg, temp_reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
dst_reg = LOAD_REG_B(fetchdat & 7);
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7);
dst_reg = LOAD_REG_B(fetchdat & 7);
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg, temp_reg;
int src_reg, dst_reg, temp_reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
dst_reg = LOAD_REG_W(fetchdat & 7);
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7);
dst_reg = LOAD_REG_W(fetchdat & 7);
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7);
return op_pc + 1;
return op_pc + 1;
}
static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
static uint32_t
ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg, temp_reg;
int src_reg, dst_reg, temp_reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
dst_reg = LOAD_REG_L(fetchdat & 7);
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7);
dst_reg = LOAD_REG_L(fetchdat & 7);
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7);
return op_pc + 1;
return op_pc + 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,23 @@
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define HASH(l) ((l) &0x1ffff)
#define BLOCK_EXIT_OFFSET 0x7e0
#ifdef OLD_GPF
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
#else
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12)
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12)
#endif
#define BLOCK_MAX 1620
enum
{
OP_RET = 0xc3
enum {
OP_RET = 0xc3
};
#define NR_HOST_REGS 4

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,23 @@
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define HASH(l) ((l) &0x1ffff)
#define BLOCK_EXIT_OFFSET 0x7f0
#ifdef OLD_GPF
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
#else
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14)
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14)
#endif
#define BLOCK_MAX 1720
enum
{
OP_RET = 0xc3
enum {
OP_RET = 0xc3
};
#define NR_HOST_REGS 4

File diff suppressed because it is too large Load Diff

View File

@@ -30,34 +30,33 @@
same page).
*/
typedef struct codeblock_t
{
uint32_t pc;
uint32_t _cs;
uint32_t phys, phys_2;
uint16_t status;
uint16_t flags;
uint8_t ins;
uint8_t TOP;
typedef struct codeblock_t {
uint32_t pc;
uint32_t _cs;
uint32_t phys, phys_2;
uint16_t status;
uint16_t flags;
uint8_t ins;
uint8_t TOP;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
uint16_t parent, left, right;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
uint16_t parent, left, right;
uint8_t *data;
uint8_t *data;
uint64_t page_mask, page_mask2;
uint64_t *dirty_mask, *dirty_mask2;
uint64_t page_mask, page_mask2;
uint64_t *dirty_mask, *dirty_mask2;
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
uint16_t prev, next;
uint16_t prev_2, next_2;
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
uint16_t prev, next;
uint16_t prev_2, next_2;
/*First mem_block_t used by this block. Any subsequent mem_block_ts
will be in the list starting at head_mem_block->next.*/
struct mem_block_t *head_mem_block;
/*First mem_block_t used by this block. Any subsequent mem_block_ts
will be in the list starting at head_mem_block->next.*/
struct mem_block_t *head_mem_block;
} codeblock_t;
extern codeblock_t *codeblock;
@@ -83,235 +82,206 @@ extern uint8_t *block_write_data;
/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/
#define CODEBLOCK_NO_IMMEDIATES 0x80
#define BLOCK_PC_INVALID 0xffffffff
#define BLOCK_PC_INVALID 0xffffffff
#define BLOCK_INVALID 0
#define BLOCK_INVALID 0
static inline int get_block_nr(codeblock_t *block)
static inline int
get_block_nr(codeblock_t *block)
{
return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t);
return ((uintptr_t) block - (uintptr_t) codeblock) / sizeof(codeblock_t);
}
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
static inline codeblock_t *
codeblock_tree_find(uint32_t phys, uint32_t _cs)
{
codeblock_t *block;
uint64_t a = _cs | ((uint64_t)phys << 32);
codeblock_t *block;
uint64_t a = _cs | ((uint64_t) phys << 32);
if (!pages[phys >> 12].head)
return NULL;
if (!pages[phys >> 12].head)
return NULL;
block = &codeblock[pages[phys >> 12].head];
while (block)
{
uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32);
if (a == block_cmp)
{
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
break;
}
if (a < block_cmp)
block = block->left ? &codeblock[block->left] : NULL;
else
block = block->right ? &codeblock[block->right] : NULL;
}
return block;
}
static inline void codeblock_tree_add(codeblock_t *new_block)
{
codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
if (!pages[new_block->phys >> 12].head)
{
pages[new_block->phys >> 12].head = get_block_nr(new_block);
new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
block = &codeblock[pages[phys >> 12].head];
while (block) {
uint64_t block_cmp = block->_cs | ((uint64_t) block->phys << 32);
if (a == block_cmp) {
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
break;
}
if (a < block_cmp)
block = block->left ? &codeblock[block->left] : NULL;
else
{
codeblock_t *old_block = NULL;
uint64_t old_block_cmp = 0;
block = block->right ? &codeblock[block->right] : NULL;
}
while (block)
{
old_block = block;
old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32);
if (a < old_block_cmp)
block = block->left ? &codeblock[block->left] : NULL;
else
block = block->right ? &codeblock[block->right] : NULL;
}
if (a < old_block_cmp)
old_block->left = get_block_nr(new_block);
else
old_block->right = get_block_nr(new_block);
new_block->parent = get_block_nr(old_block);
new_block->left = new_block->right = BLOCK_INVALID;
}
return block;
}
static inline void codeblock_tree_delete(codeblock_t *block)
static inline void
codeblock_tree_add(codeblock_t *new_block)
{
uint16_t parent_nr = block->parent;
codeblock_t *parent;
codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32);
if (block->parent)
parent = &codeblock[block->parent];
if (!pages[new_block->phys >> 12].head) {
pages[new_block->phys >> 12].head = get_block_nr(new_block);
new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
} else {
codeblock_t *old_block = NULL;
uint64_t old_block_cmp = 0;
while (block) {
old_block = block;
old_block_cmp = old_block->_cs | ((uint64_t) old_block->phys << 32);
if (a < old_block_cmp)
block = block->left ? &codeblock[block->left] : NULL;
else
block = block->right ? &codeblock[block->right] : NULL;
}
if (a < old_block_cmp)
old_block->left = get_block_nr(new_block);
else
parent = NULL;
old_block->right = get_block_nr(new_block);
if (!block->left && !block->right)
{
/*Easy case - remove from parent*/
if (!parent)
pages[block->phys >> 12].head = BLOCK_INVALID;
else
{
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
parent->left = BLOCK_INVALID;
if (parent->right == block_nr)
parent->right = BLOCK_INVALID;
}
return;
}
else if (!block->left)
{
/*Only right node*/
if (!parent_nr)
{
pages[block->phys >> 12].head = block->right;
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
}
else
{
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
{
parent->left = block->right;
codeblock[parent->left].parent = parent_nr;
}
if (parent->right == block_nr)
{
parent->right = block->right;
codeblock[parent->right].parent = parent_nr;
}
}
return;
}
else if (!block->right)
{
/*Only left node*/
if (!parent_nr)
{
pages[block->phys >> 12].head = block->left;
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
}
else
{
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
{
parent->left = block->left;
codeblock[parent->left].parent = parent_nr;
}
if (parent->right == block_nr)
{
parent->right = block->left;
codeblock[parent->right].parent = parent_nr;
}
}
return;
}
else
{
/*Difficult case - node has two children. Walk right child to find lowest node*/
codeblock_t *lowest = &codeblock[block->right], *highest;
codeblock_t *old_parent;
uint16_t lowest_nr;
while (lowest->left)
lowest = &codeblock[lowest->left];
lowest_nr = get_block_nr(lowest);
old_parent = &codeblock[lowest->parent];
/*Replace deleted node with lowest node*/
if (!parent_nr)
pages[block->phys >> 12].head = lowest_nr;
else
{
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
parent->left = lowest_nr;
if (parent->right == block_nr)
parent->right = lowest_nr;
}
lowest->parent = parent_nr;
lowest->left = block->left;
if (lowest->left)
codeblock[lowest->left].parent = lowest_nr;
old_parent->left = BLOCK_INVALID;
highest = &codeblock[lowest->right];
if (!lowest->right)
{
if (lowest_nr != block->right)
{
lowest->right = block->right;
codeblock[block->right].parent = lowest_nr;
}
return;
}
while (highest->right)
highest = &codeblock[highest->right];
if (block->right && block->right != lowest_nr)
{
highest->right = block->right;
codeblock[block->right].parent = get_block_nr(highest);
}
}
new_block->parent = get_block_nr(old_block);
new_block->left = new_block->right = BLOCK_INVALID;
}
}
#define PAGE_MASK_MASK 63
static inline void
codeblock_tree_delete(codeblock_t *block)
{
uint16_t parent_nr = block->parent;
codeblock_t *parent;
if (block->parent)
parent = &codeblock[block->parent];
else
parent = NULL;
if (!block->left && !block->right) {
/*Easy case - remove from parent*/
if (!parent)
pages[block->phys >> 12].head = BLOCK_INVALID;
else {
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
parent->left = BLOCK_INVALID;
if (parent->right == block_nr)
parent->right = BLOCK_INVALID;
}
return;
} else if (!block->left) {
/*Only right node*/
if (!parent_nr) {
pages[block->phys >> 12].head = block->right;
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
} else {
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr) {
parent->left = block->right;
codeblock[parent->left].parent = parent_nr;
}
if (parent->right == block_nr) {
parent->right = block->right;
codeblock[parent->right].parent = parent_nr;
}
}
return;
} else if (!block->right) {
/*Only left node*/
if (!parent_nr) {
pages[block->phys >> 12].head = block->left;
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
} else {
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr) {
parent->left = block->left;
codeblock[parent->left].parent = parent_nr;
}
if (parent->right == block_nr) {
parent->right = block->left;
codeblock[parent->right].parent = parent_nr;
}
}
return;
} else {
/*Difficult case - node has two children. Walk right child to find lowest node*/
codeblock_t *lowest = &codeblock[block->right], *highest;
codeblock_t *old_parent;
uint16_t lowest_nr;
while (lowest->left)
lowest = &codeblock[lowest->left];
lowest_nr = get_block_nr(lowest);
old_parent = &codeblock[lowest->parent];
/*Replace deleted node with lowest node*/
if (!parent_nr)
pages[block->phys >> 12].head = lowest_nr;
else {
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
parent->left = lowest_nr;
if (parent->right == block_nr)
parent->right = lowest_nr;
}
lowest->parent = parent_nr;
lowest->left = block->left;
if (lowest->left)
codeblock[lowest->left].parent = lowest_nr;
old_parent->left = BLOCK_INVALID;
highest = &codeblock[lowest->right];
if (!lowest->right) {
if (lowest_nr != block->right) {
lowest->right = block->right;
codeblock[block->right].parent = lowest_nr;
}
return;
}
while (highest->right)
highest = &codeblock[highest->right];
if (block->right && block->right != lowest_nr) {
highest->right = block->right;
codeblock[block->right].parent = get_block_nr(highest);
}
}
}
#define PAGE_MASK_MASK 63
#define PAGE_MASK_SHIFT 6
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len);
static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
static inline void
codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
{
if (len == 1)
{
if (block->flags & CODEBLOCK_BYTE_MASK)
{
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
else
block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
}
else
{
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
else
block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
}
if (len == 1) {
if (block->flags & CODEBLOCK_BYTE_MASK) {
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
block->page_mask |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK));
else
block->page_mask2 |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK));
} else {
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
block->page_mask |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
else
block->page_mask2 |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
}
else
codegen_mark_code_present_multibyte(block, start_pc, len);
} else
codegen_mark_code_present_multibyte(block, start_pc, len);
}
extern void codegen_init(void);
@@ -329,7 +299,7 @@ extern void codegen_set_op32(void);
extern void codegen_flush(void);
extern void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
struct ir_data_t;
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
extern void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
extern void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
@@ -338,7 +308,7 @@ extern int codegen_purge_purgable_list(void);
will only be called when the allocator is out of memory*/
extern void codegen_delete_random_block(int required_mem_block);
extern int cpu_block_end;
extern int cpu_block_end;
extern uint32_t codegen_endpc;
extern int cpu_reps;
@@ -353,14 +323,13 @@ extern void (*codegen_timing_block_start)(void);
extern void (*codegen_timing_block_end)(void);
extern int (*codegen_timing_jump_cycles)(void);
typedef struct codegen_timing_t
{
void (*start)(void);
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)(void);
void (*block_end)(void);
int (*jump_cycles)(void);
typedef struct codegen_timing_t {
void (*start)(void);
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)(void);
void (*block_end)(void);
int (*jump_cycles)(void);
} codegen_timing_t;
extern codegen_timing_t codegen_timing_pentium;
@@ -371,7 +340,6 @@ extern codegen_timing_t codegen_timing_winchip2;
extern codegen_timing_t codegen_timing_k6;
extern codegen_timing_t codegen_timing_p6;
void codegen_timing_set(codegen_timing_t *timing);
extern int block_current;
@@ -382,8 +350,8 @@ extern int block_pos;
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern uint32_t op_old_pc;
/*Set to 1 if flags have been changed in the block being recompiled, and hence
@@ -400,11 +368,11 @@ extern int codegen_in_recompile;
void codegen_generate_reset(void);
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP);
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP);
void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction);
#ifdef DEBUG_EXTRA
extern uint32_t instr_counts[256*256];
extern uint32_t instr_counts[256 * 256];
#endif
#endif

View File

@@ -9,34 +9,36 @@
static struct
{
int count;
int dest_reg;
} acc_regs[] =
{
[ACCREG_cycles] = {0, IREG_cycles}
int count;
int dest_reg;
} acc_regs[] = {
[ACCREG_cycles] = {0, IREG_cycles}
};
void codegen_accumulate(ir_data_t *ir, int acc_reg, int delta)
void
codegen_accumulate(ir_data_t *ir, int acc_reg, int delta)
{
acc_regs[acc_reg].count += delta;
acc_regs[acc_reg].count += delta;
#ifdef USE_ACYCS
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta);
}
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta);
}
#endif
}
void codegen_accumulate_flush(ir_data_t *ir)
void
codegen_accumulate_flush(ir_data_t *ir)
{
if (acc_regs[0].count) {
uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count);
}
if (acc_regs[0].count) {
uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count);
}
acc_regs[0].count = 0;
acc_regs[0].count = 0;
}
void codegen_accumulate_reset(void)
void
codegen_accumulate_reset(void)
{
acc_regs[0].count = 0;
acc_regs[0].count = 0;
}

View File

@@ -1,8 +1,7 @@
enum
{
ACCREG_cycles = 0,
enum {
ACCREG_cycles = 0,
ACCREG_COUNT
ACCREG_COUNT
};
struct ir_data_t;

View File

@@ -1,10 +1,10 @@
#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
# include <sys/mman.h>
# include <unistd.h>
# include <stdlib.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
# include <windows.h>
#endif
#include <stdint.h>
@@ -17,118 +17,116 @@
#include "codegen.h"
#include "codegen_allocator.h"
typedef struct mem_block_t
{
uint32_t offset; /*Offset into mem_block_alloc*/
uint32_t next;
uint16_t code_block;
typedef struct mem_block_t {
uint32_t offset; /*Offset into mem_block_alloc*/
uint32_t next;
uint16_t code_block;
} mem_block_t;
static mem_block_t mem_blocks[MEM_BLOCK_NR];
static uint32_t mem_block_free_list;
static uint8_t *mem_block_alloc = NULL;
static uint32_t mem_block_free_list;
static uint8_t *mem_block_alloc = NULL;
int codegen_allocator_usage = 0;
void codegen_allocator_init(void)
void
codegen_allocator_init(void)
{
int c;
int c;
#if defined WIN32 || defined _WIN32 || defined _WIN32
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
/* TODO: check deployment target: older Intel-based versions of macOS don't play
nice with MAP_JIT. */
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
/* TODO: check deployment target: older Intel-based versions of macOS don't play
nice with MAP_JIT. */
#elif defined(__APPLE__) && defined(MAP_JIT)
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_JIT, -1, 0);
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
#else
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
#endif
for (c = 0; c < MEM_BLOCK_NR; c++)
{
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
mem_blocks[c].code_block = BLOCK_INVALID;
if (c < MEM_BLOCK_NR-1)
mem_blocks[c].next = c+2;
else
mem_blocks[c].next = 0;
}
mem_block_free_list = 1;
}
mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block)
{
mem_block_t *block;
uint32_t block_nr;
while (!mem_block_free_list)
{
/*Pick a random memory block and free the owning code block*/
block_nr = rand() & MEM_BLOCK_MASK;
block = &mem_blocks[block_nr];
if (block->code_block && block->code_block != code_block)
codegen_delete_block(&codeblock[block->code_block]);
}
/*Remove from free list*/
block_nr = mem_block_free_list;
block = &mem_blocks[block_nr-1];
mem_block_free_list = block->next;
block->code_block = code_block;
if (parent)
{
/*Add to parent list*/
block->next = parent->next;
parent->next = block_nr;
}
for (c = 0; c < MEM_BLOCK_NR; c++) {
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
mem_blocks[c].code_block = BLOCK_INVALID;
if (c < MEM_BLOCK_NR - 1)
mem_blocks[c].next = c + 2;
else
block->next = 0;
codegen_allocator_usage++;
return block;
mem_blocks[c].next = 0;
}
mem_block_free_list = 1;
}
void codegen_allocator_free(mem_block_t *block)
mem_block_t *
codegen_allocator_allocate(mem_block_t *parent, int code_block)
{
int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1;
mem_block_t *block;
uint32_t block_nr;
while (1)
{
int next_block_nr = block->next;
codegen_allocator_usage--;
while (!mem_block_free_list) {
/*Pick a random memory block and free the owning code block*/
block_nr = rand() & MEM_BLOCK_MASK;
block = &mem_blocks[block_nr];
block->next = mem_block_free_list;
block->code_block = BLOCK_INVALID;
mem_block_free_list = block_nr;
block_nr = next_block_nr;
if (block->code_block && block->code_block != code_block)
codegen_delete_block(&codeblock[block->code_block]);
}
if (block_nr)
block = &mem_blocks[block_nr - 1];
else
break;
}
/*Remove from free list*/
block_nr = mem_block_free_list;
block = &mem_blocks[block_nr - 1];
mem_block_free_list = block->next;
block->code_block = code_block;
if (parent) {
/*Add to parent list*/
block->next = parent->next;
parent->next = block_nr;
} else
block->next = 0;
codegen_allocator_usage++;
return block;
}
uint8_t *codeblock_allocator_get_ptr(mem_block_t *block)
void
codegen_allocator_free(mem_block_t *block)
{
return &mem_block_alloc[block->offset];
int block_nr = (((uintptr_t) block - (uintptr_t) mem_blocks) / sizeof(mem_block_t)) + 1;
while (1) {
int next_block_nr = block->next;
codegen_allocator_usage--;
block->next = mem_block_free_list;
block->code_block = BLOCK_INVALID;
mem_block_free_list = block_nr;
block_nr = next_block_nr;
if (block_nr)
block = &mem_blocks[block_nr - 1];
else
break;
}
}
void codegen_allocator_clean_blocks(struct mem_block_t *block)
uint8_t *
codeblock_allocator_get_ptr(mem_block_t *block)
{
return &mem_block_alloc[block->offset];
}
void
codegen_allocator_clean_blocks(struct mem_block_t *block)
{
#if defined __ARM_EABI__ || defined _ARM_ || defined __aarch64__ || defined _M_ARM || defined _M_ARM64
while (1)
{
#ifndef _MSC_VER
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
#else
FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE);
#endif
if (block->next)
block = &mem_blocks[block->next - 1];
else
break;
}
while (1) {
# ifndef _MSC_VER
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
# else
FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE);
# endif
if (block->next)
block = &mem_blocks[block->next - 1];
else
break;
}
#endif
}

View File

@@ -14,12 +14,12 @@
instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to
+/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/
#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM
#define MEM_BLOCK_NR 32768
# define MEM_BLOCK_NR 32768
#else
#define MEM_BLOCK_NR 131072
# define MEM_BLOCK_NR 131072
#endif
#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1)
#define MEM_BLOCK_MASK (MEM_BLOCK_NR - 1)
#define MEM_BLOCK_SIZE 0x3c0
void codegen_allocator_init(void);

View File

@@ -2,15 +2,15 @@
#define _CODEGEN_BACKEND_H_
#if defined __amd64__ || defined _M_X64
#include "codegen_backend_x86-64.h"
# include "codegen_backend_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
#include "codegen_backend_x86.h"
# include "codegen_backend_x86.h"
#elif defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM
#include "codegen_backend_arm.h"
# include "codegen_backend_arm.h"
#elif defined __aarch64__ || defined _M_ARM64
#include "codegen_backend_arm64.h"
# include "codegen_backend_arm64.h"
#else
#error Dynamic recompiler not implemented on your platform
# error Dynamic recompiler not implemented on your platform
#endif
void codegen_backend_init(void);
@@ -29,10 +29,9 @@ extern const uOpFn uop_handlers[];
/*Register will not be preserved across function calls*/
#define HOST_REG_FLAG_VOLATILE (1 << 0)
typedef struct host_reg_def_t
{
int reg;
int flags;
typedef struct host_reg_def_t {
int reg;
int flags;
} host_reg_def_t;
extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS];

View File

@@ -1,28 +1,28 @@
#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM
#include <stdint.h>
#include <stdlib.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
# include <stdint.h>
# include <stdlib.h>
# include <86box/86box.h>
# include "cpu.h"
# include <86box/mem.h>
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_arm_defs.h"
#include "codegen_backend_arm_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#include "x87.h"
# include "codegen.h"
# include "codegen_allocator.h"
# include "codegen_backend.h"
# include "codegen_backend_arm_defs.h"
# include "codegen_backend_arm_ops.h"
# include "codegen_reg.h"
# include "x86.h"
# include "x87.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
#include <string.h>
# if defined(__linux__) || defined(__APPLE__)
# include <sys/mman.h>
# include <unistd.h>
# endif
# if defined WIN32 || defined _WIN32 || defined _WIN32
# include <windows.h>
# endif
# include <string.h>
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
@@ -43,329 +43,325 @@ void *codegen_fp_round;
void *codegen_gpf_rout;
void *codegen_exit_rout;
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
{REG_R4, 0},
{REG_R5, 0},
{REG_R6, 0},
{REG_R7, 0},
{REG_R8, 0},
{REG_R9, 0},
{REG_R11, 0}
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = {
{REG_R4, 0},
{ REG_R5, 0},
{ REG_R6, 0},
{ REG_R7, 0},
{ REG_R8, 0},
{ REG_R9, 0},
{ REG_R11, 0}
};
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
{REG_D8, 0},
{REG_D9, 0},
{REG_D10, 0},
{REG_D11, 0},
{REG_D12, 0},
{REG_D13, 0},
{REG_D14, 0},
{REG_D15, 0}
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = {
{REG_D8, 0},
{ REG_D9, 0},
{ REG_D10, 0},
{ REG_D11, 0},
{ REG_D12, 0},
{ REG_D13, 0},
{ REG_D14, 0},
{ REG_D15, 0}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
static void
build_load_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
uint32_t *branch_offset;
uint32_t *misaligned_offset;
/*In - R0 = address
Out - R0 = data, R1 = abrt*/
/*MOV R1, R0, LSR #12
MOV R2, #readlookup2
LDR R1, [R2, R1, LSL #2]
CMP R1, #-1
BNE +
LDRB R0, [R1, R0]
MOV R1, #0
MOV PC, LR
* STR LR, [SP, -4]!
BL readmembl
LDRB R1, cpu_state.abrt
LDR PC, [SP], #4
*/
codegen_alloc(block, 80);
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2);
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
if (size != 1)
{
host_arm_TST_IMM(block, REG_R0, size-1);
misaligned_offset = host_arm_BNE_(block);
}
host_arm_CMP_IMM(block, REG_R1, -1);
branch_offset = host_arm_BEQ_(block);
if (size == 1 && !is_float)
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 2 && !is_float)
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 4 && !is_float)
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 4 && is_float)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0);
}
else if (size == 8)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0);
}
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_MOV_REG(block, REG_PC, REG_LR);
/*In - R0 = address
Out - R0 = data, R1 = abrt*/
/*MOV R1, R0, LSR #12
MOV R2, #readlookup2
LDR R1, [R2, R1, LSL #2]
CMP R1, #-1
BNE +
LDRB R0, [R1, R0]
MOV R1, #0
MOV PC, LR
* STR LR, [SP, -4]!
BL readmembl
LDRB R1, cpu_state.abrt
LDR PC, [SP], #4
*/
codegen_alloc(block, 80);
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
host_arm_MOV_IMM(block, REG_R2, (uint32_t) readlookup2);
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
if (size != 1) {
host_arm_TST_IMM(block, REG_R0, size - 1);
misaligned_offset = host_arm_BNE_(block);
}
host_arm_CMP_IMM(block, REG_R1, -1);
branch_offset = host_arm_BEQ_(block);
if (size == 1 && !is_float)
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 2 && !is_float)
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 4 && !is_float)
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 4 && is_float) {
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0);
} else if (size == 8) {
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0);
}
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_MOV_REG(block, REG_PC, REG_LR);
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
if (size != 1)
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
if (size == 1)
host_arm_BL(block, (uintptr_t)readmembl);
else if (size == 2)
host_arm_BL(block, (uintptr_t)readmemwl);
else if (size == 4)
host_arm_BL(block, (uintptr_t)readmemll);
else if (size == 8)
host_arm_BL(block, (uintptr_t)readmemql);
else
fatal("build_load_routine - unknown size %i\n", size);
if (size == 4 && is_float)
host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0);
else if (size == 8)
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
*branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2;
if (size != 1)
*misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2;
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
if (size == 1)
host_arm_BL(block, (uintptr_t) readmembl);
else if (size == 2)
host_arm_BL(block, (uintptr_t) readmemwl);
else if (size == 4)
host_arm_BL(block, (uintptr_t) readmemll);
else if (size == 8)
host_arm_BL(block, (uintptr_t) readmemql);
else
fatal("build_load_routine - unknown size %i\n", size);
if (size == 4 && is_float)
host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0);
else if (size == 8)
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
static void
build_store_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
uint32_t *branch_offset;
uint32_t *misaligned_offset;
/*In - R0 = address
Out - R0 = data, R1 = abrt*/
/*MOV R1, R0, LSR #12
MOV R2, #readlookup2
LDR R1, [R2, R1, LSL #2]
CMP R1, #-1
BNE +
LDRB R0, [R1, R0]
MOV R1, #0
MOV PC, LR
* STR LR, [SP, -4]!
BL readmembl
LDRB R1, cpu_state.abrt
LDR PC, [SP], #4
*/
codegen_alloc(block, 80);
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2);
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
if (size != 1)
{
host_arm_TST_IMM(block, REG_R0, size-1);
misaligned_offset = host_arm_BNE_(block);
}
host_arm_CMP_IMM(block, REG_R2, -1);
branch_offset = host_arm_BEQ_(block);
if (size == 1 && !is_float)
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 2 && !is_float)
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 4 && !is_float)
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 4 && is_float)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
}
else if (size == 8)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
}
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_MOV_REG(block, REG_PC, REG_LR);
/*In - R0 = address
Out - R0 = data, R1 = abrt*/
/*MOV R1, R0, LSR #12
MOV R2, #readlookup2
LDR R1, [R2, R1, LSL #2]
CMP R1, #-1
BNE +
LDRB R0, [R1, R0]
MOV R1, #0
MOV PC, LR
* STR LR, [SP, -4]!
BL readmembl
LDRB R1, cpu_state.abrt
LDR PC, [SP], #4
*/
codegen_alloc(block, 80);
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
host_arm_MOV_IMM(block, REG_R3, (uint32_t) writelookup2);
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
if (size != 1) {
host_arm_TST_IMM(block, REG_R0, size - 1);
misaligned_offset = host_arm_BNE_(block);
}
host_arm_CMP_IMM(block, REG_R2, -1);
branch_offset = host_arm_BEQ_(block);
if (size == 1 && !is_float)
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 2 && !is_float)
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 4 && !is_float)
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 4 && is_float) {
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
} else if (size == 8) {
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
}
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_MOV_REG(block, REG_PC, REG_LR);
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
if (size != 1)
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
if (size == 4 && is_float)
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
else if (size == 8)
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
if (size == 1)
host_arm_BL(block, (uintptr_t)writemembl);
else if (size == 2)
host_arm_BL(block, (uintptr_t)writememwl);
else if (size == 4)
host_arm_BL(block, (uintptr_t)writememll);
else if (size == 8)
host_arm_BL_r1(block, (uintptr_t)writememql);
else
fatal("build_store_routine - unknown size %i\n", size);
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
*branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2;
if (size != 1)
*misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2;
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
if (size == 4 && is_float)
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
else if (size == 8)
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
if (size == 1)
host_arm_BL(block, (uintptr_t) writemembl);
else if (size == 2)
host_arm_BL(block, (uintptr_t) writememwl);
else if (size == 4)
host_arm_BL(block, (uintptr_t) writememll);
else if (size == 8)
host_arm_BL_r1(block, (uintptr_t) writememql);
else
fatal("build_store_routine - unknown size %i\n", size);
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
}
static void build_loadstore_routines(codeblock_t *block)
static void
build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &block_write_data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &block_write_data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &block_write_data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &block_write_data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &block_write_data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &block_write_data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_load_byte = &block_write_data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &block_write_data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &block_write_data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &block_write_data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &block_write_data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &block_write_data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &block_write_data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &block_write_data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &block_write_data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &block_write_data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &block_write_data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &block_write_data[block_pos];
build_store_routine(block, 8, 1);
codegen_mem_store_byte = &block_write_data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &block_write_data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &block_write_data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &block_write_data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &block_write_data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &block_write_data[block_pos];
build_store_routine(block, 8, 1);
}
/*VFP has a specific round-to-zero instruction, and the default rounding mode
is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/
#define FPCSR_ROUNDING_MASK (3 << 22)
#define FPCSR_ROUNDING_UP (1 << 22)
#define FPCSR_ROUNDING_DOWN (2 << 22)
# define FPCSR_ROUNDING_MASK (3 << 22)
# define FPCSR_ROUNDING_UP (1 << 22)
# define FPCSR_ROUNDING_DOWN (2 << 22)
static void build_fp_round_routine(codeblock_t *block)
static void
build_fp_round_routine(codeblock_t *block)
{
uint32_t *jump_table;
uint32_t *jump_table;
codegen_alloc(block, 80);
codegen_alloc(block, 80);
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
host_arm_NOP(block);
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state);
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
host_arm_NOP(block);
jump_table = (uint32_t *)&block_write_data[block_pos];
host_arm_NOP(block);
host_arm_NOP(block);
host_arm_NOP(block);
host_arm_NOP(block);
jump_table = (uint32_t *) &block_write_data[block_pos];
host_arm_NOP(block);
host_arm_NOP(block);
host_arm_NOP(block);
host_arm_NOP(block);
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
host_arm_VMSR_FPSCR(block, REG_TEMP2);
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_VMSR_FPSCR(block, REG_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state);
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
host_arm_VMSR_FPSCR(block, REG_TEMP2);
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_VMSR_FPSCR(block, REG_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
host_arm_VMSR_FPSCR(block, REG_TEMP2);
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_VMSR_FPSCR(block, REG_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state);
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
host_arm_VMSR_FPSCR(block, REG_TEMP2);
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_VMSR_FPSCR(block, REG_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
}
void codegen_backend_init(void)
void
codegen_backend_init(void)
{
codeblock_t *block;
int c;
codeblock_t *block;
int c;
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(&codeblock[block_current]);
//pclog("block_pos=%i\n", block_pos);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(&codeblock[block_current]);
// pclog("block_pos=%i\n", block_pos);
codegen_fp_round = &block_write_data[block_pos];
build_fp_round_routine(&codeblock[block_current]);
codegen_fp_round = &block_write_data[block_pos];
build_fp_round_routine(&codeblock[block_current]);
codegen_alloc(block, 80);
codegen_gpf_rout = &block_write_data[block_pos];
host_arm_MOV_IMM(block, REG_R0, 0);
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_call(block, x86gpf);
codegen_alloc(block, 80);
codegen_gpf_rout = &block_write_data[block_pos];
host_arm_MOV_IMM(block, REG_R0, 0);
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_call(block, x86gpf);
codegen_exit_rout = &block_write_data[block_pos];
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
codegen_exit_rout = &block_write_data[block_pos];
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
block_write_data = NULL;
//fatal("block_pos=%i\n", block_pos);
asm("vmrs %0, fpscr\n"
: "=r" (cpu_state.old_fp_control)
);
if ((cpu_state.old_fp_control >> 22) & 3)
fatal("VFP not in nearest rounding mode\n");
block_write_data = NULL;
// fatal("block_pos=%i\n", block_pos);
asm("vmrs %0, fpscr\n"
: "=r"(cpu_state.old_fp_control));
if ((cpu_state.old_fp_control >> 22) & 3)
fatal("VFP not in nearest rounding mode\n");
}
void codegen_set_rounding_mode(int mode)
void
codegen_set_rounding_mode(int mode)
{
if (mode < 0 || mode > 3)
fatal("codegen_set_rounding_mode - invalid mode\n");
cpu_state.new_fp_control = mode << 2;
if (mode < 0 || mode > 3)
fatal("codegen_set_rounding_mode - invalid mode\n");
cpu_state.new_fp_control = mode << 2;
}
/*R10 - cpu_state*/
void codegen_backend_prologue(codeblock_t *block)
void
codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START;
block_pos = BLOCK_START;
/*Entry code*/
/*Entry code*/
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
}
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t) &cpu_state);
if (block->flags & CODEBLOCK_HAS_FPU) {
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state);
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
}
}
void codegen_backend_epilogue(codeblock_t *block)
void
codegen_backend_epilogue(codeblock_t *block)
{
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
codegen_allocator_clean_blocks(block->head_mem_block);
codegen_allocator_clean_blocks(block->head_mem_block);
}
#endif

View File

@@ -1,15 +1,15 @@
#include "codegen_backend_arm_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define HASH(l) ((l) &0x1ffff)
#define BLOCK_MAX 0x3c0
#define BLOCK_MAX 0x3c0
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);

View File

@@ -1,28 +1,28 @@
#if defined __aarch64__ || defined _M_ARM64
#include <stdlib.h>
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
# include <stdlib.h>
# include <stdint.h>
# include <86box/86box.h>
# include "cpu.h"
# include <86box/mem.h>
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_arm64_defs.h"
#include "codegen_backend_arm64_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#include "x87.h"
# include "codegen.h"
# include "codegen_allocator.h"
# include "codegen_backend.h"
# include "codegen_backend_arm64_defs.h"
# include "codegen_backend_arm64_ops.h"
# include "codegen_reg.h"
# include "x86.h"
# include "x87.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
#include <string.h>
# if defined(__linux__) || defined(__APPLE__)
# include <sys/mman.h>
# include <unistd.h>
# endif
# if defined WIN32 || defined _WIN32 || defined _WIN32
# include <windows.h>
# endif
# include <string.h>
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
@@ -44,334 +44,335 @@ void *codegen_fp_round_quad;
void *codegen_gpf_rout;
void *codegen_exit_rout;
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
{REG_X19, 0},
{REG_X20, 0},
{REG_X21, 0},
{REG_X22, 0},
{REG_X23, 0},
{REG_X24, 0},
{REG_X25, 0},
{REG_X26, 0},
{REG_X27, 0},
{REG_X28, 0}
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = {
{REG_X19, 0},
{ REG_X20, 0},
{ REG_X21, 0},
{ REG_X22, 0},
{ REG_X23, 0},
{ REG_X24, 0},
{ REG_X25, 0},
{ REG_X26, 0},
{ REG_X27, 0},
{ REG_X28, 0}
};
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
{REG_V8, 0},
{REG_V9, 0},
{REG_V10, 0},
{REG_V11, 0},
{REG_V12, 0},
{REG_V13, 0},
{REG_V14, 0},
{REG_V15, 0}
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = {
{REG_V8, 0},
{ REG_V9, 0},
{ REG_V10, 0},
{ REG_V11, 0},
{ REG_V12, 0},
{ REG_V13, 0},
{ REG_V14, 0},
{ REG_V15, 0}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
static void
build_load_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
uint32_t *branch_offset;
uint32_t *misaligned_offset;
/*In - W0 = address
Out - W0 = data, W1 = abrt*/
/*MOV W1, W0, LSR #12
MOV X2, #readlookup2
LDR X1, [X2, X1, LSL #3]
CMP X1, #-1
BEQ +
LDRB W0, [X1, X0]
MOV W1, #0
RET
* STP X29, X30, [SP, #-16]
BL readmembl
LDRB R1, cpu_state.abrt
LDP X29, X30, [SP, #-16]
RET
*/
codegen_alloc(block, 80);
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2);
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
if (size != 1)
{
host_arm64_TST_IMM(block, REG_W0, size-1);
misaligned_offset = host_arm64_BNE_(block);
}
host_arm64_CMPX_IMM(block, REG_X1, -1);
branch_offset = host_arm64_BEQ_(block);
if (size == 1 && !is_float)
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 2 && !is_float)
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 4 && !is_float)
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 4 && is_float)
host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0);
else if (size == 8)
host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0);
host_arm64_MOVZ_IMM(block, REG_W1, 0);
host_arm64_RET(block, REG_X30);
/*In - W0 = address
Out - W0 = data, W1 = abrt*/
/*MOV W1, W0, LSR #12
MOV X2, #readlookup2
LDR X1, [X2, X1, LSL #3]
CMP X1, #-1
BEQ +
LDRB W0, [X1, X0]
MOV W1, #0
RET
* STP X29, X30, [SP, #-16]
BL readmembl
LDRB R1, cpu_state.abrt
LDP X29, X30, [SP, #-16]
RET
*/
codegen_alloc(block, 80);
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
host_arm64_MOVX_IMM(block, REG_X2, (uint64_t) readlookup2);
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
if (size != 1) {
host_arm64_TST_IMM(block, REG_W0, size - 1);
misaligned_offset = host_arm64_BNE_(block);
}
host_arm64_CMPX_IMM(block, REG_X1, -1);
branch_offset = host_arm64_BEQ_(block);
if (size == 1 && !is_float)
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 2 && !is_float)
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 4 && !is_float)
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 4 && is_float)
host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0);
else if (size == 8)
host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0);
host_arm64_MOVZ_IMM(block, REG_W1, 0);
host_arm64_RET(block, REG_X30);
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
if (size != 1)
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
if (size == 1)
host_arm64_call(block, (void *)readmembl);
else if (size == 2)
host_arm64_call(block, (void *)readmemwl);
else if (size == 4)
host_arm64_call(block, (void *)readmemll);
else if (size == 8)
host_arm64_call(block, (void *)readmemql);
else
fatal("build_load_routine - unknown size %i\n", size);
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
if (size == 4 && is_float)
host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0);
else if (size == 8)
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
if (size != 1)
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
if (size == 1)
host_arm64_call(block, (void *) readmembl);
else if (size == 2)
host_arm64_call(block, (void *) readmemwl);
else if (size == 4)
host_arm64_call(block, (void *) readmemll);
else if (size == 8)
host_arm64_call(block, (void *) readmemql);
else
fatal("build_load_routine - unknown size %i\n", size);
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
if (size == 4 && is_float)
host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0);
else if (size == 8)
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
static void
build_store_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
uint32_t *branch_offset;
uint32_t *misaligned_offset;
/*In - R0 = address, R1 = data
Out - R1 = abrt*/
/*MOV W2, W0, LSR #12
MOV X3, #writelookup2
LDR X2, [X3, X2, LSL #3]
CMP X2, #-1
BEQ +
STRB W1, [X2, X0]
MOV W1, #0
RET
* STP X29, X30, [SP, #-16]
BL writemembl
LDRB R1, cpu_state.abrt
LDP X29, X30, [SP, #-16]
RET
*/
codegen_alloc(block, 80);
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2);
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
if (size != 1)
{
host_arm64_TST_IMM(block, REG_W0, size-1);
misaligned_offset = host_arm64_BNE_(block);
}
host_arm64_CMPX_IMM(block, REG_X2, -1);
branch_offset = host_arm64_BEQ_(block);
if (size == 1 && !is_float)
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 2 && !is_float)
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 4 && !is_float)
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 4 && is_float)
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
else if (size == 8)
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
host_arm64_MOVZ_IMM(block, REG_X1, 0);
host_arm64_RET(block, REG_X30);
/*In - R0 = address, R1 = data
Out - R1 = abrt*/
/*MOV W2, W0, LSR #12
MOV X3, #writelookup2
LDR X2, [X3, X2, LSL #3]
CMP X2, #-1
BEQ +
STRB W1, [X2, X0]
MOV W1, #0
RET
* STP X29, X30, [SP, #-16]
BL writemembl
LDRB R1, cpu_state.abrt
LDP X29, X30, [SP, #-16]
RET
*/
codegen_alloc(block, 80);
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
host_arm64_MOVX_IMM(block, REG_X3, (uint64_t) writelookup2);
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
if (size != 1) {
host_arm64_TST_IMM(block, REG_W0, size - 1);
misaligned_offset = host_arm64_BNE_(block);
}
host_arm64_CMPX_IMM(block, REG_X2, -1);
branch_offset = host_arm64_BEQ_(block);
if (size == 1 && !is_float)
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 2 && !is_float)
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 4 && !is_float)
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 4 && is_float)
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
else if (size == 8)
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
host_arm64_MOVZ_IMM(block, REG_X1, 0);
host_arm64_RET(block, REG_X30);
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
if (size != 1)
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
if (size == 4 && is_float)
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
else if (size == 8)
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
if (size == 1)
host_arm64_call(block, (void *)writemembl);
else if (size == 2)
host_arm64_call(block, (void *)writememwl);
else if (size == 4)
host_arm64_call(block, (void *)writememll);
else if (size == 8)
host_arm64_call(block, (void *)writememql);
else
fatal("build_store_routine - unknown size %i\n", size);
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
if (size != 1)
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
if (size == 4 && is_float)
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
else if (size == 8)
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
if (size == 1)
host_arm64_call(block, (void *) writemembl);
else if (size == 2)
host_arm64_call(block, (void *) writememwl);
else if (size == 4)
host_arm64_call(block, (void *) writememll);
else if (size == 8)
host_arm64_call(block, (void *) writememql);
else
fatal("build_store_routine - unknown size %i\n", size);
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
}
static void build_loadstore_routines(codeblock_t *block)
static void
build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &block_write_data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &block_write_data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &block_write_data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &block_write_data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &block_write_data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &block_write_data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_load_byte = &block_write_data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &block_write_data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &block_write_data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &block_write_data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &block_write_data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &block_write_data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &block_write_data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &block_write_data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &block_write_data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &block_write_data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &block_write_data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &block_write_data[block_pos];
build_store_routine(block, 8, 1);
codegen_mem_store_byte = &block_write_data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &block_write_data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &block_write_data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &block_write_data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &block_write_data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &block_write_data[block_pos];
build_store_routine(block, 8, 1);
}
static void build_fp_round_routine(codeblock_t *block, int is_quad)
static void
build_fp_round_routine(codeblock_t *block, int is_quad)
{
uint64_t *jump_table;
uint64_t *jump_table;
codegen_alloc(block, 80);
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
host_arm64_ADR(block, REG_TEMP2, 12);
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
host_arm64_BR(block, REG_TEMP2);
codegen_alloc(block, 80);
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state);
host_arm64_ADR(block, REG_TEMP2, 12);
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
host_arm64_BR(block, REG_TEMP2);
jump_table = (uint64_t *)&block_write_data[block_pos];
block_pos += 4*8;
jump_table = (uint64_t *) &block_write_data[block_pos];
block_pos += 4 * 8;
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
if (is_quad)
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even
if (is_quad)
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
if (is_quad)
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf
if (is_quad)
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
if (is_quad)
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf
if (is_quad)
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
if (is_quad)
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero
if (is_quad)
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
}
void codegen_backend_init(void)
void
codegen_backend_init(void)
{
codeblock_t *block;
int c;
codeblock_t *block;
int c;
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
{
codeblock[c].pc = BLOCK_PC_INVALID;
}
for (c = 0; c < BLOCK_SIZE; c++) {
codeblock[c].pc = BLOCK_PC_INVALID;
}
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);
codegen_fp_round = &block_write_data[block_pos];
build_fp_round_routine(block, 0);
codegen_fp_round_quad = &block_write_data[block_pos];
build_fp_round_routine(block, 1);
codegen_fp_round = &block_write_data[block_pos];
build_fp_round_routine(block, 0);
codegen_fp_round_quad = &block_write_data[block_pos];
build_fp_round_routine(block, 1);
codegen_alloc(block, 80);
codegen_gpf_rout = &block_write_data[block_pos];
host_arm64_mov_imm(block, REG_ARG0, 0);
host_arm64_mov_imm(block, REG_ARG1, 0);
host_arm64_call(block, (void *)x86gpf);
codegen_alloc(block, 80);
codegen_gpf_rout = &block_write_data[block_pos];
host_arm64_mov_imm(block, REG_ARG0, 0);
host_arm64_mov_imm(block, REG_ARG1, 0);
host_arm64_call(block, (void *) x86gpf);
codegen_exit_rout = &block_write_data[block_pos];
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
codegen_exit_rout = &block_write_data[block_pos];
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
block_write_data = NULL;
block_write_data = NULL;
codegen_allocator_clean_blocks(block->head_mem_block);
codegen_allocator_clean_blocks(block->head_mem_block);
asm("mrs %0, fpcr\n"
: "=r" (cpu_state.old_fp_control)
);
asm("mrs %0, fpcr\n"
: "=r"(cpu_state.old_fp_control));
}
void codegen_set_rounding_mode(int mode)
void
codegen_set_rounding_mode(int mode)
{
if (mode < 0 || mode > 3)
fatal("codegen_set_rounding_mode - invalid mode\n");
cpu_state.new_fp_control = mode << 3;
if (mode < 0 || mode > 3)
fatal("codegen_set_rounding_mode - invalid mode\n");
cpu_state.new_fp_control = mode << 3;
}
/*R10 - cpu_state*/
void codegen_backend_prologue(codeblock_t *block)
void
codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START;
block_pos = BLOCK_START;
/*Entry code*/
/*Entry code*/
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64);
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state);
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t) &cpu_state);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset);
}
if (block->flags & CODEBLOCK_HAS_FPU) {
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state);
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset);
}
}
void codegen_backend_epilogue(codeblock_t *block)
void
codegen_backend_epilogue(codeblock_t *block)
{
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
codegen_allocator_clean_blocks(block->head_mem_block);
codegen_allocator_clean_blocks(block->head_mem_block);
}
#endif

View File

@@ -1,16 +1,15 @@
#include "codegen_backend_arm64_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0
#define HASH(l) ((l) &0x1ffff)
#define BLOCK_MAX 0x3c0
void host_arm64_BLR(codeblock_t *block, int addr_reg);
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);

View File

@@ -1,117 +1,117 @@
#define REG_W0 0
#define REG_W1 1
#define REG_W2 2
#define REG_W3 3
#define REG_W4 4
#define REG_W5 5
#define REG_W6 6
#define REG_W7 7
#define REG_W8 8
#define REG_W9 9
#define REG_W10 10
#define REG_W11 11
#define REG_W12 12
#define REG_W13 13
#define REG_W14 14
#define REG_W15 15
#define REG_W16 16
#define REG_W17 17
#define REG_W18 18
#define REG_W19 19
#define REG_W20 20
#define REG_W21 21
#define REG_W22 22
#define REG_W23 23
#define REG_W24 24
#define REG_W25 25
#define REG_W26 26
#define REG_W27 27
#define REG_W28 28
#define REG_W29 29
#define REG_W30 30
#define REG_WZR 31
#define REG_W0 0
#define REG_W1 1
#define REG_W2 2
#define REG_W3 3
#define REG_W4 4
#define REG_W5 5
#define REG_W6 6
#define REG_W7 7
#define REG_W8 8
#define REG_W9 9
#define REG_W10 10
#define REG_W11 11
#define REG_W12 12
#define REG_W13 13
#define REG_W14 14
#define REG_W15 15
#define REG_W16 16
#define REG_W17 17
#define REG_W18 18
#define REG_W19 19
#define REG_W20 20
#define REG_W21 21
#define REG_W22 22
#define REG_W23 23
#define REG_W24 24
#define REG_W25 25
#define REG_W26 26
#define REG_W27 27
#define REG_W28 28
#define REG_W29 29
#define REG_W30 30
#define REG_WZR 31
#define REG_X0 0
#define REG_X1 1
#define REG_X2 2
#define REG_X3 3
#define REG_X4 4
#define REG_X5 5
#define REG_X6 6
#define REG_X7 7
#define REG_X8 8
#define REG_X9 9
#define REG_X10 10
#define REG_X11 11
#define REG_X12 12
#define REG_X13 13
#define REG_X14 14
#define REG_X15 15
#define REG_X16 16
#define REG_X17 17
#define REG_X18 18
#define REG_X19 19
#define REG_X20 20
#define REG_X21 21
#define REG_X22 22
#define REG_X23 23
#define REG_X24 24
#define REG_X25 25
#define REG_X26 26
#define REG_X27 27
#define REG_X28 28
#define REG_X29 29
#define REG_X30 30
#define REG_XZR 31
#define REG_X0 0
#define REG_X1 1
#define REG_X2 2
#define REG_X3 3
#define REG_X4 4
#define REG_X5 5
#define REG_X6 6
#define REG_X7 7
#define REG_X8 8
#define REG_X9 9
#define REG_X10 10
#define REG_X11 11
#define REG_X12 12
#define REG_X13 13
#define REG_X14 14
#define REG_X15 15
#define REG_X16 16
#define REG_X17 17
#define REG_X18 18
#define REG_X19 19
#define REG_X20 20
#define REG_X21 21
#define REG_X22 22
#define REG_X23 23
#define REG_X24 24
#define REG_X25 25
#define REG_X26 26
#define REG_X27 27
#define REG_X28 28
#define REG_X29 29
#define REG_X30 30
#define REG_XZR 31
#define REG_V0 0
#define REG_V1 1
#define REG_V2 2
#define REG_V3 3
#define REG_V4 4
#define REG_V5 5
#define REG_V6 6
#define REG_V7 7
#define REG_V8 8
#define REG_V9 9
#define REG_V10 10
#define REG_V11 11
#define REG_V12 12
#define REG_V13 13
#define REG_V14 14
#define REG_V15 15
#define REG_V16 16
#define REG_V17 17
#define REG_V18 18
#define REG_V19 19
#define REG_V20 20
#define REG_V21 21
#define REG_V22 22
#define REG_V23 23
#define REG_V24 24
#define REG_V25 25
#define REG_V26 26
#define REG_V27 27
#define REG_V28 28
#define REG_V29 29
#define REG_V30 30
#define REG_V31 31
#define REG_V0 0
#define REG_V1 1
#define REG_V2 2
#define REG_V3 3
#define REG_V4 4
#define REG_V5 5
#define REG_V6 6
#define REG_V7 7
#define REG_V8 8
#define REG_V9 9
#define REG_V10 10
#define REG_V11 11
#define REG_V12 12
#define REG_V13 13
#define REG_V14 14
#define REG_V15 15
#define REG_V16 16
#define REG_V17 17
#define REG_V18 18
#define REG_V19 19
#define REG_V20 20
#define REG_V21 21
#define REG_V22 22
#define REG_V23 23
#define REG_V24 24
#define REG_V25 25
#define REG_V26 26
#define REG_V27 27
#define REG_V28 28
#define REG_V29 29
#define REG_V30 30
#define REG_V31 31
#define REG_XSP 31
#define REG_XSP 31
#define REG_ARG0 REG_X0
#define REG_ARG1 REG_X1
#define REG_ARG2 REG_X2
#define REG_ARG3 REG_X3
#define REG_ARG0 REG_X0
#define REG_ARG1 REG_X1
#define REG_ARG2 REG_X2
#define REG_ARG3 REG_X3
#define REG_CPUSTATE REG_X29
#define REG_CPUSTATE REG_X29
#define REG_TEMP REG_X7
#define REG_TEMP2 REG_X6
#define REG_TEMP REG_X7
#define REG_TEMP2 REG_X6
#define REG_V_TEMP REG_V0
#define REG_V_TEMP REG_V0
#define CODEGEN_HOST_REGS 10
#define CODEGEN_HOST_REGS 10
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -251,13 +251,11 @@ void host_arm64_call(codeblock_t *block, void *dst_addr);
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr);
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) &7))
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1))
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7))
#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) &1))
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) &3))
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) &7))
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);

File diff suppressed because it is too large Load Diff

View File

@@ -1,72 +1,71 @@
#define REG_R0 0
#define REG_R1 1
#define REG_R2 2
#define REG_R3 3
#define REG_R4 4
#define REG_R5 5
#define REG_R6 6
#define REG_R7 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_HOST_SP 13
#define REG_LR 14
#define REG_PC 15
#define REG_R0 0
#define REG_R1 1
#define REG_R2 2
#define REG_R3 3
#define REG_R4 4
#define REG_R5 5
#define REG_R6 6
#define REG_R7 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_HOST_SP 13
#define REG_LR 14
#define REG_PC 15
#define REG_ARG0 REG_R0
#define REG_ARG1 REG_R1
#define REG_ARG2 REG_R2
#define REG_ARG3 REG_R3
#define REG_ARG0 REG_R0
#define REG_ARG1 REG_R1
#define REG_ARG2 REG_R2
#define REG_ARG3 REG_R3
#define REG_CPUSTATE REG_R10
#define REG_CPUSTATE REG_R10
#define REG_TEMP REG_R3
#define REG_TEMP2 REG_R2
#define REG_TEMP REG_R3
#define REG_TEMP2 REG_R2
#define REG_D0 0
#define REG_D1 1
#define REG_D2 2
#define REG_D3 3
#define REG_D4 4
#define REG_D5 5
#define REG_D6 6
#define REG_D7 7
#define REG_D8 8
#define REG_D9 9
#define REG_D10 10
#define REG_D11 11
#define REG_D12 12
#define REG_D13 13
#define REG_D14 14
#define REG_D15 15
#define REG_D0 0
#define REG_D1 1
#define REG_D2 2
#define REG_D3 3
#define REG_D4 4
#define REG_D5 5
#define REG_D6 6
#define REG_D7 7
#define REG_D8 8
#define REG_D9 9
#define REG_D10 10
#define REG_D11 11
#define REG_D12 12
#define REG_D13 13
#define REG_D14 14
#define REG_D15 15
#define REG_D_TEMP REG_D0
#define REG_Q_TEMP REG_D0
#define REG_Q_TEMP_2 REG_D2
#define REG_D_TEMP REG_D0
#define REG_Q_TEMP REG_D0
#define REG_Q_TEMP_2 REG_D2
#define REG_MASK_R0 (1 << REG_R0)
#define REG_MASK_R1 (1 << REG_R1)
#define REG_MASK_R2 (1 << REG_R2)
#define REG_MASK_R3 (1 << REG_R3)
#define REG_MASK_R4 (1 << REG_R4)
#define REG_MASK_R5 (1 << REG_R5)
#define REG_MASK_R6 (1 << REG_R6)
#define REG_MASK_R7 (1 << REG_R7)
#define REG_MASK_R8 (1 << REG_R8)
#define REG_MASK_R9 (1 << REG_R9)
#define REG_MASK_R10 (1 << REG_R10)
#define REG_MASK_R11 (1 << REG_R11)
#define REG_MASK_R12 (1 << REG_R12)
#define REG_MASK_SP (1 << REG_HOST_SP)
#define REG_MASK_LR (1 << REG_LR)
#define REG_MASK_PC (1 << REG_PC)
#define REG_MASK_R0 (1 << REG_R0)
#define REG_MASK_R1 (1 << REG_R1)
#define REG_MASK_R2 (1 << REG_R2)
#define REG_MASK_R3 (1 << REG_R3)
#define REG_MASK_R4 (1 << REG_R4)
#define REG_MASK_R5 (1 << REG_R5)
#define REG_MASK_R6 (1 << REG_R6)
#define REG_MASK_R7 (1 << REG_R7)
#define REG_MASK_R8 (1 << REG_R8)
#define REG_MASK_R9 (1 << REG_R9)
#define REG_MASK_R10 (1 << REG_R10)
#define REG_MASK_R11 (1 << REG_R11)
#define REG_MASK_R12 (1 << REG_R12)
#define REG_MASK_SP (1 << REG_HOST_SP)
#define REG_MASK_LR (1 << REG_LR)
#define REG_MASK_PC (1 << REG_PC)
#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \
REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
#define CODEGEN_HOST_REGS 7
#define CODEGEN_HOST_REGS 7
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,19 @@
#define COND_SHIFT 28
#define COND_EQ (0x0 << COND_SHIFT)
#define COND_NE (0x1 << COND_SHIFT)
#define COND_CS (0x2 << COND_SHIFT)
#define COND_CC (0x3 << COND_SHIFT)
#define COND_MI (0x4 << COND_SHIFT)
#define COND_PL (0x5 << COND_SHIFT)
#define COND_VS (0x6 << COND_SHIFT)
#define COND_VC (0x7 << COND_SHIFT)
#define COND_HI (0x8 << COND_SHIFT)
#define COND_LS (0x9 << COND_SHIFT)
#define COND_GE (0xa << COND_SHIFT)
#define COND_LT (0xb << COND_SHIFT)
#define COND_GT (0xc << COND_SHIFT)
#define COND_LE (0xd << COND_SHIFT)
#define COND_AL (0xe << COND_SHIFT)
#define COND_EQ (0x0 << COND_SHIFT)
#define COND_NE (0x1 << COND_SHIFT)
#define COND_CS (0x2 << COND_SHIFT)
#define COND_CC (0x3 << COND_SHIFT)
#define COND_MI (0x4 << COND_SHIFT)
#define COND_PL (0x5 << COND_SHIFT)
#define COND_VS (0x6 << COND_SHIFT)
#define COND_VC (0x7 << COND_SHIFT)
#define COND_HI (0x8 << COND_SHIFT)
#define COND_LS (0x9 << COND_SHIFT)
#define COND_GE (0xa << COND_SHIFT)
#define COND_LT (0xb << COND_SHIFT)
#define COND_GT (0xc << COND_SHIFT)
#define COND_LE (0xd << COND_SHIFT)
#define COND_AL (0xe << COND_SHIFT)
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
#define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0)
@@ -101,12 +101,12 @@ void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shif
void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm);
void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift);
#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm)
#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm)
#define host_arm_ORR_REG_LSL(block, dst_reg, src_reg_a, src_reg_b, shift) host_arm_ORR_REG_LSL_cond(block, COND_AL, dst_reg, src_reg_a, src_reg_b, shift)
#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm)
#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm)
#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm)
#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm)
#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm)
#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm)
void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,28 @@
#if defined __amd64__ || defined _M_X64
#include <stdlib.h>
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
# include <stdlib.h>
# include <stdint.h>
# include <86box/86box.h>
# include "cpu.h"
# include <86box/mem.h>
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86-64_defs.h"
#include "codegen_backend_x86-64_ops.h"
#include "codegen_backend_x86-64_ops_sse.h"
#include "codegen_reg.h"
#include "x86.h"
# include "codegen.h"
# include "codegen_allocator.h"
# include "codegen_backend.h"
# include "codegen_backend_x86-64_defs.h"
# include "codegen_backend_x86-64_ops.h"
# include "codegen_backend_x86-64_ops_sse.h"
# include "codegen_reg.h"
# include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
#include <string.h>
# if defined(__linux__) || defined(__APPLE__)
# include <sys/mman.h>
# include <unistd.h>
# endif
# if defined WIN32 || defined _WIN32 || defined _WIN32
# include <windows.h>
# endif
# include <string.h>
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
@@ -41,346 +41,338 @@ void *codegen_mem_store_double;
void *codegen_gpf_rout;
void *codegen_exit_rout;
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
/*Note: while EAX and EDX are normally volatile registers under x86
calling conventions, the recompiler will explicitly save and restore
them across funcion calls*/
{REG_EAX, 0},
{REG_EBX, 0},
{REG_EDX, 0}
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = {
/*Note: while EAX and EDX are normally volatile registers under x86
calling conventions, the recompiler will explicitly save and restore
them across funcion calls*/
{REG_EAX, 0},
{ REG_EBX, 0},
{ REG_EDX, 0}
};
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
#if _WIN64
/*Windows x86-64 calling convention preserves XMM6-XMM15*/
{REG_XMM6, 0},
{REG_XMM7, 0},
#else
/*System V AMD64 calling convention does not preserve any XMM registers*/
{REG_XMM6, HOST_REG_FLAG_VOLATILE},
{REG_XMM7, HOST_REG_FLAG_VOLATILE},
#endif
{REG_XMM1, HOST_REG_FLAG_VOLATILE},
{REG_XMM2, HOST_REG_FLAG_VOLATILE},
{REG_XMM3, HOST_REG_FLAG_VOLATILE},
{REG_XMM4, HOST_REG_FLAG_VOLATILE},
{REG_XMM5, HOST_REG_FLAG_VOLATILE}
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = {
# if _WIN64
/*Windows x86-64 calling convention preserves XMM6-XMM15*/
{REG_XMM6, 0 },
{ REG_XMM7, 0 },
# else
/*System V AMD64 calling convention does not preserve any XMM registers*/
{ REG_XMM6, HOST_REG_FLAG_VOLATILE },
{ REG_XMM7, HOST_REG_FLAG_VOLATILE },
# endif
{ REG_XMM1, HOST_REG_FLAG_VOLATILE},
{ REG_XMM2, HOST_REG_FLAG_VOLATILE},
{ REG_XMM3, HOST_REG_FLAG_VOLATILE},
{ REG_XMM4, HOST_REG_FLAG_VOLATILE},
{ REG_XMM5, HOST_REG_FLAG_VOLATILE}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
static void
build_load_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset;
uint8_t *branch_offset;
uint8_t *misaligned_offset;
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
/*MOV ECX, ESI
SHR ESI, 12
MOV RSI, [readlookup2+ESI*4]
CMP ESI, -1
JNZ +
MOVZX ECX, B[RSI+RCX]
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL readmembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2);
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 2 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 4 && is_float)
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
else if (size == 8)
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
else
fatal("build_load_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
/*MOV ECX, ESI
SHR ESI, 12
MOV RSI, [readlookup2+ESI*4]
CMP ESI, -1
JNZ +
MOVZX ECX, B[RSI+RCX]
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL readmembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t) (uintptr_t) readlookup2);
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3);
if (size != 1) {
host_x86_TEST32_REG_IMM(block, REG_ECX, size - 1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t) -1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 2 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 4 && is_float)
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
else if (size == 8)
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
else
fatal("build_load_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
host_x86_PUSH(block, REG_RAX);
host_x86_PUSH(block, REG_RDX);
#if _WIN64
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
//host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data);
#else
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX);
#endif
if (size == 1 && !is_float)
{
host_x86_CALL(block, (void *)readmembl);
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
}
else if (size == 2 && !is_float)
{
host_x86_CALL(block, (void *)readmemwl);
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
}
else if (size == 4 && !is_float)
{
host_x86_CALL(block, (void *)readmemll);
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
}
else if (size == 4 && is_float)
{
host_x86_CALL(block, (void *)readmemll);
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
}
else if (size == 8)
{
host_x86_CALL(block, (void *)readmemql);
host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX);
}
#if _WIN64
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
#endif
host_x86_POP(block, REG_RDX);
host_x86_POP(block, REG_RAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
*branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1;
host_x86_PUSH(block, REG_RAX);
host_x86_PUSH(block, REG_RDX);
# if _WIN64
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
// host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data);
# else
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX);
# endif
if (size == 1 && !is_float) {
host_x86_CALL(block, (void *) readmembl);
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
} else if (size == 2 && !is_float) {
host_x86_CALL(block, (void *) readmemwl);
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
} else if (size == 4 && !is_float) {
host_x86_CALL(block, (void *) readmemll);
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
} else if (size == 4 && is_float) {
host_x86_CALL(block, (void *) readmemll);
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
} else if (size == 8) {
host_x86_CALL(block, (void *) readmemql);
host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX);
}
# if _WIN64
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
# endif
host_x86_POP(block, REG_RDX);
host_x86_POP(block, REG_RAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
static void
build_store_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset;
uint8_t *branch_offset;
uint8_t *misaligned_offset;
/*In - ECX = data, ESI = address
Out - ESI = abrt
Corrupts EDI*/
/*MOV EDI, ESI
SHR ESI, 12
MOV ESI, [writelookup2+ESI*4]
CMP ESI, -1
JNZ +
MOV [RSI+RDI], ECX
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL writemembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2);
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 4 && is_float)
host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
else if (size == 8)
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
else
fatal("build_store_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
/*In - ECX = data, ESI = address
Out - ESI = abrt
Corrupts EDI*/
/*MOV EDI, ESI
SHR ESI, 12
MOV ESI, [writelookup2+ESI*4]
CMP ESI, -1
JNZ +
MOV [RSI+RDI], ECX
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL writemembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t) (uintptr_t) writelookup2);
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3);
if (size != 1) {
host_x86_TEST32_REG_IMM(block, REG_EDI, size - 1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t) -1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 4 && is_float)
host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
else if (size == 8)
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
else
fatal("build_store_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
host_x86_PUSH(block, REG_RAX);
host_x86_PUSH(block, REG_RDX);
#if _WIN64
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28);
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data
else if (size == 8)
host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data
else
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address
#else
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8);
//host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); //data
else if (size == 8)
host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); //data
else
host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data
#endif
if (size == 1)
host_x86_CALL(block, (void *)writemembl);
else if (size == 2)
host_x86_CALL(block, (void *)writememwl);
else if (size == 4)
host_x86_CALL(block, (void *)writememll);
else if (size == 8)
host_x86_CALL(block, (void *)writememql);
#if _WIN64
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28);
#else
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8);
#endif
host_x86_POP(block, REG_RDX);
host_x86_POP(block, REG_RAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
*branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1;
host_x86_PUSH(block, REG_RAX);
host_x86_PUSH(block, REG_RDX);
# if _WIN64
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28);
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); // data
else if (size == 8)
host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); // data
else
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); // data
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); // address
# else
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8);
// host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); // data
else if (size == 8)
host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); // data
else
host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); // data
# endif
if (size == 1)
host_x86_CALL(block, (void *) writemembl);
else if (size == 2)
host_x86_CALL(block, (void *) writememwl);
else if (size == 4)
host_x86_CALL(block, (void *) writememll);
else if (size == 8)
host_x86_CALL(block, (void *) writememql);
# if _WIN64
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28);
# else
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8);
# endif
host_x86_POP(block, REG_RDX);
host_x86_POP(block, REG_RAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
}
static void build_loadstore_routines(codeblock_t *block)
static void
build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 1);
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 1);
}
void codegen_backend_init(void)
void
codegen_backend_init(void)
{
codeblock_t *block;
int c;
codeblock_t *block;
int c;
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current);
codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block);
block_write_data = codeblock[block_current].data;
build_loadstore_routines(&codeblock[block_current]);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current);
codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block);
block_write_data = codeblock[block_current].data;
build_loadstore_routines(&codeblock[block_current]);
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
#if _WIN64
host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX);
host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX);
#else
host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
#endif
host_x86_CALL(block, (void *)x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
host_x86_POP(block, REG_R14);
host_x86_POP(block, REG_R13);
host_x86_POP(block, REG_R12);
host_x86_POP(block, REG_RDI);
host_x86_POP(block, REG_RSI);
host_x86_POP(block, REG_RBP);
host_x86_POP(block, REG_RDX);
host_x86_RET(block);
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
# if _WIN64
host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX);
host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX);
# else
host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
# endif
host_x86_CALL(block, (void *) x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
host_x86_POP(block, REG_R14);
host_x86_POP(block, REG_R13);
host_x86_POP(block, REG_R12);
host_x86_POP(block, REG_RDI);
host_x86_POP(block, REG_RSI);
host_x86_POP(block, REG_RBP);
host_x86_POP(block, REG_RDX);
host_x86_RET(block);
block_write_data = NULL;
block_write_data = NULL;
asm(
"stmxcsr %0\n"
: "=m" (cpu_state.old_fp_control)
);
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
asm(
"stmxcsr %0\n"
: "=m"(cpu_state.old_fp_control));
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
}
void codegen_set_rounding_mode(int mode)
void
codegen_set_rounding_mode(int mode)
{
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
}
void codegen_backend_prologue(codeblock_t *block)
void
codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START; /*Entry code*/
host_x86_PUSH(block, REG_RBX);
host_x86_PUSH(block, REG_RBP);
host_x86_PUSH(block, REG_RSI);
host_x86_PUSH(block, REG_RDI);
host_x86_PUSH(block, REG_R12);
host_x86_PUSH(block, REG_R13);
host_x86_PUSH(block, REG_R14);
host_x86_PUSH(block, REG_R15);
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38);
host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX);
}
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t)ram);
block_pos = BLOCK_START; /*Entry code*/
host_x86_PUSH(block, REG_RBX);
host_x86_PUSH(block, REG_RBP);
host_x86_PUSH(block, REG_RSI);
host_x86_PUSH(block, REG_RDI);
host_x86_PUSH(block, REG_R12);
host_x86_PUSH(block, REG_R13);
host_x86_PUSH(block, REG_R14);
host_x86_PUSH(block, REG_R15);
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38);
host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t) &cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU) {
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX);
}
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t) ram);
}
void codegen_backend_epilogue(codeblock_t *block)
void
codegen_backend_epilogue(codeblock_t *block)
{
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
host_x86_POP(block, REG_R14);
host_x86_POP(block, REG_R13);
host_x86_POP(block, REG_R12);
host_x86_POP(block, REG_RDI);
host_x86_POP(block, REG_RSI);
host_x86_POP(block, REG_RBP);
host_x86_POP(block, REG_RDX);
host_x86_RET(block);
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
host_x86_POP(block, REG_R14);
host_x86_POP(block, REG_R13);
host_x86_POP(block, REG_R12);
host_x86_POP(block, REG_RDI);
host_x86_POP(block, REG_RSI);
host_x86_POP(block, REG_RBP);
host_x86_POP(block, REG_RDX);
host_x86_RET(block);
}
#endif

View File

@@ -1,14 +1,14 @@
#include "codegen_backend_x86-64_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define HASH(l) ((l) &0x1ffff)
#define BLOCK_MAX 0x3c0
#define BLOCK_MAX 0x3c0
#define CODEGEN_BACKEND_HAS_MOV_IMM

View File

@@ -1,52 +1,52 @@
/*RBP = cpu_state + 128
R12 = ram (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_RAX 0
#define REG_RCX 1
#define REG_RDX 2
#define REG_RBX 3
#define REG_RSP 4
#define REG_RBP 5
#define REG_RSI 6
#define REG_RDI 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_R13 13
#define REG_R14 14
#define REG_R15 15
#define REG_RAX 0
#define REG_RCX 1
#define REG_RDX 2
#define REG_RBX 3
#define REG_RSP 4
#define REG_RBP 5
#define REG_RSI 6
#define REG_RDI 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_R13 13
#define REG_R14 14
#define REG_R15 15
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM_TEMP REG_XMM0
#define REG_XMM_TEMP REG_XMM0
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 7
extern void *codegen_mem_load_byte;

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +1,103 @@
#define JMP_LEN_BYTES 5
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
static inline void
codegen_addbyte(codeblock_t *block, uint8_t val)
{
if (block_pos >= BLOCK_MAX)
{
fatal("codegen_addbyte over! %i\n", block_pos);
// CPU_BLOCK_END();
}
block_write_data[block_pos++] = val;
if (block_pos >= BLOCK_MAX) {
fatal("codegen_addbyte over! %i\n", block_pos);
// CPU_BLOCK_END();
}
block_write_data[block_pos++] = val;
}
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
static inline void
codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
{
if (block_pos > (BLOCK_MAX-2))
{
fatal("codegen_addbyte2 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
if (block_pos > (BLOCK_MAX - 2)) {
fatal("codegen_addbyte2 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
}
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
static inline void
codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
{
if (block_pos > (BLOCK_MAX-3))
{
fatal("codegen_addbyte3 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
if (block_pos > (BLOCK_MAX - 3)) {
fatal("codegen_addbyte3 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
}
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
static inline void
codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
{
if (block_pos > (BLOCK_MAX-4))
{
fatal("codegen_addbyte4 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
block_write_data[block_pos++] = vald;
if (block_pos > (BLOCK_MAX - 4)) {
fatal("codegen_addbyte4 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
block_write_data[block_pos++] = vald;
}
static inline void codegen_addword(codeblock_t *block, uint16_t val)
static inline void
codegen_addword(codeblock_t *block, uint16_t val)
{
if (block_pos > (BLOCK_MAX-2))
{
fatal("codegen_addword over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint16_t *)&block_write_data[block_pos] = val;
block_pos += 2;
if (block_pos > (BLOCK_MAX - 2)) {
fatal("codegen_addword over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint16_t *) &block_write_data[block_pos] = val;
block_pos += 2;
}
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
static inline void
codegen_addlong(codeblock_t *block, uint32_t val)
{
if (block_pos > (BLOCK_MAX-4))
{
fatal("codegen_addlong over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint32_t *)&block_write_data[block_pos] = val;
block_pos += 4;
if (block_pos > (BLOCK_MAX - 4)) {
fatal("codegen_addlong over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint32_t *) &block_write_data[block_pos] = val;
block_pos += 4;
}
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
static inline void
codegen_addquad(codeblock_t *block, uint64_t val)
{
if (block_pos > (BLOCK_MAX-8))
{
fatal("codegen_addquad over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint64_t *)&block_write_data[block_pos] = val;
block_pos += 8;
if (block_pos > (BLOCK_MAX - 8)) {
fatal("codegen_addquad over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint64_t *) &block_write_data[block_pos] = val;
block_pos += 8;
}
static inline void codegen_alloc_bytes(codeblock_t *block, int size)
static inline void
codegen_alloc_bytes(codeblock_t *block, int size)
{
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
{
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES)) {
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Add a jump instruction to the new block*/
codegen_addbyte(block, 0xe9); /*JMP*/
codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]);
/*Add a jump instruction to the new block*/
codegen_addbyte(block, 0xe9); /*JMP*/
codegen_addlong(block, (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos + 4]);
/*Set write address to start of new block*/
block_pos = 0;
block_write_data = new_ptr;
}
/*Set write address to start of new block*/
block_pos = 0;
block_write_data = new_ptr;
}
}
static inline int is_imm8(uint32_t imm_data)
static inline int
is_imm8(uint32_t imm_data)
{
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,29 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
# include <stddef.h>
# include <stdint.h>
# include <stdlib.h>
# include <86box/86box.h>
# include "cpu.h"
# include <86box/mem.h>
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops.h"
#include "codegen_backend_x86_ops_sse.h"
#include "codegen_reg.h"
#include "x86.h"
# include "codegen.h"
# include "codegen_allocator.h"
# include "codegen_backend.h"
# include "codegen_backend_x86_defs.h"
# include "codegen_backend_x86_ops.h"
# include "codegen_backend_x86_ops_sse.h"
# include "codegen_reg.h"
# include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
#include <string.h>
# if defined(__linux__) || defined(__APPLE__)
# include <sys/mman.h>
# include <unistd.h>
# endif
# if defined WIN32 || defined _WIN32 || defined _WIN32
# include <windows.h>
# endif
# include <string.h>
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
@@ -42,306 +42,303 @@ void *codegen_mem_store_double;
void *codegen_gpf_rout;
void *codegen_exit_rout;
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
/*Note: while EAX and EDX are normally volatile registers under x86
calling conventions, the recompiler will explicitly save and restore
them across funcion calls*/
{REG_EAX, 0},
{REG_EBX, 0},
{REG_EDX, 0}
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = {
/*Note: while EAX and EDX are normally volatile registers under x86
calling conventions, the recompiler will explicitly save and restore
them across funcion calls*/
{REG_EAX, 0},
{ REG_EBX, 0},
{ REG_EDX, 0}
};
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
{REG_XMM0, HOST_REG_FLAG_VOLATILE},
{REG_XMM1, HOST_REG_FLAG_VOLATILE},
{REG_XMM2, HOST_REG_FLAG_VOLATILE},
{REG_XMM3, HOST_REG_FLAG_VOLATILE},
{REG_XMM4, HOST_REG_FLAG_VOLATILE},
{REG_XMM5, HOST_REG_FLAG_VOLATILE}
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = {
{REG_XMM0, HOST_REG_FLAG_VOLATILE},
{ REG_XMM1, HOST_REG_FLAG_VOLATILE},
{ REG_XMM2, HOST_REG_FLAG_VOLATILE},
{ REG_XMM3, HOST_REG_FLAG_VOLATILE},
{ REG_XMM4, HOST_REG_FLAG_VOLATILE},
{ REG_XMM5, HOST_REG_FLAG_VOLATILE}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
static void
build_load_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset = NULL;
uint8_t *branch_offset;
uint8_t *misaligned_offset = NULL;
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
/*MOV ECX, ESI
SHR ESI, 12
MOV ESI, [readlookup2+ESI*4]
CMP ESI, -1
JNZ +
MOVZX ECX, B[ESI+ECX]
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL readmembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 4 && is_float)
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
else if (size == 8)
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
else
fatal("build_load_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
/*MOV ECX, ESI
SHR ESI, 12
MOV ESI, [readlookup2+ESI*4]
CMP ESI, -1
JNZ +
MOVZX ECX, B[ESI+ECX]
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL readmembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2);
if (size != 1) {
host_x86_TEST32_REG_IMM(block, REG_ECX, size - 1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t) -1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 4 && is_float)
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
else if (size == 8)
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
else
fatal("build_load_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
host_x86_PUSH(block, REG_EAX);
host_x86_PUSH(block, REG_EDX);
host_x86_PUSH(block, REG_ECX);
if (size == 1)
host_x86_CALL(block, (void *)readmembl);
else if (size == 2)
host_x86_CALL(block, (void *)readmemwl);
else if (size == 4)
host_x86_CALL(block, (void *)readmemll);
else if (size == 8)
host_x86_CALL(block, (void *)readmemql);
host_x86_POP(block, REG_ECX);
if (size == 1 && !is_float)
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
else if (size == 2 && !is_float)
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
else if (size == 4 && is_float)
{
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
}
else if (size == 8)
{
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX);
host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2);
}
host_x86_POP(block, REG_EDX);
host_x86_POP(block, REG_EAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
block_pos = (block_pos + 63) & ~63;
*branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1;
host_x86_PUSH(block, REG_EAX);
host_x86_PUSH(block, REG_EDX);
host_x86_PUSH(block, REG_ECX);
if (size == 1)
host_x86_CALL(block, (void *) readmembl);
else if (size == 2)
host_x86_CALL(block, (void *) readmemwl);
else if (size == 4)
host_x86_CALL(block, (void *) readmemll);
else if (size == 8)
host_x86_CALL(block, (void *) readmemql);
host_x86_POP(block, REG_ECX);
if (size == 1 && !is_float)
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
else if (size == 2 && !is_float)
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
else if (size == 4 && is_float) {
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
} else if (size == 8) {
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX);
host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2);
}
host_x86_POP(block, REG_EDX);
host_x86_POP(block, REG_EAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
block_pos = (block_pos + 63) & ~63;
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
static void
build_store_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset = NULL;
uint8_t *branch_offset;
uint8_t *misaligned_offset = NULL;
/*In - ECX = data, ESI = address
Out - ESI = abrt
Corrupts EDI*/
/*MOV EDI, ESI
SHR ESI, 12
MOV ESI, [writelookup2+ESI*4]
CMP ESI, -1
JNZ +
MOV [ESI+EDI], ECX
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL writemembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 4 && is_float)
host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
else if (size == 8)
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
else
fatal("build_store_routine: size=%i is_float=%i\n", size, is_float);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
/*In - ECX = data, ESI = address
Out - ESI = abrt
Corrupts EDI*/
/*MOV EDI, ESI
SHR ESI, 12
MOV ESI, [writelookup2+ESI*4]
CMP ESI, -1
JNZ +
MOV [ESI+EDI], ECX
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL writemembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2);
if (size != 1) {
host_x86_TEST32_REG_IMM(block, REG_EDI, size - 1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t) -1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 4 && is_float)
host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
else if (size == 8)
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
else
fatal("build_store_routine: size=%i is_float=%i\n", size, is_float);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP);
host_x86_PUSH(block, REG_EAX);
host_x86_PUSH(block, REG_EDX);
host_x86_PUSH(block, REG_ECX);
if (size == 8)
{
host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP);
host_x86_SUB32_REG_IMM(block, REG_ESP, 8);
}
host_x86_PUSH(block, REG_EDI);
if (size == 1)
host_x86_CALL(block, (void *)writemembl);
else if (size == 2)
host_x86_CALL(block, (void *)writememwl);
else if (size == 4)
host_x86_CALL(block, (void *)writememll);
else if (size == 8)
host_x86_CALL(block, (void *)writememql);
host_x86_POP(block, REG_EDI);
if (size == 8)
host_x86_ADD32_REG_IMM(block, REG_ESP, 8);
host_x86_POP(block, REG_ECX);
host_x86_POP(block, REG_EDX);
host_x86_POP(block, REG_EAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
block_pos = (block_pos + 63) & ~63;
*branch_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t) ((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 1;
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP);
host_x86_PUSH(block, REG_EAX);
host_x86_PUSH(block, REG_EDX);
host_x86_PUSH(block, REG_ECX);
if (size == 8) {
host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP);
host_x86_SUB32_REG_IMM(block, REG_ESP, 8);
}
host_x86_PUSH(block, REG_EDI);
if (size == 1)
host_x86_CALL(block, (void *) writemembl);
else if (size == 2)
host_x86_CALL(block, (void *) writememwl);
else if (size == 4)
host_x86_CALL(block, (void *) writememll);
else if (size == 8)
host_x86_CALL(block, (void *) writememql);
host_x86_POP(block, REG_EDI);
if (size == 8)
host_x86_ADD32_REG_IMM(block, REG_ESP, 8);
host_x86_POP(block, REG_ECX);
host_x86_POP(block, REG_EDX);
host_x86_POP(block, REG_EAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
block_pos = (block_pos + 63) & ~63;
}
static void build_loadstore_routines(codeblock_t *block)
static void
build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 1);
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 1);
}
void codegen_backend_init(void)
void
codegen_backend_init(void)
{
codeblock_t *block;
int c;
codeblock_t *block;
int c;
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0);
host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0);
host_x86_CALL(block, (void *)x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
host_x86_POP(block, REG_EDI);
host_x86_POP(block, REG_ESI);
host_x86_POP(block, REG_EBP);
host_x86_POP(block, REG_EDX);
host_x86_RET(block);
block_write_data = NULL;
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0);
host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0);
host_x86_CALL(block, (void *) x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
host_x86_POP(block, REG_EDI);
host_x86_POP(block, REG_ESI);
host_x86_POP(block, REG_EBP);
host_x86_POP(block, REG_EDX);
host_x86_RET(block);
block_write_data = NULL;
cpu_state.old_fp_control = 0;
asm(
"fstcw %0\n"
"stmxcsr %1\n"
: "=m" (cpu_state.old_fp_control2),
"=m" (cpu_state.old_fp_control)
);
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
cpu_state.old_fp_control = 0;
asm(
"fstcw %0\n"
"stmxcsr %1\n"
: "=m"(cpu_state.old_fp_control2),
"=m"(cpu_state.old_fp_control));
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
}
void codegen_set_rounding_mode(int mode)
void
codegen_set_rounding_mode(int mode)
{
/*SSE*/
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
/*x87 - used for double -> i64 conversions*/
cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
/*SSE*/
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
/*x87 - used for double -> i64 conversions*/
cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
}
void codegen_backend_prologue(codeblock_t *block)
void
codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START; /*Entry code*/
host_x86_PUSH(block, REG_EBX);
host_x86_PUSH(block, REG_EBP);
host_x86_PUSH(block, REG_ESI);
host_x86_PUSH(block, REG_EDI);
host_x86_SUB32_REG_IMM(block, REG_ESP, 64);
host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX);
}
block_pos = BLOCK_START; /*Entry code*/
host_x86_PUSH(block, REG_EBX);
host_x86_PUSH(block, REG_EBP);
host_x86_PUSH(block, REG_ESI);
host_x86_PUSH(block, REG_EDI);
host_x86_SUB32_REG_IMM(block, REG_ESP, 64);
host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t) &cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU) {
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX);
}
}
void codegen_backend_epilogue(codeblock_t *block)
void
codegen_backend_epilogue(codeblock_t *block)
{
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
host_x86_POP(block, REG_EDI);
host_x86_POP(block, REG_ESI);
host_x86_POP(block, REG_EBP);
host_x86_POP(block, REG_EDX);
host_x86_RET(block);
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
host_x86_POP(block, REG_EDI);
host_x86_POP(block, REG_ESI);
host_x86_POP(block, REG_EBP);
host_x86_POP(block, REG_EDX);
host_x86_RET(block);
}
#endif

View File

@@ -1,14 +1,14 @@
#include "codegen_backend_x86_defs.h"
#define BLOCK_SIZE 0x10000
#define BLOCK_MASK 0xffff
#define BLOCK_SIZE 0x10000
#define BLOCK_MASK 0xffff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define HASH(l) ((l) &0x1ffff)
#define BLOCK_MAX 0x3c0
#define BLOCK_MAX 0x3c0
#define CODEGEN_BACKEND_HAS_MOV_IMM

View File

@@ -1,28 +1,28 @@
#ifndef _CODEGEN_BACKEND_X86_DEFS_H_
#define _CODEGEN_BACKEND_X86_DEFS_H_
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM_TEMP REG_XMM7
#define REG_XMM_TEMP2 REG_XMM6
#define REG_XMM_TEMP REG_XMM7
#define REG_XMM_TEMP2 REG_XMM6
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 6
extern void *codegen_mem_load_byte;

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_INC32_ABS(codeblock_t *block, void *p);
void host_x86_JMP(codeblock_t *block, void *p);
void host_x86_JMP(codeblock_t *block, void *p);
uint32_t *host_x86_JMP_short(codeblock_t *block);
uint32_t *host_x86_JMP_long(codeblock_t *block);

View File

@@ -1,84 +1,74 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
# include <stdint.h>
# include <86box/86box.h>
# include "cpu.h"
# include <86box/mem.h>
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops_fpu.h"
#include "codegen_backend_x86_ops_helpers.h"
# include "codegen.h"
# include "codegen_allocator.h"
# include "codegen_backend.h"
# include "codegen_backend_x86_defs.h"
# include "codegen_backend_x86_ops_fpu.h"
# include "codegen_backend_x86_ops_helpers.h"
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg)
void
host_x87_FILDq_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/
}
if (base_reg == REG_ESP) {
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/
} else {
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/
}
}
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg)
void
host_x87_FISTPq_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/
}
if (base_reg == REG_ESP) {
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/
} else {
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/
}
}
void host_x87_FLDCW(codeblock_t *block, void *p)
void
host_x87_FLDCW(codeblock_t *block, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
int offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/
}
else
{
codegen_alloc_bytes(block, 6);
codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/
codegen_addlong(block, (uint32_t)p);
}
if (offset >= -128 && offset < 127) {
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/
} else {
codegen_alloc_bytes(block, 6);
codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/
codegen_addlong(block, (uint32_t) p);
}
}
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg)
void
host_x87_FLDd_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/
}
if (base_reg == REG_ESP) {
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/
} else {
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/
}
}
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg)
void
host_x87_FSTPd_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/
}
if (base_reg == REG_ESP) {
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/
} else {
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/
}
}
#endif

View File

@@ -1,84 +1,94 @@
#define JMP_LEN_BYTES 5
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
static inline void
codegen_addbyte(codeblock_t *block, uint8_t val)
{
if (block_pos >= BLOCK_MAX)
fatal("codegen_addbyte over! %i\n", block_pos);
block_write_data[block_pos++] = val;
if (block_pos >= BLOCK_MAX)
fatal("codegen_addbyte over! %i\n", block_pos);
block_write_data[block_pos++] = val;
}
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
static inline void
codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
{
if (block_pos > (BLOCK_MAX-2))
fatal("codegen_addbyte2 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
if (block_pos > (BLOCK_MAX - 2))
fatal("codegen_addbyte2 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
}
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
static inline void
codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
{
if (block_pos > (BLOCK_MAX-3))
fatal("codegen_addbyte3 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
if (block_pos > (BLOCK_MAX - 3))
fatal("codegen_addbyte3 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
}
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
static inline void
codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
{
if (block_pos > (BLOCK_MAX-4))
fatal("codegen_addbyte4 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
block_write_data[block_pos++] = vald;
if (block_pos > (BLOCK_MAX - 4))
fatal("codegen_addbyte4 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
block_write_data[block_pos++] = vald;
}
static inline void codegen_addword(codeblock_t *block, uint16_t val)
static inline void
codegen_addword(codeblock_t *block, uint16_t val)
{
if (block_pos > (BLOCK_MAX-2))
fatal("codegen_addword over! %i\n", block_pos);
*(uint16_t *)&block_write_data[block_pos] = val;
block_pos += 2;
if (block_pos > (BLOCK_MAX - 2))
fatal("codegen_addword over! %i\n", block_pos);
*(uint16_t *) &block_write_data[block_pos] = val;
block_pos += 2;
}
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
static inline void
codegen_addlong(codeblock_t *block, uint32_t val)
{
if (block_pos > (BLOCK_MAX-4))
fatal("codegen_addlong over! %i\n", block_pos);
*(uint32_t *)&block_write_data[block_pos] = val;
block_pos += 4;
if (block_pos > (BLOCK_MAX - 4))
fatal("codegen_addlong over! %i\n", block_pos);
*(uint32_t *) &block_write_data[block_pos] = val;
block_pos += 4;
}
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
static inline void
codegen_addquad(codeblock_t *block, uint64_t val)
{
if (block_pos > (BLOCK_MAX-8))
fatal("codegen_addquad over! %i\n", block_pos);
*(uint64_t *)&block_write_data[block_pos] = val;
block_pos += 8;
if (block_pos > (BLOCK_MAX - 8))
fatal("codegen_addquad over! %i\n", block_pos);
*(uint64_t *) &block_write_data[block_pos] = val;
block_pos += 8;
}
static void codegen_allocate_new_block(codeblock_t *block)
static void
codegen_allocate_new_block(codeblock_t *block)
{
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Add a jump instruction to the new block*/
codegen_addbyte(block, 0xe9); /*JMP*/
codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]);
/*Add a jump instruction to the new block*/
codegen_addbyte(block, 0xe9); /*JMP*/
codegen_addlong(block, (uintptr_t) new_ptr - (uintptr_t) &block_write_data[block_pos + 4]);
/*Set write address to start of new block*/
block_pos = 0;
block_write_data = new_ptr;
/*Set write address to start of new block*/
block_pos = 0;
block_write_data = new_ptr;
}
static inline void codegen_alloc_bytes(codeblock_t *block, int size)
static inline void
codegen_alloc_bytes(codeblock_t *block, int size)
{
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
codegen_allocate_new_block(block);
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
codegen_allocate_new_block(block);
}
static inline int is_imm8(uint32_t imm_data)
static inline int
is_imm8(uint32_t imm_data)
{
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
}

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

@@ -9,208 +9,186 @@
#include "codegen_ir.h"
#include "codegen_reg.h"
extern int has_ea;
extern int has_ea;
static ir_data_t ir_block;
static int codegen_unroll_start, codegen_unroll_count;
static int codegen_unroll_first_instruction;
ir_data_t *codegen_ir_init(void)
ir_data_t *
codegen_ir_init(void)
{
ir_block.wr_pos = 0;
ir_block.wr_pos = 0;
codegen_unroll_count = 0;
codegen_unroll_count = 0;
return &ir_block;
return &ir_block;
}
void codegen_ir_set_unroll(int count, int start, int first_instruction)
void
codegen_ir_set_unroll(int count, int start, int first_instruction)
{
codegen_unroll_count = count;
codegen_unroll_start = start;
codegen_unroll_first_instruction = first_instruction;
codegen_unroll_count = count;
codegen_unroll_start = start;
codegen_unroll_first_instruction = first_instruction;
}
static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset)
static void
duplicate_uop(ir_data_t *ir, uop_t *uop, int offset)
{
uop_t *new_uop = uop_alloc(ir, uop->type);
uop_t *new_uop = uop_alloc(ir, uop->type);
if (!ir_reg_is_invalid(uop->src_reg_a))
new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg);
if (!ir_reg_is_invalid(uop->src_reg_b))
new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg);
if (!ir_reg_is_invalid(uop->src_reg_c))
new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg);
if (!ir_reg_is_invalid(uop->dest_reg_a))
new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos-1);
if (!ir_reg_is_invalid(uop->src_reg_a))
new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg);
if (!ir_reg_is_invalid(uop->src_reg_b))
new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg);
if (!ir_reg_is_invalid(uop->src_reg_c))
new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg);
if (!ir_reg_is_invalid(uop->dest_reg_a))
new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos - 1);
new_uop->type = uop->type;
new_uop->imm_data = uop->imm_data;
new_uop->p = uop->p;
new_uop->pc = uop->pc;
new_uop->type = uop->type;
new_uop->imm_data = uop->imm_data;
new_uop->p = uop->p;
new_uop->pc = uop->pc;
if (uop->jump_dest_uop != -1)
{
new_uop->jump_dest_uop = uop->jump_dest_uop + offset;
if (uop->jump_dest_uop != -1) {
new_uop->jump_dest_uop = uop->jump_dest_uop + offset;
}
}
void
codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
{
int jump_target_at_end = -1;
int c;
if (codegen_unroll_count) {
int unroll_count;
int unroll_end;
codegen_set_loop_start(ir, codegen_unroll_first_instruction);
unroll_end = ir->wr_pos;
for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) {
int offset = ir->wr_pos - codegen_unroll_start;
// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count);
for (c = codegen_unroll_start; c < unroll_end; c++) {
// pclog(" Duplicate uop %i\n", c);
duplicate_uop(ir, &ir->uops[c], offset);
}
}
}
}
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
{
int jump_target_at_end = -1;
int c;
codegen_reg_mark_as_required();
codegen_reg_process_dead_list(ir);
block_write_data = codeblock_allocator_get_ptr(block->head_mem_block);
block_pos = 0;
codegen_backend_prologue(block);
if (codegen_unroll_count)
{
int unroll_count;
int unroll_end;
for (c = 0; c < ir->wr_pos; c++) {
uop_t *uop = &ir->uops[c];
codegen_set_loop_start(ir, codegen_unroll_first_instruction);
unroll_end = ir->wr_pos;
// pclog("uOP %i : %08x\n", c, uop->type);
for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++)
{
int offset = ir->wr_pos - codegen_unroll_start;
// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count);
for (c = codegen_unroll_start; c < unroll_end; c++)
{
// pclog(" Duplicate uop %i\n", c);
duplicate_uop(ir, &ir->uops[c], offset);
}
}
if (uop->type & UOP_TYPE_BARRIER)
codegen_reg_flush_invalidate(ir, block);
if (uop->type & UOP_TYPE_JUMP_DEST) {
uop_t *uop_dest = uop;
while (uop_dest->jump_list_next != -1) {
uop_dest = &ir->uops[uop_dest->jump_list_next];
codegen_set_jump_dest(block, uop_dest->p);
}
}
codegen_reg_mark_as_required();
codegen_reg_process_dead_list(ir);
block_write_data = codeblock_allocator_get_ptr(block->head_mem_block);
block_pos = 0;
codegen_backend_prologue(block);
for (c = 0; c < ir->wr_pos; c++)
{
uop_t *uop = &ir->uops[c];
// pclog("uOP %i : %08x\n", c, uop->type);
if (uop->type & UOP_TYPE_BARRIER)
codegen_reg_flush_invalidate(ir, block);
if (uop->type & UOP_TYPE_JUMP_DEST)
{
uop_t *uop_dest = uop;
while (uop_dest->jump_list_next != -1)
{
uop_dest = &ir->uops[uop_dest->jump_list_next];
codegen_set_jump_dest(block, uop_dest->p);
}
}
if ((uop->type & UOP_MASK) == UOP_INVALID)
continue;
if ((uop->type & UOP_MASK) == UOP_INVALID)
continue;
#ifdef CODEGEN_BACKEND_HAS_MOV_IMM
if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0)
{
/*Special case for UOP_MOV_IMM - if destination not already in host register
and won't be used again then just store directly to memory*/
codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data);
}
else
if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0) {
/*Special case for UOP_MOV_IMM - if destination not already in host register
and won't be used again then just store directly to memory*/
codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data);
} else
#endif
if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 &&
reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a))
{
/*Special case for UOP_MOV - if source register won't be used again then
just rename it to dest register instead of moving*/
codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg);
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a);
if (uop->type & UOP_TYPE_ORDER_BARRIER)
codegen_reg_flush(ir, block);
if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 && reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a)) {
/*Special case for UOP_MOV - if source register won't be used again then
just rename it to dest register instead of moving*/
codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg);
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a);
if (uop->type & UOP_TYPE_ORDER_BARRIER)
codegen_reg_flush(ir, block);
} else {
if (uop->type & UOP_TYPE_PARAMS_REGS) {
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
if (uop->src_reg_a.reg != IREG_INVALID) {
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
}
else
{
if (uop->type & UOP_TYPE_PARAMS_REGS)
{
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
if (uop->src_reg_a.reg != IREG_INVALID)
{
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
}
if (uop->src_reg_b.reg != IREG_INVALID)
{
uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
}
if (uop->src_reg_c.reg != IREG_INVALID)
{
uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
}
}
if (uop->src_reg_b.reg != IREG_INVALID) {
uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
}
if (uop->src_reg_c.reg != IREG_INVALID) {
uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
}
}
if (uop->type & UOP_TYPE_ORDER_BARRIER)
codegen_reg_flush(ir, block);
if (uop->type & UOP_TYPE_ORDER_BARRIER)
codegen_reg_flush(ir, block);
if (uop->type & UOP_TYPE_PARAMS_REGS)
{
if (uop->dest_reg_a.reg != IREG_INVALID)
{
uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
}
}
if (uop->type & UOP_TYPE_PARAMS_REGS) {
if (uop->dest_reg_a.reg != IREG_INVALID) {
uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
}
}
#ifndef RELEASE_BUILD
if (!uop_handlers[uop->type & UOP_MASK])
fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
if (!uop_handlers[uop->type & UOP_MASK])
fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
#endif
uop_handlers[uop->type & UOP_MASK](block, uop);
}
if (uop->type & UOP_TYPE_JUMP)
{
if (uop->jump_dest_uop == ir->wr_pos)
{
if (jump_target_at_end == -1)
jump_target_at_end = c;
else
{
uop_t *uop_dest = &ir->uops[jump_target_at_end];
while (uop_dest->jump_list_next != -1)
uop_dest = &ir->uops[uop_dest->jump_list_next];
uop_dest->jump_list_next = c;
}
}
else
{
uop_t *uop_dest = &ir->uops[uop->jump_dest_uop];
while (uop_dest->jump_list_next != -1)
uop_dest = &ir->uops[uop_dest->jump_list_next];
uop_dest->jump_list_next = c;
ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST;
}
}
uop_handlers[uop->type & UOP_MASK](block, uop);
}
codegen_reg_flush_invalidate(ir, block);
if (uop->type & UOP_TYPE_JUMP) {
if (uop->jump_dest_uop == ir->wr_pos) {
if (jump_target_at_end == -1)
jump_target_at_end = c;
else {
uop_t *uop_dest = &ir->uops[jump_target_at_end];
if (jump_target_at_end != -1)
{
uop_t *uop_dest = &ir->uops[jump_target_at_end];
while (1)
{
codegen_set_jump_dest(block, uop_dest->p);
if (uop_dest->jump_list_next == -1)
break;
while (uop_dest->jump_list_next != -1)
uop_dest = &ir->uops[uop_dest->jump_list_next];
}
}
codegen_backend_epilogue(block);
block_write_data = NULL;
// if (has_ea)
// fatal("IR compilation complete\n");
uop_dest->jump_list_next = c;
}
} else {
uop_t *uop_dest = &ir->uops[uop->jump_dest_uop];
while (uop_dest->jump_list_next != -1)
uop_dest = &ir->uops[uop_dest->jump_list_next];
uop_dest->jump_list_next = c;
ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST;
}
}
}
codegen_reg_flush_invalidate(ir, block);
if (jump_target_at_end != -1) {
uop_t *uop_dest = &ir->uops[jump_target_at_end];
while (1) {
codegen_set_jump_dest(block, uop_dest->p);
if (uop_dest->jump_list_next == -1)
break;
uop_dest = &ir->uops[uop_dest->jump_list_next];
}
}
codegen_backend_epilogue(block);
block_write_data = NULL;
// if (has_ea)
// fatal("IR compilation complete\n");
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,8 +26,8 @@
#include "codegen_ops_shift.h"
#include "codegen_ops_stack.h"
RecompOpFn recomp_opcodes[512] =
{
RecompOpFn recomp_opcodes[512] = {
// clang-format off
/*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,
@@ -71,11 +71,11 @@ RecompOpFn recomp_opcodes[512] =
/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, ropJMP_far_32, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_32, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_32
// clang-format on
};
RecompOpFn recomp_opcodes_0f[512] =
{
RecompOpFn recomp_opcodes_0f[512] = {
// clang-format off
/*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,
@@ -141,10 +141,11 @@ RecompOpFn recomp_opcodes_0f[512] =
/*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
#endif
// clang-format on
};
RecompOpFn recomp_opcodes_3DNOW[256] =
{
RecompOpFn recomp_opcodes_3DNOW[256] = {
// clang-format off
#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64
0
#else
@@ -169,10 +170,11 @@ RecompOpFn recomp_opcodes_3DNOW[256] =
/*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,
#endif
// clang-format on
};
RecompOpFn recomp_opcodes_d8[512] =
{
RecompOpFn recomp_opcodes_d8[512] = {
// clang-format off
/*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,
@@ -216,10 +218,11 @@ RecompOpFn recomp_opcodes_d8[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_d9[512] =
{
RecompOpFn recomp_opcodes_d9[512] = {
// clang-format off
/*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,
@@ -263,10 +266,11 @@ RecompOpFn recomp_opcodes_d9[512] =
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL,
// clang-format on
};
RecompOpFn recomp_opcodes_da[512] =
{
RecompOpFn recomp_opcodes_da[512] = {
// clang-format off
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
@@ -310,10 +314,11 @@ RecompOpFn recomp_opcodes_da[512] =
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, 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,
// clang-format on
};
RecompOpFn recomp_opcodes_db[512] =
{
RecompOpFn recomp_opcodes_db[512] = {
// clang-format off
/*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,
@@ -357,10 +362,11 @@ RecompOpFn recomp_opcodes_db[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_dc[512] =
{
RecompOpFn recomp_opcodes_dc[512] = {
// clang-format off
/*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,
@@ -404,10 +410,11 @@ RecompOpFn recomp_opcodes_dc[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_dd[512] =
{
RecompOpFn recomp_opcodes_dd[512] = {
// clang-format off
/*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,
@@ -451,10 +458,11 @@ RecompOpFn recomp_opcodes_dd[512] =
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
// clang-format on
};
RecompOpFn recomp_opcodes_de[512] =
{
RecompOpFn recomp_opcodes_de[512] = {
// clang-format off
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
@@ -498,10 +506,11 @@ RecompOpFn recomp_opcodes_de[512] =
/*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,
// clang-format on
};
RecompOpFn recomp_opcodes_df[512] =
{
RecompOpFn recomp_opcodes_df[512] = {
// clang-format off
/*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,
@@ -545,4 +554,5 @@ RecompOpFn recomp_opcodes_df[512] =
/*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,
// clang-format on
};

View File

@@ -29,21 +29,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512];*/
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AL 0
#define REG_AH 4
#define REG_CL 1
#define REG_CH 5
#define REG_DL 2
#define REG_DH 6
#define REG_BL 3
#define REG_BH 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AL 0
#define REG_AH 4
#define REG_CL 1
#define REG_CH 5
#define REG_DL 2
#define REG_DH 6
#define REG_BL 3
#define REG_BH 7
#endif

View File

@@ -13,199 +13,184 @@
#include "codegen_ops_3dnow.h"
#include "codegen_ops_helpers.h"
#define ropParith(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
codegen_mark_code_present(block, cs+op_pc+1, 1); \
return op_pc + 2; \
}
#define ropParith(func) \
uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs + op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) { \
int src_reg = fetchdat & 7; \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} else { \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
codegen_mark_code_present(block, cs + op_pc + 1, 1); \
return op_pc + 2; \
}
ropParith(PFADD)
ropParith(PFCMPEQ)
ropParith(PFCMPGE)
ropParith(PFCMPGT)
ropParith(PFMAX)
ropParith(PFMIN)
ropParith(PFMUL)
ropParith(PFSUB)
ropParith(PFCMPEQ)
ropParith(PFCMPGE)
ropParith(PFCMPGT)
ropParith(PFMAX)
ropParith(PFMIN)
ropParith(PFMUL)
ropParith(PFSUB)
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg));
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg));
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MMX_ENTER(ir);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc, 2);
return op_pc + 2;
}

File diff suppressed because it is too large Load Diff

View File

@@ -54,7 +54,6 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
uint32_t rop83_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t rop83_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropDEC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropDEC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -14,23 +14,25 @@
#include "codegen_ops_fpu_constant.h"
#include "codegen_ops_helpers.h"
uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_temp0, 1);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_temp0, 1);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc;
return op_pc;
}
uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_temp0, 0);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_temp0, 0);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc;
return op_pc;
}

View File

@@ -14,221 +14,234 @@
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_helpers.h"
uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1));
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64);
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1));
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64);
fpu_PUSH(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
return op_pc + 1;
}

View File

@@ -14,101 +14,109 @@
#include "codegen_ops_fpu_misc.h"
#include "codegen_ops_helpers.h"
uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY);
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY);
return op_pc;
return op_pc;
}
uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg));
uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg));
uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg));
fpu_PUSH(block, ir);
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg));
uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg));
uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg));
fpu_PUSH(block, ir);
return op_pc;
return op_pc;
}
uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
return op_pc;
return op_pc;
}
uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
fpu_POP(block, ir);
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
fpu_POP(block, ir);
return op_pc;
return op_pc;
}
uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS);
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS);
return op_pc+1;
return op_pc + 1;
}
uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_AX, IREG_NPXS);
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_AX, IREG_NPXS);
return op_pc;
return op_pc;
}
uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_temp0_D, IREG_ST(0));
uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0));
uop_MOV(ir, IREG_temp2, IREG_tag(0));
uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg));
uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg));
uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg));
uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D);
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q);
uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2);
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_temp0_D, IREG_ST(0));
uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0));
uop_MOV(ir, IREG_temp2, IREG_tag(0));
uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg));
uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg));
uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg));
uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D);
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q);
uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2);
return op_pc;
return op_pc;
}

View File

@@ -11,65 +11,64 @@
#include "codegen_reg.h"
#include "codegen_ops_helpers.h"
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
void
LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
/*Word access that crosses two pages. Perform reads from both pages, shift and combine*/
uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr));
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1));
uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8);
uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W);
/*Word access that crosses two pages. Perform reads from both pages, shift and combine*/
uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr));
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr + 1));
uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8);
uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W);
}
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
void
LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
/*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3));
uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3));
uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8);
uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8);
uop_OR(ir, dest_reg, dest_reg, IREG_temp3);
/*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3));
uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3));
uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8);
uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8);
uop_OR(ir, dest_reg, dest_reg, IREG_temp3);
}
#define UNROLL_MAX_REG_REFERENCES 200
#define UNROLL_MAX_UOPS 1000
#define UNROLL_MAX_COUNT 10
int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
#define UNROLL_MAX_UOPS 1000
#define UNROLL_MAX_COUNT 10
int
codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
{
int start;
int max_unroll;
int first_instruction;
int TOP = -1;
int start;
int max_unroll;
int first_instruction;
int TOP = -1;
/*Check that dest instruction was actually compiled into block*/
start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP);
/*Check that dest instruction was actually compiled into block*/
start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP);
/*Couldn't find any uOPs corresponding to the destination instruction*/
if (start == -1)
{
/*Is instruction jumping to itself?*/
if (dest_addr != cpu_state.oldpc)
{
return 0;
}
else
{
start = ir->wr_pos;
TOP = cpu_state.TOP;
}
/*Couldn't find any uOPs corresponding to the destination instruction*/
if (start == -1) {
/*Is instruction jumping to itself?*/
if (dest_addr != cpu_state.oldpc) {
return 0;
} else {
start = ir->wr_pos;
TOP = cpu_state.TOP;
}
}
if (TOP != cpu_state.TOP)
return 0;
if (TOP != cpu_state.TOP)
return 0;
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6);
if ((max_version_refcount != 0) && (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount)))
max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount);
if (max_unroll > UNROLL_MAX_COUNT)
max_unroll = UNROLL_MAX_COUNT;
if (max_unroll <= 1)
return 0;
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos - start) + 6);
if ((max_version_refcount != 0) && (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount)))
max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount);
if (max_unroll > UNROLL_MAX_COUNT)
max_unroll = UNROLL_MAX_COUNT;
if (max_unroll <= 1)
return 0;
codegen_ir_set_unroll(max_unroll, start, first_instruction);
codegen_ir_set_unroll(max_unroll, start, first_instruction);
return 1;
return 1;
}

View File

@@ -1,126 +1,127 @@
#include "386_common.h"
#include "codegen_backend.h"
static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset)
static inline int
LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset)
{
if (stack32)
{
if (offset)
{
uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset);
return IREG_eaaddr;
}
else
return IREG_ESP;
}
else
{
if (offset)
{
uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset);
uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W);
return IREG_eaaddr;
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
return IREG_eaaddr;
}
if (stack32) {
if (offset) {
uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset);
return IREG_eaaddr;
} else
return IREG_ESP;
} else {
if (offset) {
uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset);
uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W);
return IREG_eaaddr;
} else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
return IREG_eaaddr;
}
}
}
static inline int LOAD_SP(ir_data_t *ir)
static inline int
LOAD_SP(ir_data_t *ir)
{
return LOAD_SP_WITH_OFFSET(ir, 0);
return LOAD_SP_WITH_OFFSET(ir, 0);
}
static inline void ADD_SP(ir_data_t *ir, int offset)
static inline void
ADD_SP(ir_data_t *ir, int offset)
{
if (stack32)
uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset);
else
uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset);
if (stack32)
uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset);
else
uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset);
}
static inline void SUB_SP(ir_data_t *ir, int offset)
static inline void
SUB_SP(ir_data_t *ir, int offset)
{
if (stack32)
uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset);
else
uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset);
if (stack32)
uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset);
else
uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset);
}
static inline void fpu_POP(codeblock_t *block, ir_data_t *ir)
static inline void
fpu_POP(codeblock_t *block, ir_data_t *ir)
{
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1);
else
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1);
else
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
}
static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir)
static inline void
fpu_POP2(codeblock_t *block, ir_data_t *ir)
{
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2);
else
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2);
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2);
else
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2);
}
static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir)
static inline void
fpu_PUSH(codeblock_t *block, ir_data_t *ir)
{
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1);
else
uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1);
else
uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
}
static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset)
static inline void
CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset)
{
if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) ||
(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS)))
return;
if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS)))
return;
uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout);
if (end_offset)
{
uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset);
uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout);
}
else
uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout);
uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout);
if (end_offset) {
uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset);
uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout);
} else
uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout);
}
static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
static inline void
LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr));
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr));
}
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
static inline void
LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
if ((addr & 0xfff) == 0xfff)
LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr);
else
uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr));
if ((addr & 0xfff) == 0xfff)
LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr);
else
uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr));
}
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
static inline void
LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
if ((addr & 0xfff) >= 0xffd)
LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr);
else
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr));
if ((addr & 0xfff) >= 0xffd)
LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr);
else
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr));
}
int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr);
static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
static inline int
codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
{
if (block->flags & CODEBLOCK_BYTE_MASK)
return 0;
if (block->flags & CODEBLOCK_BYTE_MASK)
return 0;
/*Is dest within block?*/
if (dest_addr > next_pc)
return 0;
if ((cs+dest_addr) < block->pc)
return 0;
/*Is dest within block?*/
if (dest_addr > next_pc)
return 0;
if ((cs + dest_addr) < block->pc)
return 0;
return codegen_can_unroll_full(block, ir, next_pc, dest_addr);
return codegen_can_unroll_full(block, ir, next_pc, dest_addr);
}

View File

@@ -11,282 +11,281 @@
#include "codegen_ops_helpers.h"
#include "codegen_ops_mov.h"
uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
uint32_t dest_addr = op_pc+1+offset;
if (!(op_32 & 0x100))
dest_addr &= 0xffff;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 1);
return dest_addr;
}
uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
uint32_t dest_addr = op_pc+2+offset;
uint32_t offset = (int32_t) (int8_t) fastreadb(cs + op_pc);
uint32_t dest_addr = op_pc + 1 + offset;
if (!(op_32 & 0x100))
dest_addr &= 0xffff;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 2);
return dest_addr;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc + 1, dest_addr);
codegen_mark_code_present(block, cs + op_pc, 1);
return dest_addr;
}
uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = fastreadl(cs + op_pc);
uint32_t dest_addr = op_pc+4+offset;
uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc);
uint32_t dest_addr = op_pc + 2 + offset;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 4);
return dest_addr;
dest_addr &= 0xffff;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc + 1, dest_addr);
codegen_mark_code_present(block, cs + op_pc, 2);
return dest_addr;
}
uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t new_pc = fastreadw(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 2);
uint32_t offset = fastreadl(cs + op_pc);
uint32_t dest_addr = op_pc + 4 + offset;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_pc, new_pc);
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
uop_CALL_FUNC(ir, loadcsjmp);
codegen_mark_code_present(block, cs+op_pc, 4);
return -1;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc + 1, dest_addr);
codegen_mark_code_present(block, cs + op_pc, 4);
return dest_addr;
}
uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t new_pc = fastreadl(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 4);
uint16_t new_pc = fastreadw(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 2);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_pc, new_pc);
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
uop_CALL_FUNC(ir, loadcsjmp);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_pc, new_pc);
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
uop_CALL_FUNC(ir, loadcsjmp);
codegen_mark_code_present(block, cs+op_pc, 6);
return -1;
codegen_mark_code_present(block, cs + op_pc, 4);
return -1;
}
uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
uint16_t ret_addr = op_pc + 2;
uint16_t dest_addr = ret_addr + offset;
int sp_reg;
uint32_t new_pc = fastreadl(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 4);
dest_addr &= 0xffff;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_pc, new_pc);
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
uop_CALL_FUNC(ir, loadcsjmp);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr);
SUB_SP(ir, 2);
uop_MOV_IMM(ir, IREG_pc, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
codegen_mark_code_present(block, cs + op_pc, 6);
return -1;
}
uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = fastreadl(cs + op_pc);
uint32_t ret_addr = op_pc + 4;
uint32_t dest_addr = ret_addr + offset;
int sp_reg;
uint32_t offset = (int32_t) (int16_t) fastreadw(cs + op_pc);
uint16_t ret_addr = op_pc + 2;
uint16_t dest_addr = ret_addr + offset;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr);
SUB_SP(ir, 4);
uop_MOV_IMM(ir, IREG_pc, dest_addr);
dest_addr &= 0xffff;
codegen_mark_code_present(block, cs+op_pc, 4);
return -1;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr);
SUB_SP(ir, 2);
uop_MOV_IMM(ir, IREG_pc, dest_addr);
codegen_mark_code_present(block, cs + op_pc, 2);
return -1;
}
uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uint32_t offset = fastreadl(cs + op_pc);
uint32_t ret_addr = op_pc + 4;
uint32_t dest_addr = ret_addr + offset;
int sp_reg;
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 2);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr);
SUB_SP(ir, 4);
uop_MOV_IMM(ir, IREG_pc, dest_addr);
return -1;
codegen_mark_code_present(block, cs + op_pc, 4);
return -1;
}
uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 4);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 2);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
return -1;
return -1;
}
uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 4);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 2+offset);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
return -1;
}
uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset = fastreadw(cs + op_pc);
uint16_t offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 4+offset);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 2 + offset);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
codegen_mark_code_present(block, cs + op_pc, 2);
return -1;
}
uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
uint16_t offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
}
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 4);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 4 + offset);
return -1;
codegen_mark_code_present(block, cs + op_pc, 2);
return -1;
}
uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG))
return 0;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
}
uop_MOV(ir, IREG_pc, IREG_temp0);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 8);
if (stack32) {
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
} else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
}
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 4);
return -1;
return -1;
}
uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset;
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG))
return 0;
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32) {
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
} else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
}
uop_MOV(ir, IREG_pc, IREG_temp0);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 8);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
}
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 4+offset);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
return -1;
}
uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset;
uint16_t offset;
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG))
return 0;
offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
}
uop_MOV(ir, IREG_pc, IREG_temp0);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 8+offset);
if (stack32) {
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
} else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
}
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 4 + offset);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
codegen_mark_code_present(block, cs + op_pc, 2);
return -1;
}
uint32_t
ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset;
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG))
return 0;
offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32) {
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
} else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
}
uop_MOV(ir, IREG_pc, IREG_temp0);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 8 + offset);
codegen_mark_code_present(block, cs + op_pc, 2);
return -1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,32 +13,30 @@
#include "codegen_ops_mmx_arith.h"
#include "codegen_ops_helpers.h"
#define ropParith(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
#define ropParith(func) \
uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs + op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) { \
int src_reg = fetchdat & 7; \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} else { \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
// clang-format off
ropParith(PADDB)
ropParith(PADDW)
ropParith(PADDD)
@@ -58,3 +56,4 @@ ropParith(PSUBUSW)
ropParith(PMADDWD)
ropParith(PMULHW)
ropParith(PMULLW)
// clang-format on

View File

@@ -13,35 +13,34 @@
#include "codegen_ops_mmx_cmp.h"
#include "codegen_ops_helpers.h"
#define ropPcmp(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
#define ropPcmp(func) \
uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs + op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) { \
int src_reg = fetchdat & 7; \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} else { \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
// clang-format off
ropPcmp(PCMPEQB)
ropPcmp(PCMPEQW)
ropPcmp(PCMPEQD)
ropPcmp(PCMPGTB)
ropPcmp(PCMPGTW)
ropPcmp(PCMPGTD)
// clang-format on

View File

@@ -13,104 +13,96 @@
#include "codegen_ops_mmx_loadstore.h"
#include "codegen_ops_helpers.h"
uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0);
}
return op_pc + 1;
return op_pc + 1;
}
uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
int src_reg = (fetchdat >> 3) & 7;
if (cpu_iscyrix && in_smm)
return 0;
if (cpu_iscyrix && in_smm)
return 0;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
}
return op_pc + 1;
return op_pc + 1;
}
uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
return op_pc + 1;
}
uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
int src_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg));
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg));
}
return op_pc + 1;
return op_pc + 1;
}

View File

@@ -13,99 +13,91 @@
#include "codegen_ops_mmx_logic.h"
#include "codegen_ops_helpers.h"
uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
return op_pc + 1;
}
uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
return op_pc + 1;
}
uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
return op_pc + 1;
}
uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
} else {
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
return op_pc + 1;
}

View File

@@ -13,32 +13,30 @@
#include "codegen_ops_mmx_pack.h"
#include "codegen_ops_helpers.h"
#define ropPpack(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
#define ropPpack(func) \
uint32_t rop##func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs + op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) { \
int src_reg = fetchdat & 7; \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} else { \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
// clang-format off
ropPpack(PACKSSWB)
ropPpack(PACKSSDW)
ropPpack(PACKUSWB)
@@ -48,3 +46,4 @@ ropPpack(PUNPCKLDQ)
ropPpack(PUNPCKHBW)
ropPpack(PUNPCKHWD)
ropPpack(PUNPCKHDQ)
// clang-format on

View File

@@ -13,84 +13,81 @@
#include "codegen_ops_mmx_shift.h"
#include "codegen_ops_helpers.h"
uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
switch (op)
{
case 0x10: /*PSRLW*/
uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAW*/
uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLW*/
uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
switch (op) {
case 0x10: /*PSRLW*/
uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAW*/
uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLW*/
uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
}
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
switch (op)
{
case 0x10: /*PSRLD*/
uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAD*/
uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLD*/
uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
switch (op) {
case 0x10: /*PSRLD*/
uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAD*/
uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLD*/
uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
}
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}
uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
switch (op)
{
case 0x10: /*PSRLQ*/
uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAQ*/
uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLQ*/
uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs + op_pc, 1);
switch (op) {
case 0x10: /*PSRLQ*/
uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAQ*/
uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLQ*/
uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
}
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
codegen_mark_code_present(block, cs + op_pc + 1, 1);
return op_pc + 2;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -12,248 +12,243 @@
#include "codegen_ops_helpers.h"
#include "codegen_ops_misc.h"
uint32_t ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPUSH_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7));
SUB_SP(ir, 2);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_16(opcode & 7));
SUB_SP(ir, 2);
return op_pc;
return op_pc;
}
uint32_t ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPUSH_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7));
SUB_SP(ir, 4);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_32(opcode & 7));
SUB_SP(ir, 4);
return op_pc;
return op_pc;
}
uint32_t ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPOP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr);
}
if ((opcode & 7) != REG_SP)
ADD_SP(ir, 2);
return op_pc;
}
uint32_t
ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr);
}
if ((opcode & 7) != REG_ESP)
ADD_SP(ir, 4);
return op_pc;
}
uint32_t
ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm = fastreadw(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 2);
codegen_mark_code_present(block, cs + op_pc, 2);
return op_pc + 2;
}
uint32_t
ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t imm = fastreadl(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 4);
codegen_mark_code_present(block, cs + op_pc, 4);
return op_pc + 4;
}
uint32_t
ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm = (int16_t) (int8_t) fastreadb(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 2);
codegen_mark_code_present(block, cs + op_pc, 1);
return op_pc + 1;
}
uint32_t
ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t imm = (int32_t) (int8_t) fastreadb(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 4);
codegen_mark_code_present(block, cs + op_pc, 1);
return op_pc + 1;
}
uint32_t
ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr);
}
} else {
x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2);
codegen_check_seg_write(block, ir, target_seg);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_16(opcode & 7), IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_temp0, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0);
}
if ((opcode & 7) != REG_SP)
ADD_SP(ir, 2);
return op_pc;
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
}
if ((fetchdat & 0xc7) != (0xc0 | REG_SP))
ADD_SP(ir, 2);
return op_pc + 1;
}
uint32_t ropPOP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_mark_code_present(block, cs + op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0) {
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr);
}
} else {
x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4);
codegen_check_seg_write(block, ir, target_seg);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_32(opcode & 7), IREG_SS_base, IREG_eaaddr);
}
if ((opcode & 7) != REG_ESP)
ADD_SP(ir, 4);
return op_pc;
}
uint32_t ropPUSH_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm = fastreadw(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 2);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropPUSH_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t imm = fastreadl(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 4);
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropPUSH_imm_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm = (int16_t)(int8_t)fastreadb(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 2);
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropPUSH_imm_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t imm = (int32_t)(int8_t)fastreadb(cs + op_pc);
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, imm);
SUB_SP(ir, 4);
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropPOP_W(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_16(fetchdat & 7), IREG_SS_base, IREG_eaaddr);
}
}
else
{
x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 2);
codegen_check_seg_write(block, ir, target_seg);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_temp0, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_temp0);
}
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
else {
uop_MOVZX(ir, IREG_temp0, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0);
}
if ((fetchdat & 0xc7) != (0xc0 | REG_SP))
ADD_SP(ir, 2);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
}
return op_pc + 1;
}
uint32_t ropPOP_L(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if ((fetchdat & 0xc7) != (0xc0 | REG_ESP))
ADD_SP(ir, 4);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_32(fetchdat & 7), IREG_SS_base, IREG_eaaddr);
}
}
else
{
x86seg *target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 4);
codegen_check_seg_write(block, ir, target_seg);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_temp0, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_temp0);
}
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
}
if ((fetchdat & 0xc7) != (0xc0 | REG_ESP))
ADD_SP(ir, 4);
return op_pc + 1;
return op_pc + 1;
}
#define ROP_PUSH_SEG(seg) \
uint32_t ropPUSH_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int sp_reg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_ ## seg ## _seg_W); \
SUB_SP(ir, 2); \
\
return op_pc; \
} \
uint32_t ropPUSH_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int sp_reg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \
uop_MOVZX(ir, IREG_temp0, IREG_ ## seg ## _seg_W); \
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \
SUB_SP(ir, 4); \
\
return op_pc; \
}
#define ROP_POP_SEG(seg, rseg) \
uint32_t ropPOP_ ## seg ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
\
if (stack32) \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \
else \
{ \
uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \
} \
uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \
ADD_SP(ir, 2); \
\
return op_pc; \
} \
uint32_t ropPOP_ ## seg ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
\
if (stack32) \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \
else \
{ \
uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \
} \
uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \
ADD_SP(ir, 4); \
\
return op_pc; \
}
#define ROP_PUSH_SEG(seg) \
uint32_t ropPUSH_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int sp_reg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2); \
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_##seg##_seg_W); \
SUB_SP(ir, 2); \
\
return op_pc; \
} \
uint32_t ropPUSH_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int sp_reg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4); \
uop_MOVZX(ir, IREG_temp0, IREG_##seg##_seg_W); \
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_temp0); \
SUB_SP(ir, 4); \
\
return op_pc; \
}
#define ROP_POP_SEG(seg, rseg) \
uint32_t ropPOP_##seg##_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
\
if (stack32) \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \
else { \
uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \
} \
uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \
ADD_SP(ir, 2); \
\
return op_pc; \
} \
uint32_t ropPOP_##seg##_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
\
if (stack32) \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP); \
else { \
uop_MOVZX(ir, IREG_eaaddr, IREG_SP); \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr); \
} \
uop_LOAD_SEG(ir, &rseg, IREG_temp0_W); \
ADD_SP(ir, 4); \
\
return op_pc; \
}
ROP_PUSH_SEG(CS)
ROP_PUSH_SEG(DS)
@@ -266,147 +261,152 @@ ROP_POP_SEG(ES, cpu_state.seg_es)
ROP_POP_SEG(FS, cpu_state.seg_fs)
ROP_POP_SEG(GS, cpu_state.seg_gs)
uint32_t ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropLEAVE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_BP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2);
uop_MOV(ir, IREG_BP, IREG_temp0_W);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_EBP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_BP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
uop_ADD_IMM(ir, IREG_SP, IREG_BP, 2);
uop_MOV(ir, IREG_BP, IREG_temp0_W);
return op_pc;
return op_pc;
}
uint32_t ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropLEAVE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_BP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
}
uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4);
uop_MOV(ir, IREG_EBP, IREG_temp0);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_EBP);
else {
uop_MOVZX(ir, IREG_eaaddr, IREG_BP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
}
uop_ADD_IMM(ir, IREG_ESP, IREG_EBP, 4);
uop_MOV(ir, IREG_EBP, IREG_temp0);
return op_pc;
return op_pc;
}
uint32_t ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPUSHA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -16);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI);
SUB_SP(ir, 16);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -16);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 14, IREG_AX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_CX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 10, IREG_DX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_BX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 6, IREG_SP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_BP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_SI);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_DI);
SUB_SP(ir, 16);
return op_pc;
return op_pc;
}
uint32_t ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPUSHA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -32);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI);
SUB_SP(ir, 32);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -32);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 28, IREG_EAX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 24, IREG_ECX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 20, IREG_EDX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 16, IREG_EBX);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 12, IREG_ESP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 8, IREG_EBP);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 4, IREG_ESI);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_EDI);
SUB_SP(ir, 32);
return op_pc;
return op_pc;
}
uint32_t ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPOPA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP(ir);
uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14);
ADD_SP(ir, 16);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP(ir);
uop_MEM_LOAD_REG(ir, IREG_DI, IREG_SS_base, sp_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_SI, IREG_SS_base, sp_reg, 2);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_BP, IREG_SS_base, sp_reg, 4);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_BX, IREG_SS_base, sp_reg, 8);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_DX, IREG_SS_base, sp_reg, 10);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_CX, IREG_SS_base, sp_reg, 12);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_AX, IREG_SS_base, sp_reg, 14);
ADD_SP(ir, 16);
return op_pc;
return op_pc;
}
uint32_t ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPOPA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP(ir);
uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28);
ADD_SP(ir, 32);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP(ir);
uop_MEM_LOAD_REG(ir, IREG_EDI, IREG_SS_base, sp_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_ESI, IREG_SS_base, sp_reg, 4);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBP, IREG_SS_base, sp_reg, 8);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EBX, IREG_SS_base, sp_reg, 16);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EDX, IREG_SS_base, sp_reg, 20);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_ECX, IREG_SS_base, sp_reg, 24);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_EAX, IREG_SS_base, sp_reg, 28);
ADD_SP(ir, 32);
return op_pc;
return op_pc;
}
uint32_t ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPUSHF(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
return 0;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
return 0;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_CALL_FUNC(ir, flags_rebuild);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags);
SUB_SP(ir, 2);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_CALL_FUNC(ir, flags_rebuild);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags);
SUB_SP(ir, 2);
return op_pc;
return op_pc;
}
uint32_t ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
uint32_t
ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int sp_reg;
int sp_reg;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
return 0;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
return 0;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_CALL_FUNC(ir, flags_rebuild);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_CALL_FUNC(ir, flags_rebuild);
if (cpu_CR4_mask & CR4_VME)
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c);
else if (CPUID)
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24);
else
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W);
SUB_SP(ir, 4);
if (cpu_CR4_mask & CR4_VME)
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c);
else if (CPUID)
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x24);
else
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 4);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags);
uop_MEM_STORE_REG_OFFSET(ir, IREG_SS_base, sp_reg, 2, IREG_temp0_W);
SUB_SP(ir, 4);
return op_pc;
return op_pc;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,276 +1,278 @@
#ifndef _CODEGEN_REG_H_
#define _CODEGEN_REG_H_
#define IREG_REG_MASK 0xff
#define IREG_SIZE_SHIFT 8
#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT)
#define IREG_REG_MASK 0xff
#define IREG_SIZE_SHIFT 8
#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT)
#define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK)
#define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK)
#define IREG_GET_REG(reg) ((reg) &IREG_REG_MASK)
#define IREG_GET_SIZE(reg) ((reg) &IREG_SIZE_MASK)
#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT)
#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT)
#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT)
#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT)
#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT)
#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT)
#define IREG_SIZE_L (0 << IREG_SIZE_SHIFT)
#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT)
#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT)
#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT)
#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT)
#define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT)
enum
{
IREG_EAX = 0,
IREG_ECX = 1,
IREG_EDX = 2,
IREG_EBX = 3,
IREG_ESP = 4,
IREG_EBP = 5,
IREG_ESI = 6,
IREG_EDI = 7,
enum {
IREG_EAX = 0,
IREG_ECX = 1,
IREG_EDX = 2,
IREG_EBX = 3,
IREG_ESP = 4,
IREG_EBP = 5,
IREG_ESI = 6,
IREG_EDI = 7,
IREG_flags_op = 8,
IREG_flags_res = 9,
IREG_flags_op1 = 10,
IREG_flags_op2 = 11,
IREG_flags_op = 8,
IREG_flags_res = 9,
IREG_flags_op1 = 10,
IREG_flags_op2 = 11,
IREG_pc = 12,
IREG_oldpc = 13,
IREG_pc = 12,
IREG_oldpc = 13,
IREG_eaaddr = 14,
IREG_ea_seg = 15,
IREG_op32 = 16,
IREG_ssegsx = 17,
IREG_eaaddr = 14,
IREG_ea_seg = 15,
IREG_op32 = 16,
IREG_ssegsx = 17,
IREG_rm_mod_reg = 18,
IREG_rm_mod_reg = 18,
IREG_acycs = 19,
IREG_cycles = 20,
IREG_acycs = 19,
IREG_cycles = 20,
IREG_CS_base = 21,
IREG_DS_base = 22,
IREG_ES_base = 23,
IREG_FS_base = 24,
IREG_GS_base = 25,
IREG_SS_base = 26,
IREG_CS_base = 21,
IREG_DS_base = 22,
IREG_ES_base = 23,
IREG_FS_base = 24,
IREG_GS_base = 25,
IREG_SS_base = 26,
IREG_CS_seg = 27,
IREG_DS_seg = 28,
IREG_ES_seg = 29,
IREG_FS_seg = 30,
IREG_GS_seg = 31,
IREG_SS_seg = 32,
IREG_CS_seg = 27,
IREG_DS_seg = 28,
IREG_ES_seg = 29,
IREG_FS_seg = 30,
IREG_GS_seg = 31,
IREG_SS_seg = 32,
/*Temporary registers are stored on the stack, and are not guaranteed to
be preserved across uOPs. They will not be written back if they will
not be read again.*/
IREG_temp0 = 33,
IREG_temp1 = 34,
IREG_temp2 = 35,
IREG_temp3 = 36,
/*Temporary registers are stored on the stack, and are not guaranteed to
be preserved across uOPs. They will not be written back if they will
not be read again.*/
IREG_temp0 = 33,
IREG_temp1 = 34,
IREG_temp2 = 35,
IREG_temp3 = 36,
IREG_FPU_TOP = 37,
IREG_FPU_TOP = 37,
IREG_temp0d = 38,
IREG_temp1d = 39,
IREG_temp0d = 38,
IREG_temp1d = 39,
/*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag()
to access.
When CODEBLOCK_STATIC_TOP is set, the physical register number will be
used directly to index the stack. When it is clear, the difference
between the current value of TOP and the value when the block was
first compiled will be added to adjust for any changes in TOP.*/
IREG_ST0 = 40,
IREG_ST1 = 41,
IREG_ST2 = 42,
IREG_ST3 = 43,
IREG_ST4 = 44,
IREG_ST5 = 45,
IREG_ST6 = 46,
IREG_ST7 = 47,
/*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag()
to access.
When CODEBLOCK_STATIC_TOP is set, the physical register number will be
used directly to index the stack. When it is clear, the difference
between the current value of TOP and the value when the block was
first compiled will be added to adjust for any changes in TOP.*/
IREG_ST0 = 40,
IREG_ST1 = 41,
IREG_ST2 = 42,
IREG_ST3 = 43,
IREG_ST4 = 44,
IREG_ST5 = 45,
IREG_ST6 = 46,
IREG_ST7 = 47,
IREG_tag0 = 48,
IREG_tag1 = 49,
IREG_tag2 = 50,
IREG_tag3 = 51,
IREG_tag4 = 52,
IREG_tag5 = 53,
IREG_tag6 = 54,
IREG_tag7 = 55,
IREG_tag0 = 48,
IREG_tag1 = 49,
IREG_tag2 = 50,
IREG_tag3 = 51,
IREG_tag4 = 52,
IREG_tag5 = 53,
IREG_tag6 = 54,
IREG_tag7 = 55,
IREG_ST0_i64 = 56,
IREG_ST1_i64 = 57,
IREG_ST2_i64 = 58,
IREG_ST3_i64 = 59,
IREG_ST4_i64 = 60,
IREG_ST5_i64 = 61,
IREG_ST6_i64 = 62,
IREG_ST7_i64 = 63,
IREG_ST0_i64 = 56,
IREG_ST1_i64 = 57,
IREG_ST2_i64 = 58,
IREG_ST3_i64 = 59,
IREG_ST4_i64 = 60,
IREG_ST5_i64 = 61,
IREG_ST6_i64 = 62,
IREG_ST7_i64 = 63,
IREG_MM0x = 64,
IREG_MM1x = 65,
IREG_MM2x = 66,
IREG_MM3x = 67,
IREG_MM4x = 68,
IREG_MM5x = 69,
IREG_MM6x = 70,
IREG_MM7x = 71,
IREG_MM0x = 64,
IREG_MM1x = 65,
IREG_MM2x = 66,
IREG_MM3x = 67,
IREG_MM4x = 68,
IREG_MM5x = 69,
IREG_MM6x = 70,
IREG_MM7x = 71,
IREG_NPXCx = 72,
IREG_NPXSx = 73,
IREG_NPXCx = 72,
IREG_NPXSx = 73,
IREG_flagsx = 74,
IREG_eflagsx = 75,
IREG_flagsx = 74,
IREG_eflagsx = 75,
IREG_CS_limit_low = 76,
IREG_DS_limit_low = 77,
IREG_ES_limit_low = 78,
IREG_FS_limit_low = 79,
IREG_GS_limit_low = 80,
IREG_SS_limit_low = 81,
IREG_CS_limit_low = 76,
IREG_DS_limit_low = 77,
IREG_ES_limit_low = 78,
IREG_FS_limit_low = 79,
IREG_GS_limit_low = 80,
IREG_SS_limit_low = 81,
IREG_CS_limit_high = 82,
IREG_DS_limit_high = 83,
IREG_ES_limit_high = 84,
IREG_FS_limit_high = 85,
IREG_GS_limit_high = 86,
IREG_SS_limit_high = 87,
IREG_CS_limit_high = 82,
IREG_DS_limit_high = 83,
IREG_ES_limit_high = 84,
IREG_FS_limit_high = 85,
IREG_GS_limit_high = 86,
IREG_SS_limit_high = 87,
IREG_COUNT = 88,
IREG_COUNT = 88,
IREG_INVALID = 255,
IREG_INVALID = 255,
IREG_AX = IREG_EAX + IREG_SIZE_W,
IREG_CX = IREG_ECX + IREG_SIZE_W,
IREG_DX = IREG_EDX + IREG_SIZE_W,
IREG_BX = IREG_EBX + IREG_SIZE_W,
IREG_SP = IREG_ESP + IREG_SIZE_W,
IREG_BP = IREG_EBP + IREG_SIZE_W,
IREG_SI = IREG_ESI + IREG_SIZE_W,
IREG_DI = IREG_EDI + IREG_SIZE_W,
IREG_AX = IREG_EAX + IREG_SIZE_W,
IREG_CX = IREG_ECX + IREG_SIZE_W,
IREG_DX = IREG_EDX + IREG_SIZE_W,
IREG_BX = IREG_EBX + IREG_SIZE_W,
IREG_SP = IREG_ESP + IREG_SIZE_W,
IREG_BP = IREG_EBP + IREG_SIZE_W,
IREG_SI = IREG_ESI + IREG_SIZE_W,
IREG_DI = IREG_EDI + IREG_SIZE_W,
IREG_AL = IREG_EAX + IREG_SIZE_B,
IREG_CL = IREG_ECX + IREG_SIZE_B,
IREG_DL = IREG_EDX + IREG_SIZE_B,
IREG_BL = IREG_EBX + IREG_SIZE_B,
IREG_AL = IREG_EAX + IREG_SIZE_B,
IREG_CL = IREG_ECX + IREG_SIZE_B,
IREG_DL = IREG_EDX + IREG_SIZE_B,
IREG_BL = IREG_EBX + IREG_SIZE_B,
IREG_AH = IREG_EAX + IREG_SIZE_BH,
IREG_CH = IREG_ECX + IREG_SIZE_BH,
IREG_DH = IREG_EDX + IREG_SIZE_BH,
IREG_BH = IREG_EBX + IREG_SIZE_BH,
IREG_AH = IREG_EAX + IREG_SIZE_BH,
IREG_CH = IREG_ECX + IREG_SIZE_BH,
IREG_DH = IREG_EDX + IREG_SIZE_BH,
IREG_BH = IREG_EBX + IREG_SIZE_BH,
IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W,
IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W,
IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W,
IREG_flags_res_W = IREG_flags_res + IREG_SIZE_W,
IREG_flags_op1_W = IREG_flags_op1 + IREG_SIZE_W,
IREG_flags_op2_W = IREG_flags_op2 + IREG_SIZE_W,
IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B,
IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B,
IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B,
IREG_flags_res_B = IREG_flags_res + IREG_SIZE_B,
IREG_flags_op1_B = IREG_flags_op1 + IREG_SIZE_B,
IREG_flags_op2_B = IREG_flags_op2 + IREG_SIZE_B,
IREG_temp0_W = IREG_temp0 + IREG_SIZE_W,
IREG_temp1_W = IREG_temp1 + IREG_SIZE_W,
IREG_temp2_W = IREG_temp2 + IREG_SIZE_W,
IREG_temp3_W = IREG_temp3 + IREG_SIZE_W,
IREG_temp0_W = IREG_temp0 + IREG_SIZE_W,
IREG_temp1_W = IREG_temp1 + IREG_SIZE_W,
IREG_temp2_W = IREG_temp2 + IREG_SIZE_W,
IREG_temp3_W = IREG_temp3 + IREG_SIZE_W,
IREG_temp0_B = IREG_temp0 + IREG_SIZE_B,
IREG_temp1_B = IREG_temp1 + IREG_SIZE_B,
IREG_temp2_B = IREG_temp2 + IREG_SIZE_B,
IREG_temp3_B = IREG_temp3 + IREG_SIZE_B,
IREG_temp0_B = IREG_temp0 + IREG_SIZE_B,
IREG_temp1_B = IREG_temp1 + IREG_SIZE_B,
IREG_temp2_B = IREG_temp2 + IREG_SIZE_B,
IREG_temp3_B = IREG_temp3 + IREG_SIZE_B,
IREG_temp0_D = IREG_temp0d + IREG_SIZE_D,
IREG_temp1_D = IREG_temp1d + IREG_SIZE_D,
IREG_temp0_D = IREG_temp0d + IREG_SIZE_D,
IREG_temp1_D = IREG_temp1d + IREG_SIZE_D,
IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q,
IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q,
IREG_temp0_Q = IREG_temp0d + IREG_SIZE_Q,
IREG_temp1_Q = IREG_temp1d + IREG_SIZE_Q,
IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W,
IREG_eaaddr_W = IREG_eaaddr + IREG_SIZE_W,
IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W,
IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W,
IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W,
IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W,
IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W,
IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W,
IREG_CS_seg_W = IREG_CS_seg + IREG_SIZE_W,
IREG_DS_seg_W = IREG_DS_seg + IREG_SIZE_W,
IREG_ES_seg_W = IREG_ES_seg + IREG_SIZE_W,
IREG_FS_seg_W = IREG_FS_seg + IREG_SIZE_W,
IREG_GS_seg_W = IREG_GS_seg + IREG_SIZE_W,
IREG_SS_seg_W = IREG_SS_seg + IREG_SIZE_W,
IREG_MM0 = IREG_MM0x + IREG_SIZE_Q,
IREG_MM1 = IREG_MM1x + IREG_SIZE_Q,
IREG_MM2 = IREG_MM2x + IREG_SIZE_Q,
IREG_MM3 = IREG_MM3x + IREG_SIZE_Q,
IREG_MM4 = IREG_MM4x + IREG_SIZE_Q,
IREG_MM5 = IREG_MM5x + IREG_SIZE_Q,
IREG_MM6 = IREG_MM6x + IREG_SIZE_Q,
IREG_MM7 = IREG_MM7x + IREG_SIZE_Q,
IREG_MM0 = IREG_MM0x + IREG_SIZE_Q,
IREG_MM1 = IREG_MM1x + IREG_SIZE_Q,
IREG_MM2 = IREG_MM2x + IREG_SIZE_Q,
IREG_MM3 = IREG_MM3x + IREG_SIZE_Q,
IREG_MM4 = IREG_MM4x + IREG_SIZE_Q,
IREG_MM5 = IREG_MM5x + IREG_SIZE_Q,
IREG_MM6 = IREG_MM6x + IREG_SIZE_Q,
IREG_MM7 = IREG_MM7x + IREG_SIZE_Q,
IREG_NPXC = IREG_NPXCx + IREG_SIZE_W,
IREG_NPXS = IREG_NPXSx + IREG_SIZE_W,
IREG_NPXC = IREG_NPXCx + IREG_SIZE_W,
IREG_NPXS = IREG_NPXSx + IREG_SIZE_W,
IREG_ssegs = IREG_ssegsx + IREG_SIZE_B,
IREG_ssegs = IREG_ssegsx + IREG_SIZE_B,
IREG_flags = IREG_flagsx + IREG_SIZE_W,
IREG_eflags = IREG_eflagsx + IREG_SIZE_W
IREG_flags = IREG_flagsx + IREG_SIZE_W,
IREG_eflags = IREG_eflagsx + IREG_SIZE_W
};
#define IREG_8(reg) (((reg) & 4) ? (((reg) & 3) + IREG_AH) : ((reg) + IREG_AL))
#define IREG_16(reg) ((reg) + IREG_AX)
#define IREG_32(reg) ((reg) + IREG_EAX)
#define IREG_8(reg) (((reg) &4) ? (((reg) &3) + IREG_AH) : ((reg) + IREG_AL))
#define IREG_16(reg) ((reg) + IREG_AX)
#define IREG_32(reg) ((reg) + IREG_EAX)
#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D)
#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q)
#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7))
#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B)
#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D)
#define IREG_ST_i64(r) (IREG_ST0_i64 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q)
#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7))
#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B)
#define IREG_MM(reg) ((reg) + IREG_MM0)
#define IREG_MM(reg) ((reg) + IREG_MM0)
#define IREG_TOP_diff_stack_offset 32
static inline int ireg_seg_base(x86seg *seg)
static inline int
ireg_seg_base(x86seg *seg)
{
if (seg == &cpu_state.seg_cs)
return IREG_CS_base;
if (seg == &cpu_state.seg_ds)
return IREG_DS_base;
if (seg == &cpu_state.seg_es)
return IREG_ES_base;
if (seg == &cpu_state.seg_fs)
return IREG_FS_base;
if (seg == &cpu_state.seg_gs)
return IREG_GS_base;
if (seg == &cpu_state.seg_ss)
return IREG_SS_base;
fatal("ireg_seg_base : unknown segment\n");
return 0;
if (seg == &cpu_state.seg_cs)
return IREG_CS_base;
if (seg == &cpu_state.seg_ds)
return IREG_DS_base;
if (seg == &cpu_state.seg_es)
return IREG_ES_base;
if (seg == &cpu_state.seg_fs)
return IREG_FS_base;
if (seg == &cpu_state.seg_gs)
return IREG_GS_base;
if (seg == &cpu_state.seg_ss)
return IREG_SS_base;
fatal("ireg_seg_base : unknown segment\n");
return 0;
}
static inline int ireg_seg_limit_low(x86seg *seg)
static inline int
ireg_seg_limit_low(x86seg *seg)
{
if (seg == &cpu_state.seg_cs)
return IREG_CS_limit_low;
if (seg == &cpu_state.seg_ds)
return IREG_DS_limit_low;
if (seg == &cpu_state.seg_es)
return IREG_ES_limit_low;
if (seg == &cpu_state.seg_fs)
return IREG_FS_limit_low;
if (seg == &cpu_state.seg_gs)
return IREG_GS_limit_low;
if (seg == &cpu_state.seg_ss)
return IREG_SS_limit_low;
fatal("ireg_seg_limit_low : unknown segment\n");
return 0;
if (seg == &cpu_state.seg_cs)
return IREG_CS_limit_low;
if (seg == &cpu_state.seg_ds)
return IREG_DS_limit_low;
if (seg == &cpu_state.seg_es)
return IREG_ES_limit_low;
if (seg == &cpu_state.seg_fs)
return IREG_FS_limit_low;
if (seg == &cpu_state.seg_gs)
return IREG_GS_limit_low;
if (seg == &cpu_state.seg_ss)
return IREG_SS_limit_low;
fatal("ireg_seg_limit_low : unknown segment\n");
return 0;
}
static inline int ireg_seg_limit_high(x86seg *seg)
static inline int
ireg_seg_limit_high(x86seg *seg)
{
if (seg == &cpu_state.seg_cs)
return IREG_CS_limit_high;
if (seg == &cpu_state.seg_ds)
return IREG_DS_limit_high;
if (seg == &cpu_state.seg_es)
return IREG_ES_limit_high;
if (seg == &cpu_state.seg_fs)
return IREG_FS_limit_high;
if (seg == &cpu_state.seg_gs)
return IREG_GS_limit_high;
if (seg == &cpu_state.seg_ss)
return IREG_SS_limit_high;
fatal("ireg_seg_limit_high : unknown segment\n");
return 0;
if (seg == &cpu_state.seg_cs)
return IREG_CS_limit_high;
if (seg == &cpu_state.seg_ds)
return IREG_DS_limit_high;
if (seg == &cpu_state.seg_es)
return IREG_ES_limit_high;
if (seg == &cpu_state.seg_fs)
return IREG_FS_limit_high;
if (seg == &cpu_state.seg_gs)
return IREG_GS_limit_high;
if (seg == &cpu_state.seg_ss)
return IREG_SS_limit_high;
fatal("ireg_seg_limit_high : unknown segment\n");
return 0;
}
extern uint8_t reg_last_version[IREG_COUNT];
@@ -279,18 +281,18 @@ extern uint8_t reg_last_version[IREG_COUNT];
apparently required or not. Do not optimise out.*/
#define REG_FLAGS_REQUIRED (1 << 0)
/*This register and the parent uOP have been optimised out.*/
#define REG_FLAGS_DEAD (1 << 1)
#define REG_FLAGS_DEAD (1 << 1)
typedef struct
{
/*Refcount of pending reads on this register version*/
uint8_t refcount;
/*Flags*/
uint8_t flags;
/*uOP that generated this register version*/
uint16_t parent_uop;
/*Pointer to next register version in dead register list*/
uint16_t next;
/*Refcount of pending reads on this register version*/
uint8_t refcount;
/*Flags*/
uint8_t flags;
/*uOP that generated this register version*/
uint16_t parent_uop;
/*Pointer to next register version in dead register list*/
uint16_t next;
} reg_version_t;
extern reg_version_t reg_version[IREG_COUNT][256];
@@ -299,16 +301,17 @@ extern reg_version_t reg_version[IREG_COUNT][256];
can be optimised out*/
extern uint16_t reg_dead_list;
static inline void add_to_dead_list(reg_version_t *regv, int reg, int version)
static inline void
add_to_dead_list(reg_version_t *regv, int reg, int version)
{
regv->next = reg_dead_list;
reg_dead_list = version | (reg << 8);
regv->next = reg_dead_list;
reg_dead_list = version | (reg << 8);
}
typedef struct
{
uint16_t reg;
uint16_t version;
uint16_t reg;
uint16_t version;
} ir_reg_t;
extern ir_reg_t invalid_ir_reg;
@@ -317,80 +320,81 @@ typedef uint16_t ir_host_reg_t;
extern int max_version_refcount;
#define REG_VERSION_MAX 250
#define REG_VERSION_MAX 250
#define REG_REFCOUNT_MAX 250
static inline ir_reg_t codegen_reg_read(int reg)
static inline ir_reg_t
codegen_reg_read(int reg)
{
ir_reg_t ireg;
reg_version_t *version;
ir_reg_t ireg;
reg_version_t *version;
#ifndef RELEASE_BUILD
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_read - IREG_INVALID\n");
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_read - IREG_INVALID\n");
#endif
ireg.reg = reg;
ireg.version = reg_last_version[IREG_GET_REG(reg)];
version = &reg_version[IREG_GET_REG(ireg.reg)][ireg.version];
version->flags = 0;
version->refcount++;
ireg.reg = reg;
ireg.version = reg_last_version[IREG_GET_REG(reg)];
version = &reg_version[IREG_GET_REG(ireg.reg)][ireg.version];
version->flags = 0;
version->refcount++;
#ifndef RELEASE_BUILD
if (!version->refcount)
fatal("codegen_reg_read - refcount overflow\n");
else
if (!version->refcount)
fatal("codegen_reg_read - refcount overflow\n");
else
#endif
if (version->refcount > REG_REFCOUNT_MAX)
CPU_BLOCK_END();
if (version->refcount > max_version_refcount)
max_version_refcount = version->refcount;
// pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]);
return ireg;
CPU_BLOCK_END();
if (version->refcount > max_version_refcount)
max_version_refcount = version->refcount;
// pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]);
return ireg;
}
int reg_is_native_size(ir_reg_t ir_reg);
static inline ir_reg_t codegen_reg_write(int reg, int uop_nr)
static inline ir_reg_t
codegen_reg_write(int reg, int uop_nr)
{
ir_reg_t ireg;
int last_version = reg_last_version[IREG_GET_REG(reg)];
reg_version_t *version;
ir_reg_t ireg;
int last_version = reg_last_version[IREG_GET_REG(reg)];
reg_version_t *version;
#ifndef RELEASE_BUILD
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_write - IREG_INVALID\n");
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_write - IREG_INVALID\n");
#endif
ireg.reg = reg;
ireg.version = last_version + 1;
ireg.reg = reg;
ireg.version = last_version + 1;
if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount &&
!(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED))
{
if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/
add_to_dead_list(&reg_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version);
}
if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount && !(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED)) {
if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/
add_to_dead_list(&reg_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version);
}
reg_last_version[IREG_GET_REG(reg)]++;
reg_last_version[IREG_GET_REG(reg)]++;
#ifndef RELEASE_BUILD
if (!reg_last_version[IREG_GET_REG(reg)])
fatal("codegen_reg_write - version overflow\n");
else
if (!reg_last_version[IREG_GET_REG(reg)])
fatal("codegen_reg_write - version overflow\n");
else
#endif
if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX)
CPU_BLOCK_END();
if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount)
max_version_refcount = reg_last_version[IREG_GET_REG(reg)];
CPU_BLOCK_END();
if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount)
max_version_refcount = reg_last_version[IREG_GET_REG(reg)];
version = &reg_version[IREG_GET_REG(reg)][ireg.version];
version->refcount = 0;
version->flags = 0;
version->parent_uop = uop_nr;
// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK);
return ireg;
version = &reg_version[IREG_GET_REG(reg)][ireg.version];
version->refcount = 0;
version->flags = 0;
version->parent_uop = uop_nr;
// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK);
return ireg;
}
static inline int ir_reg_is_invalid(ir_reg_t ir_reg)
static inline int
ir_reg_is_invalid(ir_reg_t ir_reg)
{
return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID);
return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID);
}
struct ir_data_t;
@@ -405,7 +409,7 @@ void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block);
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c);
#ifdef CODEGEN_BACKEND_HAS_MOV_IMM
int codegen_reg_is_loaded(ir_reg_t ir_reg);
int codegen_reg_is_loaded(ir_reg_t ir_reg);
void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data);
#endif

View File

@@ -209,7 +209,7 @@ exec386(int cycs)
enter_smm_check(0);
else if (nmi && nmi_enable && nmi_mask) {
#ifndef USE_NEW_DYNAREC
oldcs = CS;
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
x86_int(2);

File diff suppressed because it is too large Load Diff

View File

@@ -21,308 +21,400 @@
#include <stddef.h>
#define readmemb_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF)?readmembl_no_mmut((s)+(a),b): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uintptr_t)((s) + (a))) )
#define readmemw_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl_no_mmut((s)+(a),b):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmeml_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll_no_mmut((s)+(a),b):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uintptr_t)((s) + (a))) )
#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uintptr_t)((s)+(a))))
#define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
#define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
#define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
#define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
#define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
#define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
#define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
#define writememb_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) writemembl_no_mmut((s)+(a),b,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememw_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl_no_mmut((s)+(a),b,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememl_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll_no_mmut((s)+(a),b,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v
#define writememb_n(s, a, b, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \
writemembl_no_mmut((s) + (a), b, v); \
else \
*(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define writememw_n(s, a, b, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \
writememwl_no_mmut((s) + (a), b, v); \
else \
*(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define writememl_n(s, a, b, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
writememll_no_mmut((s) + (a), b, v); \
else \
*(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define writememb(s, a, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \
writemembl((s) + (a), v); \
else \
*(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define writememw(s, a, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \
writememwl((s) + (a), v); \
else \
*(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define writememl(s, a, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
writememll((s) + (a), v); \
else \
*(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define writememq(s, a, v) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7)) \
writememql((s) + (a), v); \
else \
*(uint64_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
#define do_mmut_rb(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 0)
#define do_mmut_rw(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 0)
#define do_mmut_rl(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 0)
#define do_mmut_rb2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 0)
#define do_mmut_rw2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 0)
#define do_mmut_rl2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 0)
#define do_mmut_wb(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 1)
#define do_mmut_ww(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 1)
#define do_mmut_wl(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 1)
#define do_mmut_rb(s, a, b) \
if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \
do_mmutranslate((s) + (a), b, 1, 0)
#define do_mmut_rw(s, a, b) \
if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \
do_mmutranslate((s) + (a), b, 2, 0)
#define do_mmut_rl(s, a, b) \
if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
do_mmutranslate((s) + (a), b, 4, 0)
#define do_mmut_rb2(s, a, b) \
old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \
if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \
do_mmutranslate((s) + (a), b, 1, 0)
#define do_mmut_rw2(s, a, b) \
old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \
if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \
do_mmutranslate((s) + (a), b, 2, 0)
#define do_mmut_rl2(s, a, b) \
old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \
if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
do_mmutranslate((s) + (a), b, 4, 0)
#define do_mmut_wb(s, a, b) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) \
do_mmutranslate((s) + (a), b, 1, 1)
#define do_mmut_ww(s, a, b) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) \
do_mmutranslate((s) + (a), b, 2, 1)
#define do_mmut_wl(s, a, b) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
do_mmutranslate((s) + (a), b, 4, 1)
int checkio(uint32_t port);
#define check_io_perm(port) \
if (msw & 1 && ((CPL > IOPL) || (cpu_state.eflags & VM_FLAG))) { \
int tempi = checkio(port); \
if (cpu_state.abrt) \
return 1; \
if (tempi) { \
if (cpu_state.eflags & VM_FLAG) \
x86gpf_expected(NULL, 0); \
else \
x86gpf(NULL, 0); \
return 1; \
} \
}
#define check_io_perm(port) if (msw&1 && ((CPL > IOPL) || (cpu_state.eflags&VM_FLAG))) \
{ \
int tempi = checkio(port); \
if (cpu_state.abrt) return 1; \
if (tempi) \
{ \
if (cpu_state.eflags & VM_FLAG) \
x86gpf_expected(NULL,0); \
else \
x86gpf(NULL,0); \
return 1; \
} \
}
#define SEG_CHECK_READ(seg) \
do { \
if ((seg)->base == 0xffffffff) { \
x86gpf("Segment can't read", 0); \
return 1; \
} \
} while (0)
#define SEG_CHECK_READ(seg) \
do \
{ \
if ((seg)->base == 0xffffffff) \
{ \
x86gpf("Segment can't read", 0);\
return 1; \
} \
} while (0)
#define SEG_CHECK_WRITE(seg) \
do { \
if ((seg)->base == 0xffffffff) { \
x86gpf("Segment can't write", 0); \
return 1; \
} \
} while (0)
#define SEG_CHECK_WRITE(seg) \
do \
{ \
if ((seg)->base == 0xffffffff) \
{ \
x86gpf("Segment can't write", 0);\
return 1; \
} \
} while (0)
#define CHECK_READ(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) { \
x86gpf("Limit check (READ)", 0); \
return 1; \
} \
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL, (chseg)->seg & 0xfffc); \
else \
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_READ(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) \
{ \
x86gpf("Limit check (READ)", 0); \
return 1; \
} \
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_READ_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \
x86gpf("Limit check (READ)", 0); \
break; \
} \
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL, (chseg)->seg & 0xfffc); \
else \
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
break; \
}
#define CHECK_READ_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \
{ \
x86gpf("Limit check (READ)", 0); \
break; \
} \
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
break; \
}
#define CHECK_WRITE_COMMON(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) { \
x86gpf("Limit check (WRITE)", 0); \
return 1; \
} \
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL, (chseg)->seg & 0xfffc); \
else \
x86np("Write to seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_WRITE_COMMON(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) \
{ \
x86gpf("Limit check (WRITE)", 0); \
return 1; \
} \
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Write to seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_WRITE(chseg, low, high) \
CHECK_WRITE_COMMON(chseg, low, high)
#define CHECK_WRITE(chseg, low, high) \
CHECK_WRITE_COMMON(chseg, low, high)
#define CHECK_WRITE_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \
x86gpf("Limit check (WRITE REP)", 0); \
break; \
} \
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL, (chseg)->seg & 0xfffc); \
else \
x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \
break; \
}
#define CHECK_WRITE_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \
{ \
x86gpf("Limit check (WRITE REP)", 0); \
break; \
} \
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &cpu_state.seg_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \
break; \
}
#define NOTRM \
if (!(msw & 1) || (cpu_state.eflags & VM_FLAG)) { \
x86_int(6); \
return 1; \
}
#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
{ \
x86_int(6); \
return 1; \
}
static __inline uint8_t fastreadb(uint32_t a)
static __inline uint8_t
fastreadb(uint32_t a)
{
uint8_t *t;
uint8_t *t;
if ((a >> 12) == pccache)
return *((uint8_t *)&pccache2[a]);
t = getpccache(a);
if (cpu_state.abrt)
return 0;
pccache = a >> 12;
pccache2 = t;
return *((uint8_t *)&pccache2[a]);
if ((a >> 12) == pccache)
return *((uint8_t *) &pccache2[a]);
t = getpccache(a);
if (cpu_state.abrt)
return 0;
pccache = a >> 12;
pccache2 = t;
return *((uint8_t *) &pccache2[a]);
}
static __inline uint16_t fastreadw(uint32_t a)
static __inline uint16_t
fastreadw(uint32_t a)
{
uint8_t *t;
uint16_t val;
if ((a&0xFFF)>0xFFE)
{
val = fastreadb(a);
val |= (fastreadb(a + 1) << 8);
return val;
}
if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]);
t = getpccache(a);
if (cpu_state.abrt)
return 0;
pccache = a >> 12;
pccache2 = t;
return *((uint16_t *)&pccache2[a]);
}
static __inline uint32_t fastreadl(uint32_t a)
{
uint8_t *t;
uint32_t val;
if ((a&0xFFF)<0xFFD)
{
if ((a>>12)!=pccache)
{
t = getpccache(a);
if (cpu_state.abrt)
return 0;
pccache2 = t;
pccache=a>>12;
}
return *((uint32_t *)&pccache2[a]);
}
val = fastreadw(a);
val |= (fastreadw(a + 2) << 16);
uint8_t *t;
uint16_t val;
if ((a & 0xFFF) > 0xFFE) {
val = fastreadb(a);
val |= (fastreadb(a + 1) << 8);
return val;
}
if ((a >> 12) == pccache)
return *((uint16_t *) &pccache2[a]);
t = getpccache(a);
if (cpu_state.abrt)
return 0;
pccache = a >> 12;
pccache2 = t;
return *((uint16_t *) &pccache2[a]);
}
static __inline void *get_ram_ptr(uint32_t a)
static __inline uint32_t
fastreadl(uint32_t a)
{
if ((a >> 12) == pccache)
return &pccache2[a];
else
{
uint8_t *t = getpccache(a);
return &t[a];
uint8_t *t;
uint32_t val;
if ((a & 0xFFF) < 0xFFD) {
if ((a >> 12) != pccache) {
t = getpccache(a);
if (cpu_state.abrt)
return 0;
pccache2 = t;
pccache = a >> 12;
}
return *((uint32_t *) &pccache2[a]);
}
val = fastreadw(a);
val |= (fastreadw(a + 2) << 16);
return val;
}
static __inline uint8_t getbyte(void)
static __inline void *
get_ram_ptr(uint32_t a)
{
cpu_state.pc++;
return fastreadb(cs + (cpu_state.pc - 1));
if ((a >> 12) == pccache)
return &pccache2[a];
else {
uint8_t *t = getpccache(a);
return &t[a];
}
}
static __inline uint16_t getword(void)
static __inline uint8_t
getbyte(void)
{
cpu_state.pc+=2;
return fastreadw(cs+(cpu_state.pc-2));
cpu_state.pc++;
return fastreadb(cs + (cpu_state.pc - 1));
}
static __inline uint32_t getlong(void)
static __inline uint16_t
getword(void)
{
cpu_state.pc+=4;
return fastreadl(cs+(cpu_state.pc-4));
cpu_state.pc += 2;
return fastreadw(cs + (cpu_state.pc - 2));
}
static __inline uint64_t getquad(void)
static __inline uint32_t
getlong(void)
{
cpu_state.pc+=8;
return fastreadl(cs+(cpu_state.pc-8)) | ((uint64_t)fastreadl(cs+(cpu_state.pc-4)) << 32);
cpu_state.pc += 4;
return fastreadl(cs + (cpu_state.pc - 4));
}
static __inline uint8_t geteab(void)
static __inline uint64_t
getquad(void)
{
if (cpu_mod == 3)
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
if (eal_r)
return *(uint8_t *)eal_r;
return readmemb(easeg, cpu_state.eaaddr);
cpu_state.pc += 8;
return fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32);
}
static __inline uint16_t geteaw(void)
static __inline uint8_t
geteab(void)
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].w;
if (eal_r)
return *(uint16_t *)eal_r;
return readmemw(easeg, cpu_state.eaaddr);
if (cpu_mod == 3)
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l;
if (eal_r)
return *(uint8_t *) eal_r;
return readmemb(easeg, cpu_state.eaaddr);
}
static __inline uint32_t geteal(void)
static __inline uint16_t
geteaw(void)
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].l;
if (eal_r)
return *eal_r;
return readmeml(easeg, cpu_state.eaaddr);
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].w;
if (eal_r)
return *(uint16_t *) eal_r;
return readmemw(easeg, cpu_state.eaaddr);
}
static __inline uint64_t geteaq(void)
static __inline uint32_t
geteal(void)
{
return readmemq(easeg, cpu_state.eaaddr);
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].l;
if (eal_r)
return *eal_r;
return readmeml(easeg, cpu_state.eaaddr);
}
static __inline uint8_t geteab_mem(void)
static __inline uint64_t
geteaq(void)
{
if (eal_r) return *(uint8_t *)eal_r;
return readmemb(easeg,cpu_state.eaaddr);
return readmemq(easeg, cpu_state.eaaddr);
}
static __inline uint16_t geteaw_mem(void)
static __inline uint8_t
geteab_mem(void)
{
if (eal_r) return *(uint16_t *)eal_r;
return readmemw(easeg,cpu_state.eaaddr);
if (eal_r)
return *(uint8_t *) eal_r;
return readmemb(easeg, cpu_state.eaaddr);
}
static __inline uint32_t geteal_mem(void)
static __inline uint16_t
geteaw_mem(void)
{
if (eal_r) return *eal_r;
return readmeml(easeg,cpu_state.eaaddr);
if (eal_r)
return *(uint16_t *) eal_r;
return readmemw(easeg, cpu_state.eaaddr);
}
static __inline int seteaq_cwc(void)
static __inline uint32_t
geteal_mem(void)
{
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
return 0;
if (eal_r)
return *eal_r;
return readmeml(easeg, cpu_state.eaaddr);
}
static __inline void seteaq(uint64_t v)
static __inline int
seteaq_cwc(void)
{
if (seteaq_cwc())
return;
writememql(easeg + cpu_state.eaaddr, v);
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
return 0;
}
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
#define seteaw(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
#define seteal(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
static __inline void
seteaq(uint64_t v)
{
if (seteaq_cwc())
return;
writememql(easeg + cpu_state.eaaddr, v);
}
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v);
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v);
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v);
#define seteab(v) \
if (cpu_mod != 3) { \
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); \
if (eal_w) \
*(uint8_t *) eal_w = v; \
else \
writemembl(easeg + cpu_state.eaaddr, v); \
} else if (cpu_rm & 4) \
cpu_state.regs[cpu_rm & 3].b.h = v; \
else \
cpu_state.regs[cpu_rm].b.l = v
#define seteaw(v) \
if (cpu_mod != 3) { \
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); \
if (eal_w) \
*(uint16_t *) eal_w = v; \
else \
writememwl(easeg + cpu_state.eaaddr, v); \
} else \
cpu_state.regs[cpu_rm].w = v
#define seteal(v) \
if (cpu_mod != 3) { \
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \
if (eal_w) \
*eal_w = v; \
else \
writememll(easeg + cpu_state.eaaddr, v); \
} else \
cpu_state.regs[cpu_rm].l = v
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
#define seteab_mem(v) \
if (eal_w) \
*(uint8_t *) eal_w = v; \
else \
writemembl(easeg + cpu_state.eaaddr, v);
#define seteaw_mem(v) \
if (eal_w) \
*(uint16_t *) eal_w = v; \
else \
writememwl(easeg + cpu_state.eaaddr, v);
#define seteal_mem(v) \
if (eal_w) \
*eal_w = v; \
else \
writememll(easeg + cpu_state.eaaddr, v);
#define getbytef() \
((uint8_t) (fetchdat)); \
cpu_state.pc++
#define getwordf() \
((uint16_t) (fetchdat)); \
cpu_state.pc += 2
#define getbyte2f() \
((uint8_t) (fetchdat >> 8)); \
cpu_state.pc++
#define getword2f() \
((uint16_t) (fetchdat >> 8)); \
cpu_state.pc += 2
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
# define INFINITY (__builtin_inff())
#endif
#include <86box/86box.h>
@@ -25,57 +25,61 @@
#define CPU_BLOCK_END() cpu_block_end = 1
#ifndef IS_DYNAREC
#define IS_DYNAREC
# define IS_DYNAREC
#endif
#include "386_common.h"
static __inline void fetch_ea_32_long(uint32_t rmdat)
static __inline void
fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
if ( readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) {
uint32_t addr = easeg + cpu_state.eaaddr;
if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr);
}
}
static __inline void fetch_ea_16_long(uint32_t rmdat)
static __inline void
fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
if ( readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) {
uint32_t addr = easeg + cpu_state.eaaddr;
if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV)
eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr);
}
}
#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
#define fetch_ea_16(rmdat) \
cpu_state.pc++; \
if (cpu_mod != 3) \
fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) \
cpu_state.pc++; \
if (cpu_mod != 3) \
fetch_ea_32_long(rmdat);
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32)
#define PREFETCH_PREFIX()
#define PREFETCH_FLUSH()
#define OP_TABLE(name) dynarec_ops_ ## name
#define OP_TABLE(name) dynarec_ops_##name
#define CLOCK_CYCLES(c)
#if 0
#define CLOCK_CYCLES_FPU(c)
#define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
# define CLOCK_CYCLES_FPU(c)
# define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
#else
#define CLOCK_CYCLES_FPU(c)
#define CONCURRENCY_CYCLES(c)
# define CLOCK_CYCLES_FPU(c)
# define CONCURRENCY_CYCLES(c)
#endif
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)

View File

@@ -40,128 +40,137 @@
*/
#include "x86_ops.h"
#define ILLEGAL_ON(cond) \
do { \
if ((cond)) { \
cpu_state.pc = cpu_state.oldpc; \
x86illegal(); \
return 0; \
} \
} while (0)
#define ILLEGAL_ON(cond) \
do \
{ \
if ((cond)) \
{ \
cpu_state.pc = cpu_state.oldpc; \
x86illegal(); \
return 0; \
} \
} while (0)
static __inline void PUSH_W(uint16_t val)
static __inline void
PUSH_W(uint16_t val)
{
if (stack32)
{
writememw(ss, ESP - 2, val); if (cpu_state.abrt) return;
ESP -= 2;
}
else
{
writememw(ss, (SP - 2) & 0xFFFF, val); if (cpu_state.abrt) return;
SP -= 2;
}
if (stack32) {
writememw(ss, ESP - 2, val);
if (cpu_state.abrt)
return;
ESP -= 2;
} else {
writememw(ss, (SP - 2) & 0xFFFF, val);
if (cpu_state.abrt)
return;
SP -= 2;
}
}
static __inline void PUSH_L(uint32_t val)
static __inline void
PUSH_L(uint32_t val)
{
if (stack32)
{
writememl(ss, ESP - 4, val); if (cpu_state.abrt) return;
ESP -= 4;
}
else
{
writememl(ss, (SP - 4) & 0xFFFF, val); if (cpu_state.abrt) return;
SP -= 4;
}
if (stack32) {
writememl(ss, ESP - 4, val);
if (cpu_state.abrt)
return;
ESP -= 4;
} else {
writememl(ss, (SP - 4) & 0xFFFF, val);
if (cpu_state.abrt)
return;
SP -= 4;
}
}
static __inline uint16_t POP_W(void)
static __inline uint16_t
POP_W(void)
{
uint16_t ret;
if (stack32)
{
ret = readmemw(ss, ESP); if (cpu_state.abrt) return 0;
ESP += 2;
}
else
{
ret = readmemw(ss, SP); if (cpu_state.abrt) return 0;
SP += 2;
}
return ret;
uint16_t ret;
if (stack32) {
ret = readmemw(ss, ESP);
if (cpu_state.abrt)
return 0;
ESP += 2;
} else {
ret = readmemw(ss, SP);
if (cpu_state.abrt)
return 0;
SP += 2;
}
return ret;
}
static __inline uint32_t POP_L(void)
static __inline uint32_t
POP_L(void)
{
uint32_t ret;
if (stack32)
{
ret = readmeml(ss, ESP); if (cpu_state.abrt) return 0;
ESP += 4;
}
else
{
ret = readmeml(ss, SP); if (cpu_state.abrt) return 0;
SP += 4;
}
return ret;
uint32_t ret;
if (stack32) {
ret = readmeml(ss, ESP);
if (cpu_state.abrt)
return 0;
ESP += 4;
} else {
ret = readmeml(ss, SP);
if (cpu_state.abrt)
return 0;
SP += 4;
}
return ret;
}
static __inline uint16_t POP_W_seg(uint32_t seg)
static __inline uint16_t
POP_W_seg(uint32_t seg)
{
uint16_t ret;
if (stack32)
{
ret = readmemw(seg, ESP); if (cpu_state.abrt) return 0;
ESP += 2;
}
else
{
ret = readmemw(seg, SP); if (cpu_state.abrt) return 0;
SP += 2;
}
return ret;
uint16_t ret;
if (stack32) {
ret = readmemw(seg, ESP);
if (cpu_state.abrt)
return 0;
ESP += 2;
} else {
ret = readmemw(seg, SP);
if (cpu_state.abrt)
return 0;
SP += 2;
}
return ret;
}
static __inline uint32_t POP_L_seg(uint32_t seg)
static __inline uint32_t
POP_L_seg(uint32_t seg)
{
uint32_t ret;
if (stack32)
{
ret = readmeml(seg, ESP); if (cpu_state.abrt) return 0;
ESP += 4;
}
else
{
ret = readmeml(seg, SP); if (cpu_state.abrt) return 0;
SP += 4;
}
return ret;
uint32_t ret;
if (stack32) {
ret = readmeml(seg, ESP);
if (cpu_state.abrt)
return 0;
ESP += 4;
} else {
ret = readmeml(seg, SP);
if (cpu_state.abrt)
return 0;
SP += 4;
}
return ret;
}
static int fopcode;
static int ILLEGAL(uint32_t fetchdat)
static int
ILLEGAL(uint32_t fetchdat)
{
pclog("[%04X:%08X] Illegal instruction %08X (%02X)\n", CS, cpu_state.pc, fetchdat, fopcode);
cpu_state.pc = cpu_state.oldpc;
pclog("[%04X:%08X] Illegal instruction %08X (%02X)\n", CS, cpu_state.pc, fetchdat, fopcode);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 0;
x86illegal();
return 0;
}
#ifdef ENABLE_386_DYNAREC_LOG
extern void x386_dynarec_log(const char *fmt, ...);
extern void x386_dynarec_log(const char *fmt, ...);
#else
#ifndef x386_dynarec_log
#define x386_dynarec_log(fmt, ...)
#endif
# ifndef x386_dynarec_log
# define x386_dynarec_log(fmt, ...)
# endif
#endif
#include "x86seg.h"
@@ -196,9 +205,9 @@ extern void x386_dynarec_log(const char *fmt, ...);
#include "x86_ops_pmode.h"
#include "x86_ops_prefix.h"
#ifdef IS_DYNAREC
#include "x86_ops_rep_dyn.h"
# include "x86_ops_rep_dyn.h"
#else
#include "x86_ops_rep.h"
# include "x86_ops_rep.h"
#endif
#include "x86_ops_ret.h"
#include "x86_ops_set.h"
@@ -211,161 +220,164 @@ extern void x386_dynarec_log(const char *fmt, ...);
#include "x86_ops_3dnow.h"
#include <time.h>
static int opVPCEXT(uint32_t fetchdat)
static int
opVPCEXT(uint32_t fetchdat)
{
uint8_t b1, b2;
uint16_t cent;
time_t now;
struct tm *tm;
uint8_t b1, b2;
uint16_t cent;
time_t now;
struct tm *tm;
if (!is_vpc) /* only emulate this on Virtual PC machines */
return ILLEGAL(fetchdat);
if (!is_vpc) /* only emulate this on Virtual PC machines */
return ILLEGAL(fetchdat);
cpu_state.pc += 2;
cpu_state.pc += 2;
b1 = fetchdat & 0xff;
b2 = (fetchdat >> 8) & 0xff;
b1 = fetchdat & 0xff;
b2 = (fetchdat >> 8) & 0xff;
/* a lot of these opcodes (which?) return illegal instruction in user mode */
ILLEGAL_ON(CPL > 0);
/* a lot of these opcodes (which?) return illegal instruction in user mode */
ILLEGAL_ON(CPL > 0);
CLOCK_CYCLES(1);
CLOCK_CYCLES(1);
/* 0f 3f 03 xx opcodes are mostly related to the host clock, so fetch it now */
if (b1 == 0x03) {
(void)time(&now);
tm = localtime(&now);
}
/* 0f 3f 03 xx opcodes are mostly related to the host clock, so fetch it now */
if (b1 == 0x03) {
(void) time(&now);
tm = localtime(&now);
}
if ((b1 == 0x07) && (b2 == 0x0b)) {
/* 0f 3f 07 0b: unknown, EDX output depends on EAX input */
switch (EAX) {
case 0x00000000:
EDX = 0x00000003;
break;
if ((b1 == 0x07) && (b2 == 0x0b)) {
/* 0f 3f 07 0b: unknown, EDX output depends on EAX input */
switch (EAX) {
case 0x00000000:
EDX = 0x00000003;
break;
case 0x00000001:
EDX = 0x00000012;
break;
case 0x00000001:
EDX = 0x00000012;
break;
case 0x00000002:
case 0x00000003:
case 0x00000004:
case 0x00000005:
EDX = 0x00000001;
break;
case 0x00000002:
case 0x00000003:
case 0x00000004:
case 0x00000005:
EDX = 0x00000001;
break;
case 0x00000007:
EDX = 0x0000009c;
break;
case 0x00000007:
EDX = 0x0000009c;
break;
default:
EDX = 0x00000000;
if (EAX > 0x00000012) /* unknown EAX values set zero flag */
cpu_state.flags &= ~(Z_FLAG);
}
} else if ((b1 == 0x03) && (b2 == 0x00)) {
/* 0f 3f 03 00: host time in BCD */
EDX = BCD8(tm->tm_hour);
ECX = BCD8(tm->tm_min);
EAX = BCD8(tm->tm_sec);
} else if ((b1 == 0x03) && (b2 == 0x01)) {
/* 0f 3f 03 00: host date in BCD */
EDX = BCD8(tm->tm_year % 100);
ECX = BCD8(tm->tm_mon + 1);
EAX = BCD8(tm->tm_mday);
cent = (((tm->tm_year - (tm->tm_year % 100)) / 100) % 4); /* Sunday = 0 */
EBX = ((tm->tm_mday + tm->tm_mon + (tm->tm_year % 100) + cent + 3) % 7);
} else if ((b1 == 0x03) && (b2 == 0x03)) {
/* 0f 3f 03 03: host time in binary */
EDX = tm->tm_hour;
ECX = tm->tm_min;
EAX = tm->tm_sec;
} else if ((b1 == 0x03) && (b2 == 0x04)) {
/* 0f 3f 03 04: host date in binary */
EDX = 1900 + tm->tm_year;
ECX = tm->tm_mon + 1;
EBX = tm->tm_mday;
} else if ((b1 == 0x03) && (b2 == 0x05)) {
/* 0f 3f 03 05: unknown */
EBX = 0x0000000F;
ECX = 0x0000000A;
} else if ((b1 == 0x03) && (b2 == 0x06)) {
/* 0f 3f 03 06: some kind of timestamp. BX jumps around very quickly, CX not so much. */
EBX = 0x00000000;
ECX = 0x00000000;
} else if ((b1 == 0x03) && (b2 >= 0x07)) {
/* 0f 3f 03 07+: set zero flag */
cpu_state.flags &= ~(Z_FLAG);
} else if ((b1 == 0x0a) && (b2 == 0x00)) {
/* 0f 3f 0a 00: memory size in KB */
EAX = mem_size;
} else if ((b1 == 0x11) && (b2 == 0x00)) {
/* 0f 3f 11 00: unknown, set EAX to 0 */
EAX = 0x00000000;
} else if ((b1 == 0x11) && (b2 == 0x01)) {
/* 0f 3f 11 00: unknown, set EAX to 0 and set zero flag */
EAX = 0x00000000;
cpu_state.flags &= ~(Z_FLAG);
} else if ((b1 == 0x11) && (b2 == 0x02)) {
/* 0f 3f 11 02: unknown, no-op */
} else {
/* other unknown opcodes: illegal instruction */
cpu_state.pc = cpu_state.oldpc;
default:
EDX = 0x00000000;
if (EAX > 0x00000012) /* unknown EAX values set zero flag */
cpu_state.flags &= ~(Z_FLAG);
}
} else if ((b1 == 0x03) && (b2 == 0x00)) {
/* 0f 3f 03 00: host time in BCD */
EDX = BCD8(tm->tm_hour);
ECX = BCD8(tm->tm_min);
EAX = BCD8(tm->tm_sec);
} else if ((b1 == 0x03) && (b2 == 0x01)) {
/* 0f 3f 03 00: host date in BCD */
EDX = BCD8(tm->tm_year % 100);
ECX = BCD8(tm->tm_mon + 1);
EAX = BCD8(tm->tm_mday);
cent = (((tm->tm_year - (tm->tm_year % 100)) / 100) % 4); /* Sunday = 0 */
EBX = ((tm->tm_mday + tm->tm_mon + (tm->tm_year % 100) + cent + 3) % 7);
} else if ((b1 == 0x03) && (b2 == 0x03)) {
/* 0f 3f 03 03: host time in binary */
EDX = tm->tm_hour;
ECX = tm->tm_min;
EAX = tm->tm_sec;
} else if ((b1 == 0x03) && (b2 == 0x04)) {
/* 0f 3f 03 04: host date in binary */
EDX = 1900 + tm->tm_year;
ECX = tm->tm_mon + 1;
EBX = tm->tm_mday;
} else if ((b1 == 0x03) && (b2 == 0x05)) {
/* 0f 3f 03 05: unknown */
EBX = 0x0000000F;
ECX = 0x0000000A;
} else if ((b1 == 0x03) && (b2 == 0x06)) {
/* 0f 3f 03 06: some kind of timestamp. BX jumps around very quickly, CX not so much. */
EBX = 0x00000000;
ECX = 0x00000000;
} else if ((b1 == 0x03) && (b2 >= 0x07)) {
/* 0f 3f 03 07+: set zero flag */
cpu_state.flags &= ~(Z_FLAG);
} else if ((b1 == 0x0a) && (b2 == 0x00)) {
/* 0f 3f 0a 00: memory size in KB */
EAX = mem_size;
} else if ((b1 == 0x11) && (b2 == 0x00)) {
/* 0f 3f 11 00: unknown, set EAX to 0 */
EAX = 0x00000000;
} else if ((b1 == 0x11) && (b2 == 0x01)) {
/* 0f 3f 11 00: unknown, set EAX to 0 and set zero flag */
EAX = 0x00000000;
cpu_state.flags &= ~(Z_FLAG);
} else if ((b1 == 0x11) && (b2 == 0x02)) {
/* 0f 3f 11 02: unknown, no-op */
} else {
/* other unknown opcodes: illegal instruction */
cpu_state.pc = cpu_state.oldpc;
pclog("Illegal VPCEXT %08X (%02X %02X)\n", fetchdat, b1, b2);
x86illegal();
return 0;
}
pclog("Illegal VPCEXT %08X (%02X %02X)\n", fetchdat, b1, b2);
x86illegal();
return 0;
}
return 1;
return 1;
}
static int op0F_w_a16(uint32_t fetchdat)
static int
op0F_w_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
PREFETCH_PREFIX();
return x86_opcodes_0f[opcode](fetchdat >> 8);
return x86_opcodes_0f[opcode](fetchdat >> 8);
}
static int op0F_l_a16(uint32_t fetchdat)
static int
op0F_l_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
PREFETCH_PREFIX();
return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8);
return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8);
}
static int op0F_w_a32(uint32_t fetchdat)
static int
op0F_w_a32(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
PREFETCH_PREFIX();
return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8);
return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8);
}
static int op0F_l_a32(uint32_t fetchdat)
static int
op0F_l_a32(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
PREFETCH_PREFIX();
return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8);
return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8);
}
const OpFn OP_TABLE(186_0f)[1024] =
{
const OpFn OP_TABLE(186_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -453,10 +465,11 @@ const OpFn OP_TABLE(186_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(286_0f)[1024] =
{
const OpFn OP_TABLE(286_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -544,10 +557,11 @@ const OpFn OP_TABLE(286_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(386_0f)[1024] =
{
const OpFn OP_TABLE(386_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -635,10 +649,11 @@ const OpFn OP_TABLE(386_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(486_0f)[1024] =
{
const OpFn OP_TABLE(486_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -726,10 +741,11 @@ const OpFn OP_TABLE(486_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(c486_0f)[1024] =
{
const OpFn OP_TABLE(c486_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -817,10 +833,11 @@ const OpFn OP_TABLE(c486_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(stpc_0f)[1024] =
{
const OpFn OP_TABLE(stpc_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -908,10 +925,11 @@ const OpFn OP_TABLE(stpc_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(ibm486_0f)[1024] =
{
const OpFn OP_TABLE(ibm486_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -999,10 +1017,11 @@ const OpFn OP_TABLE(ibm486_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(winchip_0f)[1024] =
{
const OpFn OP_TABLE(winchip_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -1090,10 +1109,11 @@ const OpFn OP_TABLE(winchip_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(winchip2_0f)[1024] =
{
const OpFn OP_TABLE(winchip2_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
@@ -1181,10 +1201,11 @@ const OpFn OP_TABLE(winchip2_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(pentium_0f)[1024] =
{
const OpFn OP_TABLE(pentium_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -1272,11 +1293,12 @@ const OpFn OP_TABLE(pentium_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
const OpFn OP_TABLE(c6x86_0f)[1024] =
{
const OpFn OP_TABLE(c6x86_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -1364,11 +1386,12 @@ const OpFn OP_TABLE(c6x86_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
#endif
const OpFn OP_TABLE(pentiummmx_0f)[1024] =
{
const OpFn OP_TABLE(pentiummmx_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -1456,10 +1479,11 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(k6_0f)[1024] =
{
const OpFn OP_TABLE(k6_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -1547,10 +1571,11 @@ const OpFn OP_TABLE(k6_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(k62_0f)[1024] =
{
const OpFn OP_TABLE(k62_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
@@ -1638,11 +1663,12 @@ const OpFn OP_TABLE(k62_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
const OpFn OP_TABLE(c6x86mx_0f)[1024] =
{
const OpFn OP_TABLE(c6x86mx_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -1730,11 +1756,12 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
#endif
const OpFn OP_TABLE(pentiumpro_0f)[1024] =
{
const OpFn OP_TABLE(pentiumpro_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL,
@@ -1822,10 +1849,11 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] =
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(pentium2_0f)[1024] =
{
const OpFn OP_TABLE(pentium2_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL,
@@ -1913,10 +1941,11 @@ const OpFn OP_TABLE(pentium2_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(pentium2d_0f)[1024] =
{
const OpFn OP_TABLE(pentium2d_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL,
@@ -2004,10 +2033,11 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] =
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
const OpFn OP_TABLE(186)[1024] =
{
const OpFn OP_TABLE(186)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16,
@@ -2095,10 +2125,11 @@ const OpFn OP_TABLE(186)[1024] =
/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16,
/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX,
/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16,
// clang-format on
};
const OpFn OP_TABLE(286)[1024] =
{
const OpFn OP_TABLE(286)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16,
@@ -2186,10 +2217,11 @@ const OpFn OP_TABLE(286)[1024] =
/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16,
/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX,
/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16,
// clang-format on
};
const OpFn OP_TABLE(386)[1024] =
{
const OpFn OP_TABLE(386)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16,
@@ -2277,10 +2309,11 @@ const OpFn OP_TABLE(386)[1024] =
/*d0*/ opD0_a32, opD1_l_a32, opD2_a32, opD3_l_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32,
/*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX,
/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32,
// clang-format on
};
const OpFn OP_TABLE(REPE)[1024] =
{
const OpFn OP_TABLE(REPE)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -2368,10 +2401,11 @@ const OpFn OP_TABLE(REPE)[1024] =
/*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,
// clang-format on
};
const OpFn OP_TABLE(REPNE)[1024] =
{
const OpFn OP_TABLE(REPNE)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -2459,4 +2493,5 @@ const OpFn OP_TABLE(REPNE)[1024] =
/*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,
// clang-format on
};

View File

@@ -13,7 +13,6 @@
* Copyright 2022 Cacodemon345
*/
#include <stdint.h>
#include <stdlib.h>
#include "cpu.h"
@@ -38,15 +37,14 @@ clock_start(void)
cycdiff = cycles;
}
static void
clock_end(void)
{
int diff = cycdiff - cycles;
/* On 808x systems, clock speed is usually crystal frequency divided by an integer. */
tsc += (uint64_t)diff * ((uint64_t)xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
tsc += (uint64_t) diff * ((uint64_t) xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process();
}
@@ -73,7 +71,7 @@ readmemb(uint32_t a)
}
static uint8_t
ins_fetch(i8080* cpu)
ins_fetch(i8080 *cpu)
{
uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc);
@@ -83,22 +81,22 @@ ins_fetch(i8080* cpu)
#endif
void
transfer_from_808x(i8080* cpu)
transfer_from_808x(i8080 *cpu)
{
cpu->hl = BX;
cpu->bc = CX;
cpu->de = DX;
cpu->a = AL;
cpu->flags = cpu_state.flags & 0xFF;
cpu->sp = BP;
cpu->pc = cpu_state.pc;
cpu->oldpc = cpu_state.oldpc;
cpu->hl = BX;
cpu->bc = CX;
cpu->de = DX;
cpu->a = AL;
cpu->flags = cpu_state.flags & 0xFF;
cpu->sp = BP;
cpu->pc = cpu_state.pc;
cpu->oldpc = cpu_state.oldpc;
cpu->pmembase = cs;
cpu->dmembase = ds;
}
void
transfer_to_808x(i8080* cpu)
transfer_to_808x(i8080 *cpu)
{
BX = cpu->hl;
CX = cpu->bc;
@@ -106,7 +104,7 @@ transfer_to_808x(i8080* cpu)
AL = cpu->a;
cpu_state.flags &= 0xFF00;
cpu_state.flags |= cpu->flags & 0xFF;
BP = cpu->sp;
BP = cpu->sp;
cpu_state.pc = cpu->pc;
}
@@ -114,16 +112,31 @@ uint8_t
getreg_i8080(i8080 *cpu, uint8_t reg)
{
uint8_t ret = 0xFF;
switch(reg)
{
case 0x0: ret = cpu->b; break;
case 0x1: ret = cpu->c; break;
case 0x2: ret = cpu->d; break;
case 0x3: ret = cpu->e; break;
case 0x4: ret = cpu->h; break;
case 0x5: ret = cpu->l; break;
case 0x6: ret = cpu->readmembyte(cpu->dmembase + cpu->sp); break;
case 0x7: ret = cpu->a; break;
switch (reg) {
case 0x0:
ret = cpu->b;
break;
case 0x1:
ret = cpu->c;
break;
case 0x2:
ret = cpu->d;
break;
case 0x3:
ret = cpu->e;
break;
case 0x4:
ret = cpu->h;
break;
case 0x5:
ret = cpu->l;
break;
case 0x6:
ret = cpu->readmembyte(cpu->dmembase + cpu->sp);
break;
case 0x7:
ret = cpu->a;
break;
}
return ret;
}
@@ -132,16 +145,31 @@ uint8_t
getreg_i8080_emu(i8080 *cpu, uint8_t reg)
{
uint8_t ret = 0xFF;
switch(reg)
{
case 0x0: ret = CH; break;
case 0x1: ret = CL; break;
case 0x2: ret = DH; break;
case 0x3: ret = DL; break;
case 0x4: ret = BH; break;
case 0x5: ret = BL; break;
case 0x6: ret = cpu->readmembyte(cpu->dmembase + BP); break;
case 0x7: ret = AL; break;
switch (reg) {
case 0x0:
ret = CH;
break;
case 0x1:
ret = CL;
break;
case 0x2:
ret = DH;
break;
case 0x3:
ret = DL;
break;
case 0x4:
ret = BH;
break;
case 0x5:
ret = BL;
break;
case 0x6:
ret = cpu->readmembyte(cpu->dmembase + BP);
break;
case 0x7:
ret = AL;
break;
}
return ret;
}
@@ -149,57 +177,87 @@ getreg_i8080_emu(i8080 *cpu, uint8_t reg)
void
setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val)
{
switch(reg)
{
case 0x0: CH = val; break;
case 0x1: CL = val; break;
case 0x2: DH = val; break;
case 0x3: DL = val; break;
case 0x4: BH = val; break;
case 0x5: BL = val; break;
case 0x6: cpu->writemembyte(cpu->dmembase + BP, val); break;
case 0x7: AL = val; break;
switch (reg) {
case 0x0:
CH = val;
break;
case 0x1:
CL = val;
break;
case 0x2:
DH = val;
break;
case 0x3:
DL = val;
break;
case 0x4:
BH = val;
break;
case 0x5:
BL = val;
break;
case 0x6:
cpu->writemembyte(cpu->dmembase + BP, val);
break;
case 0x7:
AL = val;
break;
}
}
void
setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val)
{
switch(reg)
{
case 0x0: cpu->b = val; break;
case 0x1: cpu->c = val; break;
case 0x2: cpu->d = val; break;
case 0x3: cpu->e = val; break;
case 0x4: cpu->h = val; break;
case 0x5: cpu->l = val; break;
case 0x6: cpu->writemembyte(cpu->dmembase + cpu->sp, val); break;
case 0x7: cpu->a = val; break;
switch (reg) {
case 0x0:
cpu->b = val;
break;
case 0x1:
cpu->c = val;
break;
case 0x2:
cpu->d = val;
break;
case 0x3:
cpu->e = val;
break;
case 0x4:
cpu->h = val;
break;
case 0x5:
cpu->l = val;
break;
case 0x6:
cpu->writemembyte(cpu->dmembase + cpu->sp, val);
break;
case 0x7:
cpu->a = val;
break;
}
}
void
interpret_exec8080(i8080* cpu, uint8_t opcode)
interpret_exec8080(i8080 *cpu, uint8_t opcode)
{
switch (opcode) {
case 0x00:
{
break;
}
{
break;
}
}
}
/* Actually implement i8080 emulation. */
void
exec8080(i8080* cpu, int cycs)
exec8080(i8080 *cpu, int cycs)
{
#ifdef UNUSED_8080_VARS
uint8_t temp = 0, temp2;
uint8_t old_af;
uint8_t handled = 0;
uint8_t temp = 0, temp2;
uint8_t old_af;
uint8_t handled = 0;
uint16_t addr, tempw;
uint16_t new_ip;
int bits;
int bits;
#endif
cycles += cycs;
@@ -209,17 +267,18 @@ exec8080(i8080* cpu, int cycs)
if (!repeating) {
cpu->oldpc = cpu->pc;
opcode = cpu->fetchinstruction(cpu);
oldc = cpu->flags & C_FLAG_I8080;
opcode = cpu->fetchinstruction(cpu);
oldc = cpu->flags & C_FLAG_I8080;
i8080_wait(1, 0);
}
completed = 1;
if (completed) {
repeating = 0;
in_rep = 0;
repeating = 0;
in_rep = 0;
rep_c_flag = 0;
cpu->endclock();
if (cpu->checkinterrupts) cpu->checkinterrupts();
if (cpu->checkinterrupts)
cpu->checkinterrupts();
}
}
}

Some files were not shown because too many files have changed in this diff Show More