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