Renamed the three CPU folders to their final names.

This commit is contained in:
OBattler
2020-06-13 10:54:05 +02:00
parent 395537070b
commit 60ba71cb4b
197 changed files with 9 additions and 32694 deletions

772
src/codegen_new/codegen.c Normal file
View File

@@ -0,0 +1,772 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86_ops.h"
#include "codegen.h"
#include "x86.h"
#include "386_common.h"
#include "codegen_accumulate.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#define MAX_INSTRUCTION_COUNT 50
static struct
{
uint32_t pc;
int op_ssegs;
x86seg *op_ea_seg;
uint32_t op_32;
int first_uop;
int TOP;
} codegen_instructions[MAX_INSTRUCTION_COUNT];
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP)
{
int c;
for (c = 0; c < block->ins; c++)
{
if (codegen_instructions[c].pc == pc)
{
*first_instruction = c;
*TOP = codegen_instructions[c].TOP;
return codegen_instructions[c].first_uop;
}
}
*first_instruction = block->ins;
return -1;
}
void codegen_set_loop_start(ir_data_t *ir, int first_instruction)
{
uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32);
uop_MOV_PTR(ir, IREG_ea_seg, (void *)codegen_instructions[first_instruction].op_ea_seg);
uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs);
}
int has_ea;
codeblock_t *codeblock;
uint16_t *codeblock_hash;
void (*codegen_timing_start)();
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*codegen_timing_block_start)();
void (*codegen_timing_block_end)();
int (*codegen_timing_jump_cycles)();
void codegen_timing_set(codegen_timing_t *timing)
{
codegen_timing_start = timing->start;
codegen_timing_prefix = timing->prefix;
codegen_timing_opcode = timing->opcode;
codegen_timing_block_start = timing->block_start;
codegen_timing_block_end = timing->block_end;
codegen_timing_jump_cycles = timing->jump_cycles;
}
int codegen_in_recompile;
static int last_op_ssegs;
static x86seg *last_op_ea_seg;
static uint32_t last_op_32;
void codegen_generate_reset()
{
last_op_ssegs = -1;
last_op_ea_seg = NULL;
last_op_32 = -1;
has_ea = 0;
}
void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg)
{
/*Segments always valid in real/V86 mode*/
if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG))
return;
/*CS and SS must always be valid*/
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
return;
if (seg->checked)
return;
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
return;
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout);
seg->checked = 1;
}
void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg)
{
/*Segments always valid in real/V86 mode*/
if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG))
return;
/*CS and SS must always be valid*/
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
return;
if (seg->checked)
return;
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
return;
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout);
seg->checked = 1;
}
static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc)
{
uint32_t old_pc = (*op_pc) + 1;
if (!cpu_mod && cpu_rm == 6)
{
uint16_t addr = (fetchdat >> 8) & 0xffff;
uop_MOV_IMM(ir, IREG_eaaddr, addr);
(*op_pc) += 2;
}
else
{
int base_reg, index_reg, offset;
switch (cpu_rm & 7)
{
case 0: case 1: case 7:
base_reg = IREG_EBX;
break;
case 2: case 3: case 6:
base_reg = IREG_EBP;
break;
case 4:
base_reg = IREG_ESI;
break;
case 5:
base_reg = IREG_EDI;
break;
}
uop_MOV(ir, IREG_eaaddr, base_reg);
if (!(cpu_rm & 4))
{
if (!(cpu_rm & 1))
index_reg = IREG_ESI;
else
index_reg = IREG_EDI;
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg);
}
switch (cpu_mod)
{
case 1:
offset = (int)(int8_t)((fetchdat >> 8) & 0xff);
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset);
(*op_pc)++;
break;
case 2:
offset = (fetchdat >> 8) & 0xffff;
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset);
(*op_pc) += 2;
break;
}
uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff);
if (mod1seg[cpu_rm] == &ss && !op_ssegs)
{
op_ea_seg = &cpu_state.seg_ss;
}
}
codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-old_pc);
return op_ea_seg;
}
static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset)
{
codeblock_t *block = ir->block;
uint32_t old_pc = (*op_pc) + 1;
uint32_t new_eaaddr;
int extra_bytes = 0;
if (cpu_rm == 4)
{
uint8_t sib = fetchdat >> 8;
(*op_pc)++;
switch (cpu_mod)
{
case 0:
if ((sib & 7) == 5)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
extra_bytes = 1;
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
extra_bytes = 5;
}
(*op_pc) += 4;
}
else
{
uop_MOV(ir, IREG_eaaddr, sib & 7);
extra_bytes = 1;
}
break;
case 1:
new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
(*op_pc)++;
extra_bytes = 2;
break;
case 2:
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
extra_bytes = 1;
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
extra_bytes = 5;
}
(*op_pc) += 4;
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
break;
}
if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/
{
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset);
// addbyte(0x05);
// addlong(stack_offset);
}
if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs)
op_ea_seg = &cpu_state.seg_ss;
if (((sib >> 3) & 7) != 4)
{
switch (sib >> 6)
{
case 0:
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7);
break;
case 1:
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1);
break;
case 2:
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2);
break;
case 3:
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3);
break;
}
}
}
else
{
if (!cpu_mod && cpu_rm == 5)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
extra_bytes = 4;
}
(*op_pc) += 4;
}
else
{
uop_MOV(ir, IREG_eaaddr, cpu_rm);
if (cpu_mod)
{
if (cpu_rm == 5 && !op_ssegs)
op_ea_seg = &cpu_state.seg_ss;
if (cpu_mod == 1)
{
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8));
(*op_pc)++;
extra_bytes = 1;
}
else
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1);
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0);
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr);
extra_bytes = 4;
}
(*op_pc) += 4;
}
}
}
}
if (extra_bytes)
codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes);
return op_ea_seg;
}
x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset)
{
cpu_mod = (fetchdat >> 6) & 3;
cpu_reg = (fetchdat >> 3) & 7;
cpu_rm = fetchdat & 7;
if ((fetchdat & 0xc0) == 0xc0)
return NULL;
if (op_32 & 0x200)
return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset);
return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc);
}
static uint8_t opcode_modrm[256] =
{
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/
};
static uint8_t opcode_0f_modrm[256] =
{
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/
0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /*a0*/
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/
1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/
0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/
0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/
};
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc)
{
codeblock_t *block = &codeblock[block_current];
ir_data_t *ir = codegen_get_ir_data();
uint32_t op_pc = new_pc;
OpFn *op_table = (OpFn *) x86_dynarec_opcodes;
RecompOpFn *recomp_op_table = recomp_opcodes;
int opcode_shift = 0;
int opcode_mask = 0x3ff;
uint32_t recomp_opcode_mask = 0x1ff;
uint32_t op_32 = use32;
int over = 0;
int test_modrm = 1;
int pc_off = 0;
uint32_t next_pc = 0;
#ifdef DEBUG_EXTRA
uint8_t last_prefix = 0;
#endif
op_ea_seg = &cpu_state.seg_ds;
op_ssegs = 0;
codegen_timing_start();
while (!over)
{
switch (opcode)
{
case 0x0f:
#ifdef DEBUG_EXTRA
last_prefix = 0x0f;
#endif
op_table = (OpFn *) x86_dynarec_opcodes_0f;
recomp_op_table = recomp_opcodes_0f;
over = 1;
break;
case 0x26: /*ES:*/
op_ea_seg = &cpu_state.seg_es;
op_ssegs = 1;
break;
case 0x2e: /*CS:*/
op_ea_seg = &cpu_state.seg_cs;
op_ssegs = 1;
break;
case 0x36: /*SS:*/
op_ea_seg = &cpu_state.seg_ss;
op_ssegs = 1;
break;
case 0x3e: /*DS:*/
op_ea_seg = &cpu_state.seg_ds;
op_ssegs = 1;
break;
case 0x64: /*FS:*/
op_ea_seg = &cpu_state.seg_fs;
op_ssegs = 1;
break;
case 0x65: /*GS:*/
op_ea_seg = &cpu_state.seg_gs;
op_ssegs = 1;
break;
case 0x66: /*Data size select*/
op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200);
break;
case 0x67: /*Address size select*/
op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100);
break;
case 0xd8:
#ifdef DEBUG_EXTRA
last_prefix = 0xd8;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d8_a32 : (OpFn *) x86_dynarec_opcodes_d8_a16;
recomp_op_table = recomp_opcodes_d8;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xd9:
#ifdef DEBUG_EXTRA
last_prefix = 0xd9;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d9_a32 : (OpFn *) x86_dynarec_opcodes_d9_a16;
recomp_op_table = recomp_opcodes_d9;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xda:
#ifdef DEBUG_EXTRA
last_prefix = 0xda;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_da_a32 : (OpFn *) x86_dynarec_opcodes_da_a16;
recomp_op_table = recomp_opcodes_da;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdb:
#ifdef DEBUG_EXTRA
last_prefix = 0xdb;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_db_a32 : (OpFn *) x86_dynarec_opcodes_db_a16;
recomp_op_table = recomp_opcodes_db;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdc:
#ifdef DEBUG_EXTRA
last_prefix = 0xdc;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dc_a32 : (OpFn *) x86_dynarec_opcodes_dc_a16;
recomp_op_table = recomp_opcodes_dc;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdd:
#ifdef DEBUG_EXTRA
last_prefix = 0xdd;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dd_a32 : (OpFn *) x86_dynarec_opcodes_dd_a16;
recomp_op_table = recomp_opcodes_dd;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xde:
#ifdef DEBUG_EXTRA
last_prefix = 0xde;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_de_a32 : (OpFn *) x86_dynarec_opcodes_de_a16;
recomp_op_table = recomp_opcodes_de;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdf:
#ifdef DEBUG_EXTRA
last_prefix = 0xdf;
#endif
op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_df_a32 : (OpFn *) x86_dynarec_opcodes_df_a16;
recomp_op_table = recomp_opcodes_df;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xf0: /*LOCK*/
break;
case 0xf2: /*REPNE*/
#ifdef DEBUG_EXTRA
last_prefix = 0xf2;
#endif
op_table = (OpFn *) x86_dynarec_opcodes_REPNE;
recomp_op_table = NULL;//recomp_opcodes_REPNE;
break;
case 0xf3: /*REPE*/
#ifdef DEBUG_EXTRA
last_prefix = 0xf3;
#endif
op_table = (OpFn *) x86_dynarec_opcodes_REPE;
recomp_op_table = NULL;//recomp_opcodes_REPE;
break;
default:
goto generate_call;
}
fetchdat = fastreadl(cs + op_pc);
codegen_timing_prefix(opcode, fetchdat);
if (cpu_state.abrt)
return;
opcode = fetchdat & 0xff;
if (!pc_off)
fetchdat >>= 8;
op_pc++;
}
generate_call:
codegen_instructions[block->ins].pc = cpu_state.oldpc;
codegen_instructions[block->ins].op_ssegs = last_op_ssegs;
codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg;
codegen_instructions[block->ins].op_32 = last_op_32;
codegen_instructions[block->ins].TOP = cpu_state.TOP;
codegen_instructions[block->ins].first_uop = ir->wr_pos;
codegen_timing_opcode(opcode, fetchdat, op_32, op_pc);
codegen_accumulate(ACCREG_ins, 1);
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
codegen_block_cycles = 0;
if ((op_table == x86_dynarec_opcodes &&
((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 ||
(opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 ||
(opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) ||
(op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))
{
/*On some CPUs (eg K6), a jump/branch instruction may be able to pair with
subsequent instructions, so no cycles may have been deducted for it yet.
To prevent having zero cycle blocks (eg with a jump instruction pointing
to itself), apply the cycles that would be taken if this jump is taken,
then reverse it for subsequent instructions if the jump is not taken*/
int jump_cycles = codegen_timing_jump_cycles();
if (jump_cycles)
codegen_accumulate(ACCREG_cycles, -jump_cycles);
codegen_accumulate_flush(ir);
if (jump_cycles)
codegen_accumulate(ACCREG_cycles, jump_cycles);
}
if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f)
{
/*3DNow opcodes are stored after ModR/M, SIB and any offset*/
uint8_t modrm = fetchdat & 0xff;
uint8_t sib = (fetchdat >> 8) & 0xff;
uint32_t opcode_pc = op_pc + 1;
uint8_t opcode_3dnow;
if ((modrm & 0xc0) != 0xc0)
{
if (op_32 & 0x200)
{
if ((modrm & 7) == 4)
{
/* Has SIB*/
opcode_pc++;
if ((modrm & 0xc0) == 0x40)
opcode_pc++;
else if ((modrm & 0xc0) == 0x80)
opcode_pc += 4;
else if ((sib & 0x07) == 0x05)
opcode_pc += 4;
}
else
{
if ((modrm & 0xc0) == 0x40)
opcode_pc++;
else if ((modrm & 0xc0) == 0x80)
opcode_pc += 4;
else if ((modrm & 0xc7) == 0x05)
opcode_pc += 4;
}
}
else
{
if ((modrm & 0xc0) == 0x40)
opcode_pc++;
else if ((modrm & 0xc0) == 0x80)
opcode_pc += 2;
else if ((modrm & 0xc7) == 0x06)
opcode_pc += 2;
}
}
opcode_3dnow = fastreadb(cs + opcode_pc);
if (recomp_opcodes_3DNOW[opcode_3dnow])
{
next_pc = opcode_pc + 1;
op_table = (OpFn *) x86_dynarec_opcodes_3DNOW;
recomp_op_table = recomp_opcodes_3DNOW;
opcode = opcode_3dnow;
recomp_opcode_mask = 0xff;
opcode_mask = 0xff;
}
}
codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off);
/* It is apparently a prefixed instruction. */
if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask])
{
uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc);
if (new_pc)
{
if (new_pc != -1)
uop_MOV_IMM(ir, IREG_pc, new_pc);
codegen_endpc = (cs + cpu_state.pc) + 8;
block->ins++;
if (block->ins >= MAX_INSTRUCTION_COUNT)
CPU_BLOCK_END();
return;
}
}
if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32])
{
op_table = (OpFn *) x86_dynarec_opcodes;
recomp_op_table = recomp_opcodes;
}
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
if (!test_modrm ||
(op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) ||
(op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) ||
(op_table == x86_dynarec_opcodes_3DNOW))
{
int stack_offset = 0;
if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/
stack_offset = (op_32 & 0x100) ? 4 : 2;
cpu_mod = (fetchdat >> 6) & 3;
cpu_reg = (fetchdat >> 3) & 7;
cpu_rm = fetchdat & 7;
uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16));
op_pc += pc_off;
if (cpu_mod != 3 && !(op_32 & 0x200))
{
op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc);
}
if (cpu_mod != 3 && (op_32 & 0x200))
{
op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset);
}
op_pc -= pc_off;
}
#ifdef DEBUG_EXTRA
uop_LOG_INSTR(ir, opcode | (last_prefix << 8));
#endif
codegen_accumulate_flush(ir);
if (op_table == x86_dynarec_opcodes_3DNOW)
uop_MOV_IMM(ir, IREG_pc, next_pc);
else
uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off);
uop_MOV_IMM(ir, IREG_oldpc, old_pc);
if (op_32 != last_op_32)
uop_MOV_IMM(ir, IREG_op32, op_32);
if (op_ea_seg != last_op_ea_seg)
uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg);
if (op_ssegs != last_op_ssegs)
uop_MOV_IMM(ir, IREG_ssegs, op_ssegs);
uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat);
uop_CALL_INSTRUCTION_FUNC(ir, op);
codegen_mark_code_present(block, cs+cpu_state.pc, 8);
last_op_32 = op_32;
last_op_ea_seg = op_ea_seg;
last_op_ssegs = op_ssegs;
//codegen_block_ins++;
block->ins++;
if (block->ins >= MAX_INSTRUCTION_COUNT)
CPU_BLOCK_END();
codegen_endpc = (cs + cpu_state.pc) + 8;
// if (has_ea)
// fatal("Has EA\n");
}

417
src/codegen_new/codegen.h Normal file
View File

@@ -0,0 +1,417 @@
#ifndef _CODEGEN_H_
#define _CODEGEN_H_
#include <86box/mem.h>
#include <stddef.h>
#include "x86_ops.h"
/*Handling self-modifying code (of which there is a lot on x86) :
PCem tracks a 'dirty mask' for each physical page, in which each bit
represents 64 bytes. This is only tracked for pages that have code in - when a
page first has a codeblock generated, it is evicted from the writelookup and
added to the page_lookup for this purpose. When in the page_lookup, each write
will go through the mem_write_ram*_page() functions and set the dirty mask
appropriately.
Each codeblock also contains a code mask (actually two masks, one for each
page the block is/may be in), again with each bit representing 64 bytes.
Each page has a list of codeblocks present in it. As each codeblock can span
up to two pages, two lists are present.
When a codeblock is about to be executed, the code masks are compared with the
dirty masks for the relevant pages. If either intersect, then
codegen_check_flush() is called on the affected page(s), and all affected
blocks are evicted.
The 64 byte granularity appears to work reasonably well for most cases,
avoiding most unnecessary evictions (eg when code & data are stored in the
same page).
*/
typedef struct codeblock_t
{
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;
uint8_t *data;
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;
/*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;
extern uint16_t *codeblock_hash;
extern uint8_t *block_write_data;
/*Code block uses FPU*/
#define CODEBLOCK_HAS_FPU 1
/*Code block is always entered with the same FPU top-of-stack*/
#define CODEBLOCK_STATIC_TOP 2
/*Code block has been compiled*/
#define CODEBLOCK_WAS_RECOMPILED 4
/*Code block is in free list and is not valid*/
#define CODEBLOCK_IN_FREE_LIST 8
/*Code block spans two pages, page_mask2 and dirty_mask2 are valid*/
#define CODEBLOCK_HAS_PAGE2 0x10
/*Code block is using a byte mask for code present and dirty*/
#define CODEBLOCK_BYTE_MASK 0x20
/*Code block is in dirty list*/
#define CODEBLOCK_IN_DIRTY_LIST 0x40
/*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_INVALID 0
static inline int get_block_nr(codeblock_t *block)
{
return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t);
}
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
{
codeblock_t *block;
uint64_t a = _cs | ((uint64_t)phys << 32);
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;
}
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
old_block->right = get_block_nr(new_block);
new_block->parent = get_block_nr(old_block);
new_block->left = new_block->right = BLOCK_INVALID;
}
}
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)
{
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);
}
void codegen_init();
void codegen_close();
void codegen_reset();
void codegen_block_init(uint32_t phys_addr);
void codegen_block_remove();
void codegen_block_start_recompile(codeblock_t *block);
void codegen_block_end_recompile(codeblock_t *block);
void codegen_block_end();
void codegen_delete_block(codeblock_t *block);
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
void codegen_generate_seg_restore();
void codegen_set_op32();
void codegen_flush();
void codegen_check_flush(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);
void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
int codegen_purge_purgable_list();
/*Delete a random code block to free memory. This is obviously quite expensive, and
will only be called when the allocator is out of memory*/
void codegen_delete_random_block(int required_mem_block);
extern int cpu_block_end;
extern uint32_t codegen_endpc;
extern int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
extern int cpu_recomp_flushes, cpu_recomp_flushes_latched;
extern int cpu_recomp_evicted, cpu_recomp_evicted_latched;
extern int cpu_recomp_reuse, cpu_recomp_reuse_latched;
extern int cpu_recomp_removed, cpu_recomp_removed_latched;
extern int cpu_reps, cpu_reps_latched;
extern int cpu_notreps, cpu_notreps_latched;
extern int codegen_block_cycles;
extern void (*codegen_timing_start)();
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
extern void (*codegen_timing_block_start)();
extern void (*codegen_timing_block_end)();
extern int (*codegen_timing_jump_cycles)();
typedef struct codegen_timing_t
{
void (*start)();
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)();
void (*block_end)();
int (*jump_cycles)();
} codegen_timing_t;
extern codegen_timing_t codegen_timing_pentium;
extern codegen_timing_t codegen_timing_686;
extern codegen_timing_t codegen_timing_486;
extern codegen_timing_t codegen_timing_winchip;
extern codegen_timing_t codegen_timing_winchip2;
extern codegen_timing_t codegen_timing_k6;
extern codegen_timing_t codegen_timing_p6;
void codegen_timing_set(codegen_timing_t *timing);
extern int block_current;
extern int block_pos;
#define CPU_BLOCK_END() cpu_block_end = 1
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern uint32_t op_old_pc;
/*Set to 1 if flags have been changed in the block being recompiled, and hence
flags_op is known and can be relied on */
extern int codegen_flags_changed;
extern int codegen_fpu_entered;
extern int codegen_mmx_entered;
extern int codegen_fpu_loaded_iq[8];
extern int codegen_reg_loaded[8];
extern int codegen_in_recompile;
void codegen_generate_reset();
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];
#endif
#endif

View File

@@ -0,0 +1,46 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
static struct
{
int count;
int dest_reg;
} acc_regs[] =
{
[ACCREG_ins] = {0, IREG_ins},
[ACCREG_cycles] = {0, IREG_cycles},
};
void codegen_accumulate(int acc_reg, int delta)
{
acc_regs[acc_reg].count += delta;
}
void codegen_accumulate_flush(ir_data_t *ir)
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
{
if (acc_regs[c].count)
{
uop_ADD_IMM(ir, acc_regs[c].dest_reg, acc_regs[c].dest_reg, acc_regs[c].count);
}
acc_regs[c].count = 0;
}
}
void codegen_accumulate_reset()
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
acc_regs[c].count = 0;
}

View File

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

View File

@@ -0,0 +1,125 @@
#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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#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;
} 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;
int codegen_allocator_usage = 0;
void codegen_allocator_init()
{
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);
#else
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 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;
}
else
block->next = 0;
codegen_allocator_usage++;
return block;
}
void codegen_allocator_free(mem_block_t *block)
{
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;
}
}
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__
while (1)
{
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
if (block->next)
block = &mem_blocks[block->next - 1];
else
break;
}
#endif
}

View File

@@ -0,0 +1,39 @@
#ifndef _CODEGEN_ALLOCATOR_H_
#define _CODEGEN_ALLOCATOR_H_
/*The allocator handles all allocation of executable memory. Since the two-pass
recompiler design makes applying hard limits to codeblock size difficult, the
allocator allows memory to be provided as and when required.
The allocator provides a block size of a little under 1 kB (slightly lower to
limit cache aliasing). Each generated codeblock is allocated one block by default,
and will allocate additional block(s) once the existing memory is sorted. Blocks
are chained together by jump instructions.
Due to the chaining, the total memory size is limited by the range of a jump
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__ || _ARM_
#define MEM_BLOCK_NR 32768
#else
#define MEM_BLOCK_NR 131072
#endif
#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1)
#define MEM_BLOCK_SIZE 0x3c0
void codegen_allocator_init();
/*Allocate a mem_block_t, and the associated backing memory.
If parent is non-NULL, then the new block will be added to the list in
parent->next*/
struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent, int code_block);
/*Free a mem_block_t, and any subsequent blocks in the list at block->next*/
void codegen_allocator_free(struct mem_block_t *block);
/*Get a pointer to the backing memory associated with block*/
uint8_t *codeblock_allocator_get_ptr(struct mem_block_t *block);
/*Cache clean memory block list*/
void codegen_allocator_clean_blocks(struct mem_block_t *block);
extern int codegen_allocator_usage;
#endif

View File

@@ -0,0 +1,41 @@
#ifndef _CODEGEN_BACKEND_H_
#define _CODEGEN_BACKEND_H_
#if defined __amd64__
#include "codegen_backend_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
#include "codegen_backend_x86.h"
#elif defined __ARM_EABI__ || defined _ARM_
#include "codegen_backend_arm.h"
#elif defined __aarch64__
#include "codegen_backend_arm64.h"
#else
#error Dynamic recompiler not implemented on your platform
#endif
void codegen_backend_init();
void codegen_backend_prologue(codeblock_t *block);
void codegen_backend_epilogue(codeblock_t *block);
struct ir_data_t;
struct uop_t;
struct ir_data_t *codegen_get_ir_data();
typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
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;
} host_reg_def_t;
extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS];
extern host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];
#endif

View File

@@ -0,0 +1,370 @@
#if defined __ARM_EABI__ || defined _ARM_
#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"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
void *codegen_mem_store_double;
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_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)
{
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);
*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)
{
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);
*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)
{
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);
}
/*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)
static void build_fp_round_routine(codeblock_t *block)
{
uint32_t *jump_table;
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);
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_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_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()
{
codeblock_t *block;
int c;
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 *));
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]);
printf("block_pos=%i\n", block_pos);
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_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");
}
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;
}
/*R10 - cpu_state*/
void codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START;
/*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);
}
}
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);
codegen_allocator_clean_blocks(block->head_mem_block);
}
#endif

View File

@@ -0,0 +1,24 @@
#include "codegen_backend_arm_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_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);
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_call(codeblock_t *block, void *dst_addr);
void host_arm_nop(codeblock_t *block);
void codegen_alloc(codeblock_t *block, int size);

View File

@@ -0,0 +1,384 @@
#ifdef __aarch64__
#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"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
void *codegen_mem_store_double;
void *codegen_fp_round;
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_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)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
int 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);
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)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
int 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);
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)
{
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);
}
static void build_fp_round_routine(codeblock_t *block, int is_quad)
{
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);
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_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_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()
{
codeblock_t *block;
int c;
#if defined(__linux__) || defined(__APPLE__)
void *start;
size_t len;
long pagesize = sysconf(_SC_PAGESIZE);
long pagemask = ~(pagesize - 1);
#endif
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 *));
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);
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_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;
codegen_allocator_clean_blocks(block->head_mem_block);
asm("mrs %0, fpcr\n"
: "=r" (cpu_state.old_fp_control)
);
}
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;
}
/*R10 - cpu_state*/
void codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START;
/*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_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);
}
}
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);
codegen_allocator_clean_blocks(block->head_mem_block);
}
#endif

View File

@@ -0,0 +1,31 @@
#include "codegen_backend_arm64_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0
void host_arm64_BLR(codeblock_t *block, int addr_reg);
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
void host_arm64_NOP(codeblock_t *block);
void host_arm64_RET(codeblock_t *block, int reg);
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_call(codeblock_t *block, void *dst_addr);
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
uint32_t host_arm64_find_imm(uint32_t data);

View File

@@ -0,0 +1,135 @@
#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_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_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_TEMP REG_X7
#define REG_TEMP2 REG_X6
#define REG_V_TEMP REG_V0
#define CODEGEN_HOST_REGS 10
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_fp_round;
extern void *codegen_fp_round_quad;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,264 @@
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data);
void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset);
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_B(codeblock_t *block, void *dest);
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_BLR(codeblock_t *block, int addr_reg);
void host_arm64_BEQ(codeblock_t *block, void *dest);
uint32_t *host_arm64_BCC_(codeblock_t *block);
uint32_t *host_arm64_BCS_(codeblock_t *block);
uint32_t *host_arm64_BEQ_(codeblock_t *block);
uint32_t *host_arm64_BGE_(codeblock_t *block);
uint32_t *host_arm64_BGT_(codeblock_t *block);
uint32_t *host_arm64_BHI_(codeblock_t *block);
uint32_t *host_arm64_BLE_(codeblock_t *block);
uint32_t *host_arm64_BLS_(codeblock_t *block);
uint32_t *host_arm64_BLT_(codeblock_t *block);
uint32_t *host_arm64_BMI_(codeblock_t *block);
uint32_t *host_arm64_BNE_(codeblock_t *block);
uint32_t *host_arm64_BPL_(codeblock_t *block);
uint32_t *host_arm64_BVC_(codeblock_t *block);
uint32_t *host_arm64_BVS_(codeblock_t *block);
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest);
void host_arm64_BR(codeblock_t *block, int addr_reg);
void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
#define host_arm64_CMP_REG(block, src_n_reg, src_m_reg) host_arm64_CMP_REG_LSL(block, src_n_reg, src_m_reg, 0)
void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift);
void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element);
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg);
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg);
void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data);
void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg);
void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_NOP(codeblock_t *block);
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_RET(codeblock_t *block, int reg);
void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg);
void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift);
void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit);
#define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data)
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
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_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))
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
void codegen_alloc(codeblock_t *block, int size);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
#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_CPUSTATE REG_R10
#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_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_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_FP_REGS 8
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_fp_round;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,252 @@
#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)
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)
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_B(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BLX(codeblock_t *block, int addr_reg);
uint32_t *host_arm_BCC_(codeblock_t *block);
uint32_t *host_arm_BCS_(codeblock_t *block);
uint32_t *host_arm_BEQ_(codeblock_t *block);
uint32_t *host_arm_BGE_(codeblock_t *block);
uint32_t *host_arm_BGT_(codeblock_t *block);
uint32_t *host_arm_BHI_(codeblock_t *block);
uint32_t *host_arm_BLE_(codeblock_t *block);
uint32_t *host_arm_BLS_(codeblock_t *block);
uint32_t *host_arm_BLT_(codeblock_t *block);
uint32_t *host_arm_BMI_(codeblock_t *block);
uint32_t *host_arm_BNE_(codeblock_t *block);
uint32_t *host_arm_BPL_(codeblock_t *block);
uint32_t *host_arm_BVC_(codeblock_t *block);
uint32_t *host_arm_BVS_(codeblock_t *block);
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BX(codeblock_t *block, int addr_reg);
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm);
void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm);
#define host_arm_CMP_REG(block, src_reg_n, src_reg_m) host_arm_CMP_REG_LSL(block, src_reg_n, src_reg_m, 0)
void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset);
#define host_arm_LDR_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDR_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
void host_arm_LDRB_ABS(codeblock_t *block, int dst, void *p);
void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
#define host_arm_LDRB_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDRB_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg);
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
#define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0)
void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
#define host_arm_NOP(block) host_arm_MOV_REG(block, REG_R0, REG_R0)
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_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)
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);
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset);
#define host_arm_STR_REG(block, src_reg, addr_reg, offset_reg) host_arm_STR_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
#define host_arm_STRB_REG(block, src_reg, addr_reg, offset_reg) host_arm_STRB_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
void host_arm_STRH_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg);
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_TST_IMM(codeblock_t *block, int src_reg1, uint32_t imm);
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2);
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m);
void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm);
void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg);
void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high);
void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMRS_APSR(codeblock_t *block);
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg);
void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg);
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_S16(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_S32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_U16(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg);
void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg);
void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,391 @@
#ifdef __amd64__
#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"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
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_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)
{
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);
*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)
{
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);
*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)
{
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);
}
void codegen_backend_init()
{
codeblock_t *block;
int c;
#if defined(__linux__) || defined(__APPLE__)
void *start;
size_t len;
long pagesize = sysconf(_SC_PAGESIZE);
long pagemask = ~(pagesize - 1);
#endif
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 *));
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]);
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, (uintptr_t)x86gpf); */
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;
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)
{
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
}
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);
}
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);
}
#endif

View File

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

View File

@@ -0,0 +1,67 @@
/*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_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_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 CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 7
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,193 @@
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CALL(codeblock_t *block, void *p);
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_JMP(codeblock_t *block, void *p);
void host_x86_JNZ(codeblock_t *block, void *p);
void host_x86_JZ(codeblock_t *block, void *p);
uint8_t *host_x86_JNZ_short(codeblock_t *block);
uint8_t *host_x86_JS_short(codeblock_t *block);
uint8_t *host_x86_JZ_short(codeblock_t *block);
uint32_t *host_x86_JNB_long(codeblock_t *block);
uint32_t *host_x86_JNBE_long(codeblock_t *block);
uint32_t *host_x86_JNL_long(codeblock_t *block);
uint32_t *host_x86_JNLE_long(codeblock_t *block);
uint32_t *host_x86_JNO_long(codeblock_t *block);
uint32_t *host_x86_JNS_long(codeblock_t *block);
uint32_t *host_x86_JNZ_long(codeblock_t *block);
uint32_t *host_x86_JB_long(codeblock_t *block);
uint32_t *host_x86_JBE_long(codeblock_t *block);
uint32_t *host_x86_JL_long(codeblock_t *block);
uint32_t *host_x86_JLE_long(codeblock_t *block);
uint32_t *host_x86_JO_long(codeblock_t *block);
uint32_t *host_x86_JS_long(codeblock_t *block);
uint32_t *host_x86_JZ_long(codeblock_t *block);
void host_x86_LAHF(codeblock_t *block);
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset);
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg);
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift);
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale);
void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data);
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
void host_x86_NOP(codeblock_t *block);
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_POP(codeblock_t *block, int src_reg);
void host_x86_PUSH(codeblock_t *block, int src_reg);
void host_x86_RET(codeblock_t *block);
void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL32_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);

View File

@@ -0,0 +1,102 @@
#define JMP_LEN_BYTES 5
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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);
/*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;
}
}
static inline int is_imm8(uint32_t imm_data)
{
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
}

View File

@@ -0,0 +1,618 @@
#ifdef __amd64__
#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_sse.h"
#include "codegen_backend_x86-64_ops_helpers.h"
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
}
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
}
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
}
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
}
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
}
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
}
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
}
void host_x86_LDMXCSR(codeblock_t *block, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
}
else if (offset < (1ull << 32))
{
codegen_alloc_bytes(block, 7);
codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/
codegen_addlong(block, offset);
}
else
{
fatal("host_x86_LDMXCSR - out of range %p\n", p);
}
}
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/
}
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3));
}
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (src_reg & 8)
fatal("host_x86_MOVQ_ABS_REG reg & 8\n");
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p);
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addbyte(block, 0x25);
codegen_addlong(block, (uint32_t)(uintptr_t)p);
}
}
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
{
if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n");
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_RSP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset);
}
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (dst_reg & 8)
fatal("host_x86_MOVQ_REG_ABS reg & 8\n");
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p);
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addbyte(block, 0x25);
codegen_addlong(block, (uint32_t)(uintptr_t)p);
}
}
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
{
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n");
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset);
}
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
}
void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3));
}
void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
}
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
}
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
}
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/
}
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/
}
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/
}
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/
}
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/
}
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/
}
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/
}
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/
}
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/
}
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/
}
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/
}
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/
}
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/
}
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/
}
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/
}
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/
}
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/
}
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
}
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
}
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
}
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
}
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
}
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
}
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
}
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
}
#endif

View File

@@ -0,0 +1,114 @@
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
#define CMPPS_EQ 0
#define CMPPS_NLT 5
#define CMPPS_NLE 6
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_LDMXCSR(codeblock_t *block, void *p);
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,351 @@
#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 "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
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
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_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)
{
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);
*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)
{
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);
*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)
{
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);
}
void codegen_backend_init()
{
codeblock_t *block;
int c;
#if defined(__linux__) || defined(__APPLE__)
void *start;
size_t len;
long pagesize = sysconf(_SC_PAGESIZE);
long pagemask = ~(pagesize - 1);
#endif
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 *));
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);
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;
}
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);
}
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);
}
}
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);
}
#endif

View File

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

View File

@@ -0,0 +1,50 @@
#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_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 CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 6
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;
#define STACK_ARG0 (0)
#define STACK_ARG1 (4)
#define STACK_ARG2 (8)
#define STACK_ARG3 (12)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,192 @@
void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CALL(codeblock_t *block, void *p);
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
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);
uint32_t *host_x86_JMP_short(codeblock_t *block);
uint32_t *host_x86_JMP_long(codeblock_t *block);
void host_x86_JNZ(codeblock_t *block, void *p);
void host_x86_JZ(codeblock_t *block, void *p);
uint8_t *host_x86_JNZ_short(codeblock_t *block);
uint8_t *host_x86_JS_short(codeblock_t *block);
uint8_t *host_x86_JZ_short(codeblock_t *block);
uint32_t *host_x86_JNB_long(codeblock_t *block);
uint32_t *host_x86_JNBE_long(codeblock_t *block);
uint32_t *host_x86_JNL_long(codeblock_t *block);
uint32_t *host_x86_JNLE_long(codeblock_t *block);
uint32_t *host_x86_JNO_long(codeblock_t *block);
uint32_t *host_x86_JNS_long(codeblock_t *block);
uint32_t *host_x86_JNZ_long(codeblock_t *block);
uint32_t *host_x86_JB_long(codeblock_t *block);
uint32_t *host_x86_JBE_long(codeblock_t *block);
uint32_t *host_x86_JL_long(codeblock_t *block);
uint32_t *host_x86_JLE_long(codeblock_t *block);
uint32_t *host_x86_JO_long(codeblock_t *block);
uint32_t *host_x86_JS_long(codeblock_t *block);
uint32_t *host_x86_JZ_long(codeblock_t *block);
void host_x86_LAHF(codeblock_t *block);
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset);
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg);
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift);
void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_addr, uint32_t addr, int base_reg, int idx_reg, int shift);
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
#define host_x86_MOV16_STACK_REG(block, offset, src_reg) host_x86_MOV16_BASE_OFFSET_REG(block, REG_ESP, offset, src_reg)
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_POP(codeblock_t *block, int src_reg);
void host_x86_PUSH(codeblock_t *block, int src_reg);
void host_x86_RET(codeblock_t *block);
void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL32_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data);
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);

View File

@@ -0,0 +1,84 @@
#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 "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)
{
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)
{
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)
{
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);
}
}
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]*/
}
}
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]*/
}
}
#endif

View File

@@ -0,0 +1,5 @@
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg);
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg);
void host_x87_FLDCW(codeblock_t *block, void *p);
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg);
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg);

View File

@@ -0,0 +1,84 @@
#define JMP_LEN_BYTES 5
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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);
/*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;
}
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);
}
static inline int is_imm8(uint32_t imm_data)
{
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
}

View File

@@ -0,0 +1,578 @@
#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 "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops_sse.h"
#include "codegen_backend_x86_ops_helpers.h"
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
}
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
}
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
}
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
}
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
}
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
}
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/
}
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/
}
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
}
void host_x86_LDMXCSR(codeblock_t *block, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
}
else
{
codegen_alloc_bytes(block, 7);
codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/
}
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3));
}
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
codegen_alloc_bytes(block, 8);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
{
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset);
}
void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg)
{
if (!offset)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/
codegen_addbyte(block, 0x24);
}
else if (offset >= -0x80 && offset < 0x80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
codegen_addbyte2(block, 0x24, offset & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
codegen_addbyte(block, 0x24);
codegen_addlong(block, offset);
}
}
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
codegen_alloc_bytes(block, 8);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
{
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset);
}
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
}
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
}
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
}
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
}
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/
}
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/
}
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/
}
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/
}
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/
}
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/
}
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/
}
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/
}
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/
}
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/
}
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/
}
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/
}
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/
}
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/
}
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | src_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, shuffle);
}
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/
}
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/
}
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/
}
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
}
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
}
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
}
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
}
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
}
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
}
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
}
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
}
#endif

View File

@@ -0,0 +1,111 @@
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
#define CMPPS_EQ 0
#define CMPPS_NLT 5
#define CMPPS_NLE 6
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg);
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_LDMXCSR(codeblock_t *block, void *p);
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg);
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle);
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,863 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "x86_ops.h"
#include "x87.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_reg.h"
uint8_t *block_write_data = NULL;
int codegen_flat_ds, codegen_flat_ss;
int mmx_ebx_ecx_loaded;
int codegen_flags_changed = 0;
int codegen_fpu_entered = 0;
int codegen_mmx_entered = 0;
int codegen_fpu_loaded_iq[8];
x86seg *op_ea_seg;
int op_ssegs;
uint32_t op_old_pc;
uint32_t recomp_page = -1;
int block_current = 0;
static int block_num;
int block_pos;
int cpu_recomp_flushes, cpu_recomp_flushes_latched;
int cpu_recomp_evicted, cpu_recomp_evicted_latched;
int cpu_recomp_reuse, cpu_recomp_reuse_latched;
int cpu_recomp_removed, cpu_recomp_removed_latched;
uint32_t codegen_endpc;
int codegen_block_cycles;
static int codegen_block_ins;
static int codegen_block_full_ins;
static uint32_t last_op32;
static x86seg *last_ea_seg;
static int last_ssegs;
#ifdef DEBUG_EXTRA
uint32_t instr_counts[256*256];
#endif
static uint16_t block_free_list;
static void delete_block(codeblock_t *block);
static void delete_dirty_block(codeblock_t *block);
/*Temporary list of code blocks that have recently been evicted. This allows for
some historical state to be kept when a block is the target of self-modifying
code.
The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is
exceeded the oldest entry will be moved to the free list.*/
static uint16_t block_dirty_list_head, block_dirty_list_tail;
static int dirty_list_size = 0;
#define DIRTY_LIST_MAX_SIZE 64
static void block_free_list_add(codeblock_t *block)
{
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("block_free_list_add: block=%p in dirty list\n", block);
if (block_free_list)
block->next = block_free_list;
else
block->next = 0;
block_free_list = get_block_nr(block);
block->flags = CODEBLOCK_IN_FREE_LIST;
}
static void block_dirty_list_add(codeblock_t *block)
{
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("block_dirty_list_add: block=%p already in dirty list\n", block);
if (block_dirty_list_head != BLOCK_INVALID)
{
codeblock_t *old_head = &codeblock[block_dirty_list_head];
block->next = block_dirty_list_head;
block->prev = BLOCK_INVALID;
block_dirty_list_head = old_head->prev = get_block_nr(block);
}
else
{
/*List empty*/
block->prev = block->next = BLOCK_INVALID;
block_dirty_list_head = block_dirty_list_tail = get_block_nr(block);
}
block->flags |= CODEBLOCK_IN_DIRTY_LIST;
dirty_list_size++;
if (dirty_list_size > DIRTY_LIST_MAX_SIZE)
{
/*Evict oldest block to the free list*/
codeblock_t *evict_block = &codeblock[block_dirty_list_tail];
if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST))
fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags);
if (!block_dirty_list_tail)
fatal("block_dirty_list_add - !block_dirty_list_tail\n");
if (evict_block->prev == BLOCK_INVALID)
fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n");
block_dirty_list_tail = evict_block->prev;
codeblock[evict_block->prev].next = BLOCK_INVALID;
dirty_list_size--;
evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
delete_dirty_block(evict_block);
}
}
static void block_dirty_list_remove(codeblock_t *block)
{
codeblock_t *prev_block = &codeblock[block->prev];
codeblock_t *next_block = &codeblock[block->next];
if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST))
fatal("block_dirty_list_remove: block=%p not in dirty list\n", block);
/*Is block head of list*/
if (block->prev == BLOCK_INVALID)
block_dirty_list_head = block->next;
else
prev_block->next = block->next;
/*Is block tail of list?*/
if (block->next == BLOCK_INVALID)
block_dirty_list_tail = block->prev;
else
next_block->prev = block->prev;
dirty_list_size--;
if (dirty_list_size < 0)
fatal("remove - dirty_list_size < 0!\n");
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
}
int codegen_purge_purgable_list()
{
if (purgable_page_list_head)
{
page_t *page = &pages[purgable_page_list_head];
if (page->code_present_mask & page->dirty_mask)
{
codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12);
if (block_free_list)
return 1;
}
}
return 0;
}
static codeblock_t *block_free_list_get()
{
codeblock_t *block = NULL;
while (!block_free_list)
{
/*Free list is empty, check the dirty list*/
if (block_dirty_list_tail)
{
if (dirty_list_size <= 0)
fatal("get - dirty_list_size <= 0!\n");
/*Reuse oldest block*/
block = &codeblock[block_dirty_list_tail];
block_dirty_list_tail = block->prev;
if (block->prev == BLOCK_INVALID)
block_dirty_list_head = BLOCK_INVALID;
else
codeblock[block->prev].next = BLOCK_INVALID;
dirty_list_size--;
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
delete_dirty_block(block);
block_free_list = get_block_nr(block);
break;
}
/*Free list is empty - free up a block*/
if (!codegen_purge_purgable_list())
codegen_delete_random_block(0);
}
block = &codeblock[block_free_list];
block_free_list = block->next;
block->flags &= ~CODEBLOCK_IN_FREE_LIST;
block->next = 0;
return block;
}
void codegen_init()
{
int c;
codegen_allocator_init();
codegen_backend_init();
block_free_list = 0;
for (c = 0; c < BLOCK_SIZE; c++)
block_free_list_add(&codeblock[c]);
block_dirty_list_head = block_dirty_list_tail = 0;
dirty_list_size = 0;
#ifdef DEBUG_EXTRA
memset(instr_counts, 0, sizeof(instr_counts));
#endif
}
void codegen_close()
{
#ifdef DEBUG_EXTRA
pclog("Instruction counts :\n");
while (1)
{
int c;
uint32_t highest_num = 0, highest_idx = 0;
for (c = 0; c < 256*256; c++)
{
if (instr_counts[c] > highest_num)
{
highest_num = instr_counts[c];
highest_idx = c;
}
}
if (!highest_num)
break;
instr_counts[highest_idx] = 0;
if (highest_idx > 256)
pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num);
else
pclog(" %02x = %u\n", highest_idx & 0xff, highest_num);
}
#endif
}
void codegen_reset()
{
int c;
for (c = 1; c < BLOCK_SIZE; c++)
{
codeblock_t *block = &codeblock[c];
if (block->pc != BLOCK_PC_INVALID)
{
block->phys = 0;
block->phys_2 = 0;
delete_block(block);
}
}
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t));
mem_reset_page_blocks();
block_free_list = 0;
for (c = 0; c < BLOCK_SIZE; c++)
{
codeblock[c].pc = BLOCK_PC_INVALID;
block_free_list_add(&codeblock[c]);
}
}
void dump_block()
{
/* codeblock_t *block = pages[0x119000 >> 12].block;
pclog("dump_block:\n");
while (block)
{
uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff);
uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff);
pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next);
if (!block->pc)
fatal("Dead PC=0\n");
block = block->next;
}
pclog("dump_block done\n");*/
}
static void add_to_block_list(codeblock_t *block)
{
uint16_t block_prev_nr = pages[block->phys >> 12].block;
uint16_t block_nr = get_block_nr(block);
if (!block->page_mask)
fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2);
if (block_prev_nr)
{
block->next = block_prev_nr;
codeblock[block_prev_nr].prev = block_nr;
pages[block->phys >> 12].block = block_nr;
}
else
{
block->next = BLOCK_INVALID;
pages[block->phys >> 12].block = block_nr;
}
if (block->next)
{
if (codeblock[block->next].pc == BLOCK_PC_INVALID)
fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos);
}
if (block->page_mask2)
{
block->flags |= CODEBLOCK_HAS_PAGE2;
block_prev_nr = pages[block->phys_2 >> 12].block_2;
if (block_prev_nr)
{
block->next_2 = block_prev_nr;
codeblock[block_prev_nr].prev_2 = block_nr;
pages[block->phys_2 >> 12].block_2 = block_nr;
}
else
{
block->next_2 = BLOCK_INVALID;
pages[block->phys_2 >> 12].block_2 = block_nr;
}
}
}
static void remove_from_block_list(codeblock_t *block, uint32_t pc)
{
if (!block->page_mask)
return;
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("remove_from_block_list: in dirty list\n");
if (block->prev)
{
codeblock[block->prev].next = block->next;
if (block->next)
codeblock[block->next].prev = block->prev;
}
else
{
pages[block->phys >> 12].block = block->next;
if (block->next)
codeblock[block->next].prev = BLOCK_INVALID;
else
mem_flush_write_page(block->phys, 0);
}
if (!(block->flags & CODEBLOCK_HAS_PAGE2))
{
if (block->prev_2 || block->next_2)
fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys);
return;
}
block->flags &= ~CODEBLOCK_HAS_PAGE2;
if (block->prev_2)
{
codeblock[block->prev_2].next_2 = block->next_2;
if (block->next_2)
codeblock[block->next_2].prev_2 = block->prev_2;
}
else
{
pages[block->phys_2 >> 12].block_2 = block->next_2;
if (block->next_2)
codeblock[block->next_2].prev_2 = BLOCK_INVALID;
else
mem_flush_write_page(block->phys_2, 0);
}
}
static void invalidate_block(codeblock_t *block)
{
uint32_t old_pc = block->pc;
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("invalidate_block: already in dirty list\n");
if (block->pc == BLOCK_PC_INVALID)
fatal("Invalidating deleted block\n");
remove_from_block_list(block, old_pc);
block_dirty_list_add(block);
if (block->head_mem_block)
codegen_allocator_free(block->head_mem_block);
block->head_mem_block = NULL;
}
static void delete_block(codeblock_t *block)
{
uint32_t old_pc = block->pc;
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
if (block->pc == BLOCK_PC_INVALID)
fatal("Deleting deleted block\n");
block->pc = BLOCK_PC_INVALID;
codeblock_tree_delete(block);
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
block_dirty_list_remove(block);
else
remove_from_block_list(block, old_pc);
if (block->head_mem_block)
codegen_allocator_free(block->head_mem_block);
block->head_mem_block = NULL;
block_free_list_add(block);
}
static void delete_dirty_block(codeblock_t *block)
{
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
if (block->pc == BLOCK_PC_INVALID)
fatal("Deleting deleted block\n");
block->pc = BLOCK_PC_INVALID;
codeblock_tree_delete(block);
block_free_list_add(block);
}
void codegen_delete_block(codeblock_t *block)
{
if (block->pc != BLOCK_PC_INVALID)
delete_block(block);
}
void codegen_delete_random_block(int required_mem_block)
{
int block_nr = rand() & BLOCK_MASK;
while (1)
{
if (block_nr && block_nr != block_current)
{
codeblock_t *block = &codeblock[block_nr];
if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block))
{
delete_block(block);
return;
}
}
block_nr = (block_nr + 1) & BLOCK_MASK;
}
}
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
{
uint16_t block_nr = page->block;
int remove_from_evict_list = 0;
int c;
while (block_nr)
{
codeblock_t *block = &codeblock[block_nr];
uint16_t next_block = block->next;
if (*block->dirty_mask & block->page_mask)
{
invalidate_block(block);
cpu_recomp_evicted++;
}
if (block_nr == next_block)
fatal("Broken 1\n");
block_nr = next_block;
}
block_nr = page->block_2;
while (block_nr)
{
codeblock_t *block = &codeblock[block_nr];
uint16_t next_block = block->next_2;
if (*block->dirty_mask2 & block->page_mask2)
{
invalidate_block(block);
cpu_recomp_evicted++;
}
if (block_nr == next_block)
fatal("Broken 2\n");
block_nr = next_block;
}
if (page->code_present_mask & page->dirty_mask)
remove_from_evict_list = 1;
page->code_present_mask &= ~page->dirty_mask;
page->dirty_mask = 0;
for (c = 0; c < 64; c++)
{
if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c])
remove_from_evict_list = 0;
page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c];
page->byte_dirty_mask[c] = 0;
}
if (remove_from_evict_list)
page_remove_from_evict_list(page);
}
void codegen_block_init(uint32_t phys_addr)
{
codeblock_t *block;
page_t *page = &pages[phys_addr >> 12];
if (!page->block)
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
block = block_free_list_get();
if (!block)
fatal("codegen_block_init: block_free_list_get() returned NULL\n");
block_current = get_block_nr(block);
block_num = HASH(phys_addr);
codeblock_hash[block_num] = block_current;
block->ins = 0;
block->pc = cs + cpu_state.pc;
block->_cs = cs;
block->phys = phys_addr;
block->dirty_mask = &page->dirty_mask;
block->dirty_mask2 = NULL;
block->next = block->prev = BLOCK_INVALID;
block->next_2 = block->prev_2 = BLOCK_INVALID;
block->page_mask = block->page_mask2 = 0;
block->flags = CODEBLOCK_STATIC_TOP;
block->status = cpu_cur_status;
recomp_page = block->phys & ~0xfff;
codeblock_tree_add(block);
}
static ir_data_t *ir_data;
ir_data_t *codegen_get_ir_data()
{
return ir_data;
}
void codegen_block_start_recompile(codeblock_t *block)
{
page_t *page = &pages[block->phys >> 12];
if (!page->block)
mem_flush_write_page(block->phys, cs+cpu_state.pc);
block_num = HASH(block->phys);
block_current = get_block_nr(block);//block->pnt;
if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED))
fatal("Recompile to used block!\n");
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block->status = cpu_cur_status;
block->page_mask = block->page_mask2 = 0;
block->ins = 0;
cpu_block_end = 0;
last_op32 = -1;
last_ea_seg = NULL;
last_ssegs = -1;
codegen_block_cycles = 0;
codegen_timing_block_start();
codegen_block_ins = 0;
codegen_block_full_ins = 0;
recomp_page = block->phys & ~0xfff;
codegen_flags_changed = 0;
codegen_fpu_entered = 0;
codegen_mmx_entered = 0;
codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1;
block->TOP = cpu_state.TOP & 7;
block->flags |= CODEBLOCK_WAS_RECOMPILED;
codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);
codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS);
if (block->flags & CODEBLOCK_BYTE_MASK)
{
block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK];
block->dirty_mask2 = NULL;
}
ir_data = codegen_ir_init();
ir_data->block = block;
codegen_reg_reset();
codegen_accumulate_reset();
codegen_generate_reset();
}
void codegen_block_remove()
{
codeblock_t *block = &codeblock[block_current];
delete_block(block);
cpu_recomp_removed++;
recomp_page = -1;
}
void codegen_block_generate_end_mask_recompile()
{
codeblock_t *block = &codeblock[block_current];
page_t *p;
p = &pages[block->phys >> 12];
if (block->flags & CODEBLOCK_BYTE_MASK)
{
int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
p->byte_code_present_mask[offset] |= block->page_mask;
}
else
p->code_present_mask |= block->page_mask;
if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p))
page_add_to_evict_list(p);
block->phys_2 = -1;
block->next_2 = block->prev_2 = BLOCK_INVALID;
if (block->page_mask2)
{
block->phys_2 = get_phys_noabrt(codegen_endpc);
if (block->phys_2 != -1)
{
page_t *page_2 = &pages[block->phys_2 >> 12];
if (block->flags & CODEBLOCK_BYTE_MASK)
{
int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
page_2->byte_code_present_mask[offset] |= block->page_mask2;
block->dirty_mask2 = &page_2->byte_dirty_mask[offset];
}
else
{
page_2->code_present_mask |= block->page_mask2;
block->dirty_mask2 = &page_2->dirty_mask;
}
if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2))
page_add_to_evict_list(page_2);
if (!pages[block->phys_2 >> 12].block_2)
mem_flush_write_page(block->phys_2, codegen_endpc);
if (!block->page_mask2)
fatal("!page_mask2\n");
if (block->next_2)
{
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
}
}
else
{
/*Second page not present. page_mask2 is most likely set only because
the recompiler didn't know how long the last instruction was, so
clear it*/
block->page_mask2 = 0;
}
}
recomp_page = -1;
}
void codegen_block_generate_end_mask_mark()
{
codeblock_t *block = &codeblock[block_current];
uint32_t start_pc;
uint32_t end_pc;
page_t *p;
if (block->flags & CODEBLOCK_BYTE_MASK)
fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n");
block->page_mask = 0;
start_pc = (block->pc & 0xfff) & ~63;
if ((block->pc ^ codegen_endpc) & ~0xfff)
end_pc = 0xfff & ~63;
else
end_pc = (codegen_endpc & 0xfff) & ~63;
if (end_pc < start_pc)
end_pc = 0xfff;
start_pc >>= PAGE_MASK_SHIFT;
end_pc >>= PAGE_MASK_SHIFT;
for (; start_pc <= end_pc; start_pc++)
{
block->page_mask |= ((uint64_t)1 << start_pc);
}
p = &pages[block->phys >> 12];
p->code_present_mask |= block->page_mask;
if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p))
page_add_to_evict_list(p);
block->phys_2 = -1;
block->page_mask2 = 0;
block->next_2 = block->prev_2 = BLOCK_INVALID;
if ((block->pc ^ codegen_endpc) & ~0xfff)
{
block->phys_2 = get_phys_noabrt(codegen_endpc);
if (block->phys_2 != -1)
{
page_t *page_2 = &pages[block->phys_2 >> 12];
start_pc = 0;
end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT;
for (; start_pc <= end_pc; start_pc++)
block->page_mask2 |= ((uint64_t)1 << start_pc);
page_2->code_present_mask |= block->page_mask2;
if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2))
page_add_to_evict_list(page_2);
if (!pages[block->phys_2 >> 12].block_2)
mem_flush_write_page(block->phys_2, codegen_endpc);
if (!block->page_mask2)
fatal("!page_mask2\n");
if (block->next_2)
{
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
}
block->dirty_mask2 = &page_2->dirty_mask;
}
else
{
/*Second page not present. page_mask2 is most likely set only because
the recompiler didn't know how long the last instruction was, so
clear it*/
block->page_mask2 = 0;
}
}
recomp_page = -1;
}
void codegen_block_end()
{
codeblock_t *block = &codeblock[block_current];
codegen_block_generate_end_mask_mark();
add_to_block_list(block);
}
void codegen_block_end_recompile(codeblock_t *block)
{
codegen_timing_block_end();
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
block_dirty_list_remove(block);
else
remove_from_block_list(block, block->pc);
block->next = block->prev = BLOCK_INVALID;
block->next_2 = block->prev_2 = BLOCK_INVALID;
codegen_block_generate_end_mask_recompile();
add_to_block_list(block);
if (!(block->flags & CODEBLOCK_HAS_FPU))
block->flags &= ~CODEBLOCK_STATIC_TOP;
codegen_accumulate_flush(ir_data);
codegen_ir_compile(ir_data, block);
}
void codegen_flush()
{
return;
}
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len)
{
if (len)
{
uint32_t end_pc = start_pc + (len-1);
if (block->flags & CODEBLOCK_BYTE_MASK)
{
uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK;
uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK;
if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/
{
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
}
else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/
{
for (; start_pc_masked <= 63; start_pc_masked++)
block->page_mask |= ((uint64_t)1 << start_pc_masked);
for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++)
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
}
else /*First page only*/
{
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
block->page_mask |= ((uint64_t)1 << start_pc_masked);
}
}
else
{
uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT;
uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT;
start_pc_shifted &= PAGE_MASK_MASK;
end_pc_shifted &= PAGE_MASK_MASK;
if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/
{
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
}
else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/
{
for (; start_pc_shifted <= 63; start_pc_shifted++)
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
}
else /*First page only*/
{
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
}
}
}
}

View File

@@ -0,0 +1,188 @@
#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_ir.h"
#include "codegen_reg.h"
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()
{
ir_block.wr_pos = 0;
codegen_unroll_count = 0;
return &ir_block;
}
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;
}
static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset)
{
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);
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;
}
}
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;
for (c = codegen_unroll_start; c < unroll_end; c++)
{
duplicate_uop(ir, &ir->uops[c], offset);
}
}
}
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];
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_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->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_handlers[uop->type & UOP_MASK])
fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
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;
}
}
}
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");
}

View File

@@ -0,0 +1,6 @@
#include "codegen_ir_defs.h"
ir_data_t *codegen_ir_init();
void codegen_ir_set_unroll(int count, int start, int first_instruction);
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block);

View File

@@ -0,0 +1,810 @@
#ifndef _CODEGEN_IR_DEFS_
#define _CODEGEN_IR_DEFS_
#include "codegen_reg.h"
#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8))
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
All registers must have been written back or discarded.
This should be used when calling external functions that may change any emulated
registers.*/
#define UOP_TYPE_BARRIER (1 << 31)
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
All registers must have been written back, but do not have to be discarded.
This should be used when calling functions that preserve registers, but can cause
the code block to exit (eg memory load/store functions).*/
#define UOP_TYPE_ORDER_BARRIER (1 << 27)
/*uOP uses source and dest registers*/
#define UOP_TYPE_PARAMS_REGS (1 << 28)
/*uOP uses pointer*/
#define UOP_TYPE_PARAMS_POINTER (1 << 29)
/*uOP uses immediate data*/
#define UOP_TYPE_PARAMS_IMM (1 << 30)
/*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must
set jump_dest in the destination uOP to the address of the branch offset to be
written when known.*/
#define UOP_TYPE_JUMP (1 << 26)
/*uOP is the destination of a jump, and must set the destination offset of the jump
at compile time.*/
#define UOP_TYPE_JUMP_DEST (1 << 25)
#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00)
#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01)
#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02)
#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03)
#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER)
#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER)
#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER)
#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER)
#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER)
/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/
#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER)
#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12)
#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13)
/*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/
#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER)
/*UOP_JMP - jump to ptr*/
#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER)
/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/
#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER)
/*UOP_JMP_DEST - jump to ptr*/
#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18)
#ifdef DEBUG_EXTRA
/*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/
#define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f)
#endif
/*UOP_MOV_PTR - dest_reg = p*/
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
/*UOP_MOV_IMM - dest_reg = imm_data*/
#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21)
/*UOP_MOV - dest_reg = src_reg_a*/
#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22)
/*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/
#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23)
/*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/
#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24)
/*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/
#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25)
/*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26)
/*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27)
/*UOP_MOV_REG_PTR - dest_reg = *p*/
#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28)
/*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/
#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29)
/*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/
#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a)
/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/
#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31)
/*UOP_AND - dest_reg = src_reg_a & src_reg_b*/
#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32)
/*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/
#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33)
/*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data)
Intended for EA calcluations, imm_data must be between 0 and 3*/
#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34)
/*UOP_OR - dest_reg = src_reg_a | src_reg_b*/
#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35)
/*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/
#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36)
/*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/
#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37)
/*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/
#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38)
/*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/
#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39)
/*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/
#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a)
/*UOP_ANDN - dest_reg = ~src_reg_a & src_reg_b*/
#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b)
/*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/
#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/
#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/
#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/
#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/
#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/
#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/
#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_LOAD_SINGLE - dest_reg = (float)src_reg_a:[src_reg_b]*/
#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER)
/*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_LOAD_DOUBLE - dest_reg = (double)src_reg_a:[src_reg_b]*/
#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_SINGLE - src_reg_a:[src_reg_b] = src_reg_c*/
#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/
#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER)
/*UOP_CMP_JB - if (src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER)
/*UOP_CMP_JNBE - if (src_reg_a > src_reg_b) then jump to ptr*/
#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER)
/*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/
#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50)
/*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/
#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51)
/*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/
#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52)
/*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/
#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53)
/*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/
#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54)
/*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/
#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55)
/*UOP_ROL - dest_reg = src_reg_a rotate<< src_reg_b*/
#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56)
/*UOP_ROL_IMM - dest_reg = src_reg_a rotate<< immediate*/
#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57)
/*UOP_ROR - dest_reg = src_reg_a rotate>> src_reg_b*/
#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58)
/*UOP_ROR_IMM - dest_reg = src_reg_a rotate>> immediate*/
#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59)
/*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/
#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/
#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/
#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/
#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/
#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/
#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/
#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/
#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/
#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_FP_ENTER - must be called before any FPU register accessed*/
#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER)
/*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/
#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81)
/*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/
#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82)
/*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/
#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83)
/*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/
#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84)
/*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/
#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85)
/*UOP_FABS - dest_reg = fabs(src_reg_a)*/
#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86)
/*UOP_FCHS - dest_reg = fabs(src_reg_a)*/
#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87)
/*UOP_FTST - dest_reg = flags from compare(src_reg_a, 0)*/
#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88)
/*UOP_FSQRT - dest_reg = fsqrt(src_reg_a)*/
#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89)
/*UOP_MMX_ENTER - must be called before any MMX registers accessed*/
#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER)
/*UOP_PADDB - (packed byte) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91)
/*UOP_PADDW - (packed word) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92)
/*UOP_PADDD - (packed long) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93)
/*UOP_PADDSB - (packed byte with signed saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94)
/*UOP_PADDSW - (packed word with signed saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95)
/*UOP_PADDUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96)
/*UOP_PADDUSW - (packed word with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97)
/*UOP_PSUBB - (packed byte) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98)
/*UOP_PSUBW - (packed word) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99)
/*UOP_PSUBD - (packed long) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a)
/*UOP_PSUBSB - (packed byte with signed saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b)
/*UOP_PSUBSW - (packed word with signed saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c)
/*UOP_PSUBUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d)
/*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e)
/*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/
#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f)
/*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/
#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0)
/*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/
#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1)
/*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2)
/*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3)
/*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4)
/*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5)
/*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6)
/*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7)
/*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8)
/*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9)
/*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa)
/*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab)
/*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac)
/*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad)
/*UOP_PUNPCKLBW - (packed byte) dest_reg = interleave low src_reg_a/src_reg_b*/
#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae)
/*UOP_PUNPCKLWD - (packed word) dest_reg = interleave low src_reg_a/src_reg_b*/
#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf)
/*UOP_PUNPCKLDQ - (packed long) dest_reg = interleave low src_reg_a/src_reg_b*/
#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0)
/*UOP_PUNPCKHBW - (packed byte) dest_reg = interleave high src_reg_a/src_reg_b*/
#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1)
/*UOP_PUNPCKHWD - (packed word) dest_reg = interleave high src_reg_a/src_reg_b*/
#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2)
/*UOP_PUNPCKHDQ - (packed long) dest_reg = interleave high src_reg_a/src_reg_b*/
#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3)
/*UOP_PACKSSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with signed saturation*/
#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4)
/*UOP_PACKSSDW - dest_reg = interleave src_reg_a/src_reg_b, converting longs to words with signed saturation*/
#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5)
/*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/
#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6)
/*UOP_PMULLW - (packed word) dest_reg = (src_reg_a * src_reg_b) & 0xffff*/
#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7)
/*UOP_PMULHW - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8)
/*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9)
/*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba)
/*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb)
/*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/
#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc)
/*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/
#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd)
/*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/
#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe)
/*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf)
/*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/
#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0)
/*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1)
/*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/
#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2)
/*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/
#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3)
/*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/
#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4)
/*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/
#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5)
#define UOP_MAX 0xc6
#define UOP_INVALID 0xff
#define UOP_MASK 0xffff
typedef struct uop_t
{
uint32_t type;
ir_reg_t dest_reg_a;
ir_reg_t src_reg_a;
ir_reg_t src_reg_b;
ir_reg_t src_reg_c;
uint32_t imm_data;
void *p;
ir_host_reg_t dest_reg_a_real;
ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real;
int jump_dest_uop;
int jump_list_next;
void *jump_dest;
uint32_t pc;
} uop_t;
#define UOP_NR_MAX 4096
typedef struct ir_data_t
{
uop_t uops[UOP_NR_MAX];
int wr_pos;
struct codeblock_t *block;
} ir_data_t;
static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type)
{
uop_t *uop;
if (ir->wr_pos >= UOP_NR_MAX)
fatal("Exceeded uOP max\n");
uop = &ir->uops[ir->wr_pos++];
uop->dest_reg_a = invalid_ir_reg;
uop->src_reg_a = invalid_ir_reg;
uop->src_reg_b = invalid_ir_reg;
uop->src_reg_c = invalid_ir_reg;
uop->pc = cpu_state.oldpc;
uop->jump_dest_uop = -1;
uop->jump_list_next = -1;
if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))
codegen_reg_mark_as_required();
return uop;
}
static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop)
{
uop_t *uop = &ir->uops[jump_uop];
uop->jump_dest_uop = ir->wr_pos;
}
static inline int uop_gen(uint32_t uop_type, ir_data_t *ir)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
return ir->wr_pos-1;
}
static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
return ir->wr_pos-1;
}
static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
}
static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->imm_data = imm;
return ir->wr_pos-1;
}
static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->p = p;
}
static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
return ir->wr_pos-1;
}
static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->imm_data = imm;
}
static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
}
static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
uop->imm_data = imm;
}
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->imm_data = imm;
}
static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->p = p;
}
static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->p = p;
uop->imm_data = imm;
}
static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->p = p;
}
static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->p = p;
uop->imm_data = imm;
}
static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->p = p;
}
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm)
#define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift)
#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm)
#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm)
#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg)
#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg)
#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm)
#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg)
#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm)
#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg)
#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm)
#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg)
#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm)
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p)
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm)
#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm)
#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm)
#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p)
#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p)
#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b)
#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg)
#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg)
#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg)
#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg)
#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0)
#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0)
#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p)
#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir)
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm)
#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0)
#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset)
#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0)
#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0)
#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm)
#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0)
#define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset)
#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm)
#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm)
#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm)
#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0)
#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0)
#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg)
#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm)
#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p)
#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p)
#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p)
#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p)
#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg)
#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg)
#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg)
#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/)
#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag)
#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir)
#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg)
#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg)
#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg)
#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg)
#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg)
#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg)
#ifdef DEBUG_EXTRA
#define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm)
#endif
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_set_jump_dest(codeblock_t *block, void *p);
#endif

View File

@@ -0,0 +1,522 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_3dnow.h"
#include "codegen_ops_arith.h"
#include "codegen_ops_branch.h"
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_fpu_constant.h"
#include "codegen_ops_fpu_loadstore.h"
#include "codegen_ops_fpu_misc.h"
#include "codegen_ops_jump.h"
#include "codegen_ops_logic.h"
#include "codegen_ops_misc.h"
#include "codegen_ops_mmx_arith.h"
#include "codegen_ops_mmx_cmp.h"
#include "codegen_ops_mmx_loadstore.h"
#include "codegen_ops_mmx_logic.h"
#include "codegen_ops_mmx_pack.h"
#include "codegen_ops_mmx_shift.h"
#include "codegen_ops_mov.h"
#include "codegen_ops_shift.h"
#include "codegen_ops_stack.h"
RecompOpFn recomp_opcodes[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
/*10*/ ropADC_b_rmw, ropADC_w_rmw, ropADC_b_rm, ropADC_w_rm, ropADC_AL_imm, ropADC_AX_imm, ropPUSH_SS_16, NULL, ropSBB_b_rmw, ropSBB_w_rmw, ropSBB_b_rm, ropSBB_w_rm, ropSBB_AL_imm, ropSBB_AX_imm, ropPUSH_DS_16, ropPOP_DS_16,
/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL,
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
/*40*/ ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16,
/*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16,
/*60*/ ropPUSHA_16, ropPOPA_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W,
/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropCBW, ropCWD, NULL, NULL, ropPUSHF, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES_16, ropLDS_16, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, ropRETF_imm_16, ropRETF_16, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, ropJMP_far_16, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_16, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_16,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL,
/*10*/ ropADC_b_rmw, ropADC_l_rmw, ropADC_b_rm, ropADC_l_rm, ropADC_AL_imm, ropADC_EAX_imm, ropPUSH_SS_32, NULL, ropSBB_b_rmw, ropSBB_l_rmw, ropSBB_b_rm, ropSBB_l_rm, ropSBB_AL_imm, ropSBB_EAX_imm, ropPUSH_DS_32, ropPOP_DS_32,
/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL,
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
/*40*/ ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32,
/*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32,
/*60*/ ropPUSHA_32, ropPOPA_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L,
/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropCWDE, ropCDQ, NULL, NULL, ropPUSHFD, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES_32, ropLDS_32, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, ropRETF_imm_32, ropRETF_32, NULL, NULL, NULL, NULL,
/*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
};
RecompOpFn recomp_opcodes_0f[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q,
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r,
/*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
/*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,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q,
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r,
/*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
/*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,
};
RecompOpFn recomp_opcodes_3DNOW[256] =
{
/* 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, ropPI2FD, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPF2ID, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropPFCMPGE, NULL, NULL, NULL, ropPFMIN, NULL, ropPFRCP, ropPFRSQRT, NULL, NULL, ropPFSUB, NULL, NULL, NULL, ropPFADD, NULL,
/*a0*/ ropPFCMPGT, NULL, NULL, NULL, ropPFMAX, NULL, ropPFRCPIT, ropPFRSQIT1, NULL, NULL, ropPFSUBR, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropPFCMPEQ, NULL, NULL, NULL, ropPFMUL, NULL, ropPFRCPIT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_d8[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
};
RecompOpFn recomp_opcodes_d9[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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,
};
RecompOpFn recomp_opcodes_da[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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,
/*32-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,
/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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,
};
RecompOpFn recomp_opcodes_db[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_dc[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
};
RecompOpFn recomp_opcodes_dd[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ 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,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ 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,
};
RecompOpFn recomp_opcodes_de[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
};
RecompOpFn recomp_opcodes_df[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};

View File

@@ -0,0 +1,49 @@
#ifndef _CODEGEN_OPS_H_
#define _CODEGEN_OPS_H_
#include "codegen.h"
struct ir_data_t;
typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
extern RecompOpFn recomp_opcodes[512];
extern RecompOpFn recomp_opcodes_0f[512];
extern RecompOpFn recomp_opcodes_3DNOW[256];
extern RecompOpFn recomp_opcodes_d8[512];
extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_da[512];
extern RecompOpFn recomp_opcodes_db[512];
extern RecompOpFn recomp_opcodes_dc[512];
extern RecompOpFn recomp_opcodes_dd[512];
extern RecompOpFn recomp_opcodes_de[512];
extern RecompOpFn recomp_opcodes_df[512];
/*extern RecompOpFn recomp_opcodes_REPE[512];
extern RecompOpFn recomp_opcodes_REPNE[512];*/
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AL 0
#define REG_AH 4
#define REG_CL 1
#define REG_CH 5
#define REG_DL 2
#define REG_DH 6
#define REG_BL 3
#define REG_BH 7
#endif

View File

@@ -0,0 +1,211 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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; \
}
ropParith(PFADD)
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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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));
}
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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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);
}
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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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);
}
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)
{
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}

View File

@@ -0,0 +1,15 @@
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 ropPFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFCMPEQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFCMPGE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFCMPGT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFMAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFMIN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFMUL(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);
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 ropPFRSQRT(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);
uint32_t ropPFSUB(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);
uint32_t ropPI2FD(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

View File

@@ -0,0 +1,64 @@
uint32_t ropADC_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADC_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropADD_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMP_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSBB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSUB_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t rop80(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t rop81_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
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);
uint32_t ropINC_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropINC_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropINCDEC(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

View File

@@ -0,0 +1,69 @@
uint32_t ropJB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,575 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_helpers.h"
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
}
uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP2(block, ir);
return op_pc;
}
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
}
uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP2(block, ir);
return op_pc;
}
#define ropF_arith_mem(name, load_uop) \
uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
if ((cpu_state.npxc >> 10) & 3) \
return 0; \
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFCOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
\
return op_pc+1; \
} \
uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
fpu_POP(block, ir); \
\
return op_pc+1; \
} \
uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFSUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFSUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
}
ropF_arith_mem(s, uop_MEM_LOAD_SINGLE)
ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE)
#define ropFI_arith_mem(name, temp_reg) \
uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFICOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
\
return op_pc+1; \
} \
uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
fpu_POP(block, ir); \
\
return op_pc+1; \
} \
uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFIDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFIMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFISUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
}
ropFI_arith_mem(l, IREG_temp0)
ropFI_arith_mem(w, IREG_temp0_W)
uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FABS(ir, IREG_ST(0), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FCHS(ir, IREG_ST(0), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FSQRT(ir, IREG_ST(0), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FTST(ir, IREG_temp0_W, IREG_ST(0));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
}

View File

@@ -0,0 +1,63 @@
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIADDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIADDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIMULl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIMULw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,36 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
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;
}
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);
return op_pc;
}

View File

@@ -0,0 +1,2 @@
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 ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,234 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
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);
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)
{
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);
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)
{
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));
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)
{
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);
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)
{
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));
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
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);
return op_pc+1;
}

View File

@@ -0,0 +1,17 @@
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 ropFLDd(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);
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 ropFSTd(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);
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 ropFILDl(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);
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 ropFISTPw(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);
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 ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,114 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY);
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)
{
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);
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)
{
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));
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)
{
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);
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)
{
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);
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)
{
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);
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)
{
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_AX, IREG_NPXS);
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)
{
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);
return op_pc;
}

View File

@@ -0,0 +1,12 @@
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 ropFLD(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);
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 ropFSTCW(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);
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 ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,75 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ir_defs.h"
#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)
{
/*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)
{
/*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)
{
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);
/*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;
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6);
if (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);
return 1;
}

View File

@@ -0,0 +1,126 @@
#include "386_common.h"
#include "codegen_backend.h"
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;
}
}
}
static inline int LOAD_SP(ir_data_t *ir)
{
return LOAD_SP_WITH_OFFSET(ir, 0);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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;
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)
{
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)
{
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)
{
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)
{
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;
return codegen_can_unroll_full(block, ir, next_pc, dest_addr);
}

View File

@@ -0,0 +1,292 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
int32_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)
{
int32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
uint32_t dest_addr = op_pc+2+offset;
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_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int32_t offset = fastreadl(cs + op_pc);
uint32_t dest_addr = op_pc+4+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;
}
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)
{
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);
codegen_mark_code_present(block, cs+op_pc, 4);
return -1;
}
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 new_pc = fastreadl(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 4);
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;
}
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 = (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;
dest_addr &= 0xffff;
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 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 offset = fastreadl(cs + op_pc);
uint32_t ret_addr = op_pc + 4;
uint32_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);
codegen_mark_code_present(block, cs+op_pc, 4);
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)
{
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);
}
ADD_SP(ir, 2);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
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)
{
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);
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)
{
uint16_t offset = fastreadw(cs + 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);
}
ADD_SP(ir, 2+offset);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
codegen_mark_code_present(block, cs+op_pc, 2);
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)
{
uint16_t offset = fastreadw(cs + op_pc);
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);
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)
{
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
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);
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)
{
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
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);
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)
{
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_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;
}
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;
}

View File

@@ -0,0 +1,21 @@
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_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_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_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_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 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 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 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 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_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_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_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);
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_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,807 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_logic.h"
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, dest_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, dest_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}

View File

@@ -0,0 +1,36 @@
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,614 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_misc.h"
uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W);
return op_pc + 1;
}
uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr);
return op_pc + 1;
}
uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint8_t imm_data;
int reg;
if (fetchdat & 0x20)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
reg = IREG_8(fetchdat & 7);
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
reg = IREG_temp0_B;
}
switch (fetchdat & 0x38)
{
case 0x00: case 0x08: /*TEST*/
imm_data = fastreadb(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data);
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc+2;
case 0x10: /*NOT*/
uop_XOR_IMM(ir, reg, reg, 0xff);
if ((fetchdat & 0xc0) != 0xc0)
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
codegen_flags_changed = 1;
return op_pc+1;
case 0x18: /*NEG*/
uop_MOV_IMM(ir, IREG_temp1_B, 0);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op2, reg);
uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
uop_MOV(ir, reg, IREG_temp1_B);
}
else
{
uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8);
uop_MOV_IMM(ir, IREG_flags_op1, 0);
codegen_flags_changed = 1;
return op_pc+1;
}
return 0;
}
uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint16_t imm_data;
int reg;
if (fetchdat & 0x20)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
reg = IREG_16(fetchdat & 7);
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
reg = IREG_temp0_W;
}
switch (fetchdat & 0x38)
{
case 0x00: case 0x08: /*TEST*/
imm_data = fastreadw(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data);
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc+1, 2);
return op_pc+3;
case 0x10: /*NOT*/
uop_XOR_IMM(ir, reg, reg, 0xffff);
if ((fetchdat & 0xc0) != 0xc0)
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
codegen_flags_changed = 1;
return op_pc+1;
case 0x18: /*NEG*/
uop_MOV_IMM(ir, IREG_temp1_W, 0);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op2, reg);
uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
uop_MOV(ir, reg, IREG_temp1_W);
}
else
{
uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16);
uop_MOV_IMM(ir, IREG_flags_op1, 0);
codegen_flags_changed = 1;
return op_pc+1;
}
return 0;
}
uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint32_t imm_data;
int reg;
if (fetchdat & 0x20)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
reg = IREG_32(fetchdat & 7);
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
reg = IREG_temp0;
}
switch (fetchdat & 0x38)
{
case 0x00: case 0x08: /*TEST*/
imm_data = fastreadl(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_flags_res, reg, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc+1, 4);
return op_pc+5;
case 0x10: /*NOT*/
uop_XOR_IMM(ir, reg, reg, 0xffffffff);
if ((fetchdat & 0xc0) != 0xc0)
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
codegen_flags_changed = 1;
return op_pc+1;
case 0x18: /*NEG*/
uop_MOV_IMM(ir, IREG_temp1, 0);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_flags_op2, reg);
uop_SUB(ir, IREG_temp1, IREG_temp1, reg);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
uop_MOV(ir, reg, IREG_temp1);
}
else
{
uop_SUB(ir, IREG_temp1, IREG_temp1, reg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op2, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV_IMM(ir, IREG_flags_op1, 0);
codegen_flags_changed = 1;
return op_pc+1;
}
return 0;
}
static void rebuild_c(ir_data_t *ir)
{
int needs_rebuild = 1;
if (codegen_flags_changed)
{
switch (cpu_state.flags_op)
{
case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32:
case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32:
needs_rebuild = 0;
break;
}
}
if (needs_rebuild)
{
uop_CALL_FUNC(ir, flags_rebuild_c);
}
}
uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg, sp_reg;
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
if ((fetchdat & 0x38) == 0x28)
return 0;
src_reg = IREG_16(fetchdat & 7);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if (!(fetchdat & 0x30)) /*INC/DEC*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
src_reg = IREG_temp0_W;
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_ADD_IMM(ir, src_reg, src_reg, 1);
uop_MOVZX(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16);
}
else
{
uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16);
}
return op_pc+1;
case 0x08: /*DEC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_SUB_IMM(ir, src_reg, src_reg, 1);
uop_MOVZX(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16);
}
else
{
uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16);
}
return op_pc+1;
case 0x10: /*CALL*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1);
SUB_SP(ir, 2);
uop_MOVZX(ir, IREG_pc, src_reg);
return -1;
case 0x20: /*JMP*/
uop_MOVZX(ir, IREG_pc, src_reg);
return -1;
case 0x28: /*JMP far*/
uop_MOVZX(ir, IREG_pc, src_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1);
uop_CALL_FUNC(ir, loadcsjmp);
return -1;
case 0x30: /*PUSH*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg);
SUB_SP(ir, 2);
return op_pc+1;
}
return 0;
}
uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg, sp_reg;
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
if ((fetchdat & 0x38) == 0x28)
return 0;
src_reg = IREG_32(fetchdat & 7);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if (!(fetchdat & 0x30)) /*INC/DEC*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
src_reg = IREG_temp0;
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_ADD_IMM(ir, src_reg, src_reg, 1);
uop_MOV(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32);
}
else
{
uop_ADD_IMM(ir, IREG_temp1, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32);
}
return op_pc+1;
case 0x08: /*DEC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_SUB_IMM(ir, src_reg, src_reg, 1);
uop_MOV(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32);
}
else
{
uop_SUB_IMM(ir, IREG_temp1, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32);
}
return op_pc+1;
case 0x10: /*CALL*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1);
SUB_SP(ir, 4);
uop_MOV(ir, IREG_pc, src_reg);
return -1;
case 0x20: /*JMP*/
uop_MOV(ir, IREG_pc, src_reg);
return -1;
case 0x28: /*JMP far*/
uop_MOV(ir, IREG_pc, src_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1);
uop_CALL_FUNC(ir, loadcsjmp);
return -1;
case 0x30: /*PUSH*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg);
SUB_SP(ir, 4);
return op_pc+1;
}
return 0;
}
uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
return op_pc;
}
uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOVSX(ir, IREG_AX, IREG_AL);
return op_pc;
}
uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31);
return op_pc;
}
uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15);
return op_pc;
}
uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOVSX(ir, IREG_EAX, IREG_AX);
return op_pc;
}
#define ropLxS(name, seg) \
uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg = NULL; \
int dest_reg = (fetchdat >> 3) & 7; \
\
if ((fetchdat & 0xc0) == 0xc0) \
return 0; \
\
codegen_mark_code_present(block, cs+op_pc, 1); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \
\
if (seg == &cpu_state.seg_ss) \
CPU_BLOCK_END(); \
\
return op_pc + 1; \
} \
uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg = NULL; \
int dest_reg = (fetchdat >> 3) & 7; \
\
if ((fetchdat & 0xc0) == 0xc0) \
return 0; \
\
codegen_mark_code_present(block, cs+op_pc, 1); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \
\
if (seg == &cpu_state.seg_ss) \
CPU_BLOCK_END(); \
\
return op_pc + 1; \
}
ropLxS(LDS, &cpu_state.seg_ds)
ropLxS(LES, &cpu_state.seg_es)
ropLxS(LFS, &cpu_state.seg_fs)
ropLxS(LGS, &cpu_state.seg_gs)
ropLxS(LSS, &cpu_state.seg_ss)
uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_CALL_FUNC(ir, flags_rebuild);
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG);
return op_pc;
}
uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_CALL_FUNC(ir, flags_rebuild);
uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG);
return op_pc;
}
uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_CALL_FUNC(ir, flags_rebuild);
uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG);
return op_pc;
}
uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG);
return op_pc;
}
uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG);
return op_pc;
}
uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG);
return op_pc;
}
uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG);
return op_pc;
}

View File

@@ -0,0 +1,37 @@
uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLDS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLDS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLFS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLFS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLGS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLGS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLSS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLSS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,60 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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; \
}
ropParith(PADDB)
ropParith(PADDW)
ropParith(PADDD)
ropParith(PADDSB)
ropParith(PADDSW)
ropParith(PADDUSB)
ropParith(PADDUSW)
ropParith(PSUBB)
ropParith(PSUBW)
ropParith(PSUBD)
ropParith(PSUBSB)
ropParith(PSUBSW)
ropParith(PSUBUSB)
ropParith(PSUBUSW)
ropParith(PMADDWD)
ropParith(PMULHW)
ropParith(PMULLW)

View File

@@ -0,0 +1,19 @@
uint32_t ropPADDB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPMADDWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPMULHW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPMULLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,47 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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; \
}
ropPcmp(PCMPEQB)
ropPcmp(PCMPEQW)
ropPcmp(PCMPEQD)
ropPcmp(PCMPGTB)
ropPcmp(PCMPGTW)
ropPcmp(PCMPGTD)

View File

@@ -0,0 +1,6 @@
uint32_t ropPCMPEQB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPEQW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPEQD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPGTB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPGTW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPGTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,113 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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);
}
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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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));
}
return op_pc + 1;
}

View File

@@ -0,0 +1,5 @@
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_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 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_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,111 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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);
}
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)
{
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_MOV_IMM(ir, IREG_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;
}
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;
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);
}
return op_pc + 1;
}

View File

@@ -0,0 +1,4 @@
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 ropPANDN(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);
uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,50 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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; \
}
ropPpack(PACKSSWB)
ropPpack(PACKSSDW)
ropPpack(PACKUSWB)
ropPpack(PUNPCKLBW)
ropPpack(PUNPCKLWD)
ropPpack(PUNPCKLDQ)
ropPpack(PUNPCKHBW)
ropPpack(PUNPCKHWD)
ropPpack(PUNPCKHDQ)

View File

@@ -0,0 +1,9 @@
uint32_t ropPACKSSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPACKSSDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPACKUSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKLBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKLWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKLDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKHBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKHWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKHDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,96 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
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;
}
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)
{
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;
}
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)
{
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;
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}

View File

@@ -0,0 +1,7 @@
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 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 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 ropPSLLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSLLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSLLQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,773 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_mov.h"
uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm = fastreadb(cs + op_pc);
uop_MOV_IMM(ir, IREG_8(opcode & 7), imm);
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_16(opcode & 7), imm);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc);
}
else
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat);
codegen_mark_code_present(block, cs+op_pc, 4);
}
return op_pc + 4;
}
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg));
}
return op_pc + 1;
}
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg));
}
return op_pc + 1;
}
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg));
}
return op_pc + 1;
}
uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr = 0;
if (op_32 & 0x200)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc);
}
else
{
addr = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
}
}
else
{
addr = fastreadw(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 2);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200))
uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr);
else
uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uint8_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
imm = fastreadb(cs + op_pc + 1);
uop_MOV_IMM(ir, IREG_8(dest_reg), imm);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
imm = fastreadb(cs + op_pc + 1);
uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uint16_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
imm = fastreadw(cs + op_pc + 1);
uop_MOV_IMM(ir, IREG_16(dest_reg), imm);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
imm = fastreadw(cs + op_pc + 1);
uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 2);
return op_pc + 3;
}
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uint32_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
imm = fastreadl(cs + op_pc + 1);
uop_MOV_IMM(ir, IREG_32(dest_reg), imm);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
imm = fastreadl(cs + op_pc + 1);
uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 4);
return op_pc + 5;
}
uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
src_reg = IREG_ES_seg_W;
break;
case 0x08: /*CS*/
src_reg = IREG_CS_seg_W;
break;
case 0x18: /*DS*/
src_reg = IREG_DS_seg_W;
break;
case 0x10: /*SS*/
src_reg = IREG_SS_seg_W;
break;
case 0x20: /*FS*/
src_reg = IREG_FS_seg_W;
break;
case 0x28: /*GS*/
src_reg = IREG_GS_seg_W;
break;
default:
return 0;
}
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_16(dest_reg), src_reg);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg);
}
return op_pc + 1;
}
uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
src_reg = IREG_ES_seg_W;
break;
case 0x08: /*CS*/
src_reg = IREG_CS_seg_W;
break;
case 0x18: /*DS*/
src_reg = IREG_DS_seg_W;
break;
case 0x10: /*SS*/
src_reg = IREG_SS_seg_W;
break;
case 0x20: /*FS*/
src_reg = IREG_FS_seg_W;
break;
case 0x28: /*GS*/
src_reg = IREG_GS_seg_W;
break;
default:
return 0;
}
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), src_reg);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg);
}
return op_pc + 1;
}
uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg;
x86seg *rseg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
rseg = &cpu_state.seg_es;
break;
case 0x18: /*DS*/
rseg = &cpu_state.seg_ds;
break;
case 0x20: /*FS*/
rseg = &cpu_state.seg_fs;
break;
case 0x28: /*GS*/
rseg = &cpu_state.seg_gs;
break;
default:
return 0;
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7));
src_reg = IREG_temp0_W;
}
else
{
x86seg *target_seg;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
src_reg = IREG_temp0_W;
}
uop_LOAD_SEG(ir, rseg, src_reg);
return op_pc + 1;
}
uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W);
}
return op_pc + 1;
}
uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W);
}
return op_pc + 1;
}
uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg2 = IREG_16(opcode & 7);
uop_MOV(ir, IREG_temp0_W, IREG_AX);
uop_MOV(ir, IREG_AX, reg2);
uop_MOV(ir, reg2, IREG_temp0_W);
return op_pc;
}
uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg2 = IREG_32(opcode & 7);
uop_MOV(ir, IREG_temp0, IREG_EAX);
uop_MOV(ir, IREG_EAX, reg2);
uop_MOV(ir, reg2, IREG_temp0);
return op_pc;
}
uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg1 = IREG_8((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_8(fetchdat & 7);
uop_MOV(ir, IREG_temp0_B, reg1);
uop_MOV(ir, reg1, reg2);
uop_MOV(ir, reg2, IREG_temp0_B);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
uop_MOV(ir, reg1, IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg1 = IREG_16((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_16(fetchdat & 7);
uop_MOV(ir, IREG_temp0_W, reg1);
uop_MOV(ir, reg1, reg2);
uop_MOV(ir, reg2, IREG_temp0_W);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
uop_MOV(ir, reg1, IREG_temp0_W);
}
return op_pc + 1;
}
uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg1 = IREG_32((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_32(fetchdat & 7);
uop_MOV(ir, IREG_temp0, reg1);
uop_MOV(ir, reg1, reg2);
uop_MOV(ir, reg2, IREG_temp0);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
uop_MOV(ir, reg1, IREG_temp0);
}
return op_pc + 1;
}
uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOVZX(ir, IREG_eaaddr, IREG_AL);
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX);
if (!(op_32 & 0x200))
uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff);
uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr);
return op_pc;
}

View File

@@ -0,0 +1,43 @@
uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXLAT(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

View File

@@ -0,0 +1,16 @@
uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,412 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#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)
{
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);
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)
{
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);
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)
{
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_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);
}
if ((fetchdat & 0xc7) != (0xc0 | REG_SP))
ADD_SP(ir, 2);
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);
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;
}
#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)
ROP_PUSH_SEG(ES)
ROP_PUSH_SEG(FS)
ROP_PUSH_SEG(GS)
ROP_PUSH_SEG(SS)
ROP_POP_SEG(DS, cpu_state.seg_ds)
ROP_POP_SEG(ES, cpu_state.seg_es)
ROP_POP_SEG(FS, cpu_state.seg_fs)
ROP_POP_SEG(GS, cpu_state.seg_gs)
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);
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;
}
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);
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;
}
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;
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;
}
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;
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;
}
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;
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;
}
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;
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;
}
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;
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);
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)
{
int sp_reg;
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);
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;
}

View File

@@ -0,0 +1,49 @@
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_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_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_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_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 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 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);
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 ropPOP_W(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);
uint32_t ropPUSH_CS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_DS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_ES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_FS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_GS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_SS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_CS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_DS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_ES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_FS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_GS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUSH_SS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_DS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_ES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_FS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_GS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_DS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_ES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_FS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOP_GS_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_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_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_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_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_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_32(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);
uint32_t ropPUSHFD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View File

@@ -0,0 +1,767 @@
#include <stdint.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_ir_defs.h"
#include "codegen_reg.h"
int max_version_refcount;
uint16_t reg_dead_list = 0;
uint8_t reg_last_version[IREG_COUNT];
reg_version_t reg_version[IREG_COUNT][256];
ir_reg_t invalid_ir_reg = {IREG_INVALID};
ir_reg_t _host_regs[CODEGEN_HOST_REGS];
static uint8_t _host_reg_dirty[CODEGEN_HOST_REGS];
ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS];
static uint8_t host_fp_reg_dirty[CODEGEN_HOST_FP_REGS];
typedef struct host_reg_set_t
{
ir_reg_t *regs;
uint8_t *dirty;
host_reg_def_t *reg_list;
uint16_t locked;
int nr_regs;
} host_reg_set_t;
static host_reg_set_t host_reg_set, host_fp_reg_set;
enum
{
REG_BYTE,
REG_WORD,
REG_DWORD,
REG_QWORD,
REG_POINTER,
REG_DOUBLE,
REG_FPU_ST_BYTE,
REG_FPU_ST_DOUBLE,
REG_FPU_ST_QWORD
};
enum
{
REG_INTEGER,
REG_FP
};
enum
{
/*Register may be accessed outside of code block, and must be written
back before any control transfers*/
REG_PERMANENT = 0,
/*Register will not be accessed outside of code block, and does not need
to be written back if there are no readers remaining*/
REG_VOLATILE = 1
};
struct
{
int native_size;
void *p;
int type;
int is_volatile;
} ireg_data[IREG_COUNT] =
{
[IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT},
[IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT},
[IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT},
[IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT},
[IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT},
[IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT},
[IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT},
[IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT},
[IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT},
[IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT},
[IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT},
[IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT},
[IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT},
[IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT},
[IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT},
[IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT},
[IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT},
[IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT},
[IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT},
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER, REG_PERMANENT},
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT},
[IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT},
[IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT},
[IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT},
[IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT},
[IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT},
[IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT},
[IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT},
[IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT},
[IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT},
[IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT},
[IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT},
[IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT},
[IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT},
[IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
[IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
[IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
[IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT},
[IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT},
[IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT},
[IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT},
[IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT},
[IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT},
[IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT},
[IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT},
[IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT},
[IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT},
[IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT},
[IREG_CS_limit_low] = {REG_DWORD, &cpu_state.seg_cs.limit_low, REG_INTEGER, REG_PERMANENT},
[IREG_DS_limit_low] = {REG_DWORD, &cpu_state.seg_ds.limit_low, REG_INTEGER, REG_PERMANENT},
[IREG_ES_limit_low] = {REG_DWORD, &cpu_state.seg_es.limit_low, REG_INTEGER, REG_PERMANENT},
[IREG_FS_limit_low] = {REG_DWORD, &cpu_state.seg_fs.limit_low, REG_INTEGER, REG_PERMANENT},
[IREG_GS_limit_low] = {REG_DWORD, &cpu_state.seg_gs.limit_low, REG_INTEGER, REG_PERMANENT},
[IREG_SS_limit_low] = {REG_DWORD, &cpu_state.seg_ss.limit_low, REG_INTEGER, REG_PERMANENT},
[IREG_CS_limit_high] = {REG_DWORD, &cpu_state.seg_cs.limit_high, REG_INTEGER, REG_PERMANENT},
[IREG_DS_limit_high] = {REG_DWORD, &cpu_state.seg_ds.limit_high, REG_INTEGER, REG_PERMANENT},
[IREG_ES_limit_high] = {REG_DWORD, &cpu_state.seg_es.limit_high, REG_INTEGER, REG_PERMANENT},
[IREG_FS_limit_high] = {REG_DWORD, &cpu_state.seg_fs.limit_high, REG_INTEGER, REG_PERMANENT},
[IREG_GS_limit_high] = {REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT},
[IREG_SS_limit_high] = {REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT},
/*Temporary registers are stored on the stack, and are not guaranteed to
be preserved across uOPs. They will not be written back if they will
not be read again.*/
[IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER, REG_VOLATILE},
[IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER, REG_VOLATILE},
[IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER, REG_VOLATILE},
[IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER, REG_VOLATILE},
[IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP, REG_VOLATILE},
[IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE},
};
void codegen_reg_mark_as_required()
{
int reg;
for (reg = 0; reg < IREG_COUNT; reg++)
{
int last_version = reg_last_version[reg];
if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT)
reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED;
}
}
int reg_is_native_size(ir_reg_t ir_reg)
{
int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size;
int requested_size = IREG_GET_SIZE(ir_reg.reg);
switch (native_size)
{
case REG_BYTE: case REG_FPU_ST_BYTE:
return (requested_size == IREG_SIZE_B);
case REG_WORD:
return (requested_size == IREG_SIZE_W);
case REG_DWORD:
return (requested_size == IREG_SIZE_L);
case REG_QWORD: case REG_FPU_ST_QWORD: case REG_DOUBLE: case REG_FPU_ST_DOUBLE:
return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q));
case REG_POINTER:
if (sizeof(void *) == 4)
return (requested_size == IREG_SIZE_L);
return (requested_size == IREG_SIZE_Q);
default:
fatal("get_reg_is_native_size: unknown native size %i\n", native_size);
}
return 0;
}
void codegen_reg_reset()
{
int c;
host_reg_set.regs = _host_regs;
host_reg_set.dirty = _host_reg_dirty;
host_reg_set.reg_list = codegen_host_reg_list;
host_reg_set.locked = 0;
host_reg_set.nr_regs = CODEGEN_HOST_REGS;
host_fp_reg_set.regs = host_fp_regs;
host_fp_reg_set.dirty = host_fp_reg_dirty;
host_fp_reg_set.reg_list = codegen_host_fp_reg_list;
host_fp_reg_set.locked = 0;
host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS;
for (c = 0; c < IREG_COUNT; c++)
{
reg_last_version[c] = 0;
reg_version[c][0].refcount = 0;
}
for (c = 0; c < CODEGEN_HOST_REGS; c++)
{
host_reg_set.regs[c] = invalid_ir_reg;
host_reg_set.dirty[c] = 0;
}
for (c = 0; c < CODEGEN_HOST_FP_REGS; c++)
{
host_fp_reg_set.regs[c] = invalid_ir_reg;
host_fp_reg_set.dirty[c] = 0;
}
reg_dead_list = 0;
max_version_refcount = 0;
}
static inline int ir_get_refcount(ir_reg_t ir_reg)
{
return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount;
}
static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg)
{
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER)
return &host_reg_set;
else
return &host_fp_reg_set;
}
static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg)
{
switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size)
{
case REG_WORD:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_16_stack(block, reg_set->reg_list[c].reg, (int)(uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_16(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_DWORD:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_32_stack(block, reg_set->reg_list[c].reg, (int)(uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_32(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_QWORD:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_QWORD !REG_FP\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_64_stack(block, reg_set->reg_list[c].reg, (int)(uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_64(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_POINTER:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_pointer_stack(block, reg_set->reg_list[c].reg, (int)(uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_pointer(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_DOUBLE:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_double_stack(block, reg_set->reg_list[c].reg, (int)(uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_double(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_FPU_ST_BYTE:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n");
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_read_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[ir_reg.reg & 7]);
else
codegen_direct_read_st_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[0], ir_reg.reg & 7);
break;
case REG_FPU_ST_QWORD:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n");
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_read_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[ir_reg.reg & 7]);
else
codegen_direct_read_st_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[0], ir_reg.reg & 7);
break;
case REG_FPU_ST_DOUBLE:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n");
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_read_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[ir_reg.reg & 7]);
else
codegen_direct_read_st_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[0], ir_reg.reg & 7);
break;
default: fatal("codegen_reg_load - native_size=%i reg=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size, IREG_GET_REG(ir_reg.reg));
}
reg_set->regs[c] = ir_reg;
}
static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate)
{
int ir_reg = IREG_GET_REG(reg_set->regs[c].reg);
void *p = ireg_data[ir_reg].p;
if (!reg_version[ir_reg][reg_set->regs[c].version].refcount &&
ireg_data[ir_reg].is_volatile)
return;
switch (ireg_data[ir_reg].native_size)
{
case REG_BYTE:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_BYTE %p\n", p);
codegen_direct_write_8(block, p, reg_set->reg_list[c].reg);
break;
case REG_WORD:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_WORD %p\n", p);
codegen_direct_write_16(block, p, reg_set->reg_list[c].reg);
break;
case REG_DWORD:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n");
if ((uintptr_t)p < 256)
codegen_direct_write_32_stack(block, (int)(uintptr_t)p, reg_set->reg_list[c].reg);
else
codegen_direct_write_32(block, p, reg_set->reg_list[c].reg);
break;
case REG_QWORD:
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n");
if ((uintptr_t)p < 256)
codegen_direct_write_64_stack(block, (int)(uintptr_t)p, reg_set->reg_list[c].reg);
else
codegen_direct_write_64(block, p, reg_set->reg_list[c].reg);
break;
case REG_POINTER:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_POINTER %p\n", p);
codegen_direct_write_ptr(block, p, reg_set->reg_list[c].reg);
break;
case REG_DOUBLE:
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n");
if ((uintptr_t)p < 256)
codegen_direct_write_double_stack(block, (int)(uintptr_t)p, reg_set->reg_list[c].reg);
else
codegen_direct_write_double(block, p, reg_set->reg_list[c].reg);
break;
case REG_FPU_ST_BYTE:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n");
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg);
else
codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg);
break;
case REG_FPU_ST_QWORD:
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n");
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg);
else
codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg);
break;
case REG_FPU_ST_DOUBLE:
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n");
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg);
else
codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg);
break;
default:
fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size);
}
if (invalidate)
reg_set->regs[c] = invalid_ir_reg;
reg_set->dirty[c] = 0;
}
static void alloc_reg(ir_reg_t ir_reg)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS;
int c;
for (c = 0; c < nr_regs; c++)
{
if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
if (reg_set->regs[c].version != ir_reg.version)
fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg);
reg_set->locked |= (1 << c);
return;
}
}
}
static void alloc_dest_reg(ir_reg_t ir_reg, int dest_reference)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
int nr_regs = (reg_set == &host_reg_set) ? CODEGEN_HOST_REGS : CODEGEN_HOST_FP_REGS;
int c;
for (c = 0; c < nr_regs; c++)
{
if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
if (reg_set->regs[c].version == ir_reg.version)
{
reg_set->locked |= (1 << c);
}
else
{
/*The immediate prior version may have been
optimised out, so search backwards to find the
last valid version*/
int prev_version = ir_reg.version-1;
while (prev_version >= 0)
{
reg_version_t *regv = &reg_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version];
if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference)
{
reg_set->locked |= (1 << c);
return;
}
prev_version--;
}
fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference);
}
return;
}
}
}
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)
{
int dest_reference = 0;
host_reg_set.locked = 0;
host_fp_reg_set.locked = 0;
if (!ir_reg_is_invalid(dest_reg_a))
{
if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(src_reg_a.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_a.version == dest_reg_a.version-1)
dest_reference++;
if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1)
dest_reference++;
if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version-1)
dest_reference++;
}
if (!ir_reg_is_invalid(src_reg_a))
alloc_reg(src_reg_a);
if (!ir_reg_is_invalid(src_reg_b))
alloc_reg(src_reg_b);
if (!ir_reg_is_invalid(src_reg_c))
alloc_reg(src_reg_c);
if (!ir_reg_is_invalid(dest_reg_a))
alloc_dest_reg(dest_reg_a, dest_reference);
}
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
int c;
/*Search for required register*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version)
break;
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version)
{
reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++;
break;
}
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount)
fatal("codegen_reg_alloc_read_reg - version mismatch!\n");
}
if (c == reg_set->nr_regs)
{
/*No unused registers. Search for an unlocked register with no pending reads*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c]))
break;
}
if (c == reg_set->nr_regs)
{
/*Search for any unlocked register*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!(reg_set->locked & (1 << c)))
break;
}
if (c == reg_set->nr_regs)
fatal("codegen_reg_alloc_read_reg - out of registers\n");
}
if (reg_set->dirty[c])
codegen_reg_writeback(reg_set, block, c, 1);
codegen_reg_load(reg_set, block, c, ir_reg);
reg_set->locked |= (1 << c);
reg_set->dirty[c] = 0;
}
reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--;
if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t)-1)
fatal("codegen_reg_alloc_read_reg - refcount < 0\n");
if (host_reg_idx)
*host_reg_idx = c;
return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg);
}
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
int c;
if (!reg_is_native_size(ir_reg))
{
/*Read in parent register so we can do partial accesses to it*/
ir_reg_t parent_reg;
parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L;
parent_reg.version = ir_reg.version - 1;
reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++;
codegen_reg_alloc_read_reg(block, parent_reg, &c);
if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version-1)
fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c,
reg_set->regs[c].reg,reg_set->regs[c].version,
ir_reg.reg,ir_reg.version);
reg_set->regs[c].reg = ir_reg.reg;
reg_set->regs[c].version = ir_reg.version;
reg_set->dirty[c] = 1;
return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg);
}
/*Search for previous version in host register*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
if (reg_set->regs[c].version <= ir_reg.version-1)
{
if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0)
fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n");
break;
}
}
}
if (c == reg_set->nr_regs)
{
/*Search for unused registers*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (ir_reg_is_invalid(reg_set->regs[c]))
break;
}
if (c == reg_set->nr_regs)
{
/*No unused registers. Search for an unlocked register*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!(reg_set->locked & (1 << c)))
break;
}
if (c == reg_set->nr_regs)
fatal("codegen_reg_alloc_write_reg - out of registers\n");
if (reg_set->dirty[c])
codegen_reg_writeback(reg_set, block, c, 1);
}
}
reg_set->regs[c].reg = ir_reg.reg;
reg_set->regs[c].version = ir_reg.version;
reg_set->dirty[c] = 1;
return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg);
}
void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
{
host_reg_set_t *reg_set;
int c;
reg_set = &host_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c])
{
codegen_reg_writeback(reg_set, block, c, 0);
}
if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE)
{
reg_set->regs[c] = invalid_ir_reg;
reg_set->dirty[c] = 0;
}
}
reg_set = &host_fp_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c])
{
codegen_reg_writeback(reg_set, block, c, 0);
}
if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE)
{
reg_set->regs[c] = invalid_ir_reg;
reg_set->dirty[c] = 0;
}
}
}
void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block)
{
host_reg_set_t *reg_set;
int c;
reg_set = &host_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c])
{
codegen_reg_writeback(reg_set, block, c, 1);
}
reg_set->regs[c] = invalid_ir_reg;
reg_set->dirty[c] = 0;
}
reg_set = &host_fp_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c])
{
codegen_reg_writeback(reg_set, block, c, 1);
}
reg_set->regs[c] = invalid_ir_reg;
reg_set->dirty[c] = 0;
}
}
/*Process dead register list, and optimise out register versions and uOPs where
possible*/
void codegen_reg_process_dead_list(ir_data_t *ir)
{
while (reg_dead_list)
{
int version = reg_dead_list & 0xff;
int reg = reg_dead_list >> 8;
reg_version_t *regv = &reg_version[reg][version];
uop_t *uop = &ir->uops[regv->parent_uop];
/*Barrier uOPs should be preserved*/
if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)))
{
uop->type = UOP_INVALID;
/*Adjust refcounts on source registers. If these drop to
zero then those registers can be considered for removal*/
if (uop->src_reg_a.reg != IREG_INVALID)
{
reg_version_t *src_regv = &reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version];
src_regv->refcount--;
if (!src_regv->refcount)
add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version);
}
if (uop->src_reg_b.reg != IREG_INVALID)
{
reg_version_t *src_regv = &reg_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version];
src_regv->refcount--;
if (!src_regv->refcount)
add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version);
}
if (uop->src_reg_c.reg != IREG_INVALID)
{
reg_version_t *src_regv = &reg_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version];
src_regv->refcount--;
if (!src_regv->refcount)
add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version);
}
regv->flags |= REG_FLAGS_DEAD;
}
reg_dead_list = regv->next;
}
}

View File

@@ -0,0 +1,402 @@
#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_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)
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_pc = 12,
IREG_oldpc = 13,
IREG_eaaddr = 14,
IREG_ea_seg = 15,
IREG_op32 = 16,
IREG_ssegsx = 17,
IREG_rm_mod_reg = 18,
IREG_ins = 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_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,
IREG_FPU_TOP = 37,
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,
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_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_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_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_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_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_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_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_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_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_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_ssegs = IREG_ssegsx + IREG_SIZE_B,
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_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_TOP_diff_stack_offset 32
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;
}
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;
}
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;
}
extern uint8_t reg_last_version[IREG_COUNT];
/*This version of the register must be calculated, regardless of whether it is
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)
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;
} reg_version_t;
extern reg_version_t reg_version[IREG_COUNT][256];
/*Head of dead register list; a list of register versions that are not used and
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)
{
regv->next = reg_dead_list;
reg_dead_list = version | (reg << 8);
}
typedef struct
{
uint16_t reg;
uint16_t version;
} ir_reg_t;
extern ir_reg_t invalid_ir_reg;
typedef uint16_t ir_host_reg_t;
extern int max_version_refcount;
#define REG_VERSION_MAX 250
#define REG_REFCOUNT_MAX 250
static inline ir_reg_t codegen_reg_read(int reg)
{
ir_reg_t ireg;
reg_version_t *version;
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_read - IREG_INVALID\n");
ireg.reg = reg;
ireg.version = reg_last_version[IREG_GET_REG(reg)];
version = &reg_version[IREG_GET_REG(ireg.reg)][ireg.version];
version->flags = 0;
version->refcount++;
if (!version->refcount)
fatal("codegen_reg_read - refcount overflow\n");
else if (version->refcount > REG_REFCOUNT_MAX)
CPU_BLOCK_END();
if (version->refcount > max_version_refcount)
max_version_refcount = version->refcount;
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)
{
ir_reg_t ireg;
int last_version = reg_last_version[IREG_GET_REG(reg)];
reg_version_t *version;
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_write - IREG_INVALID\n");
ireg.reg = reg;
ireg.version = last_version + 1;
if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount &&
!(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED))
{
if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/
add_to_dead_list(&reg_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version);
}
reg_last_version[IREG_GET_REG(reg)]++;
if (!reg_last_version[IREG_GET_REG(reg)])
fatal("codegen_reg_write - version overflow\n");
else 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)];
version = &reg_version[IREG_GET_REG(reg)][ireg.version];
version->refcount = 0;
version->flags = 0;
version->parent_uop = uop_nr;
return ireg;
}
static inline int ir_reg_is_invalid(ir_reg_t ir_reg)
{
return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID);
}
struct ir_data_t;
void codegen_reg_reset();
/*Write back all dirty registers*/
void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block);
/*Write back and evict all registers*/
void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block);
/*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c);
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx);
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg);
void codegen_reg_mark_as_required();
void codegen_reg_process_dead_list(struct ir_data_t *ir);
#endif

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

630
src/codegen_new/x86_flags.h Normal file
View File

@@ -0,0 +1,630 @@
extern int tempc;
enum
{
FLAGS_UNKNOWN,
FLAGS_ZN8,
FLAGS_ZN16,
FLAGS_ZN32,
FLAGS_ADD8,
FLAGS_ADD16,
FLAGS_ADD32,
FLAGS_SUB8,
FLAGS_SUB16,
FLAGS_SUB32,
FLAGS_SHL8,
FLAGS_SHL16,
FLAGS_SHL32,
FLAGS_SHR8,
FLAGS_SHR16,
FLAGS_SHR32,
FLAGS_SAR8,
FLAGS_SAR16,
FLAGS_SAR32,
FLAGS_ROL8,
FLAGS_ROL16,
FLAGS_ROL32,
FLAGS_ROR8,
FLAGS_ROR16,
FLAGS_ROR32,
FLAGS_INC8,
FLAGS_INC16,
FLAGS_INC32,
FLAGS_DEC8,
FLAGS_DEC16,
FLAGS_DEC32,
FLAGS_ADC8,
FLAGS_ADC16,
FLAGS_ADC32,
FLAGS_SBC8,
FLAGS_SBC16,
FLAGS_SBC32
};
static inline int ZF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
case FLAGS_ADC8:
case FLAGS_ADC16:
case FLAGS_ADC32:
case FLAGS_SBC8:
case FLAGS_SBC16:
case FLAGS_SBC32:
return !cpu_state.flags_res;
case FLAGS_ROL8:
case FLAGS_ROL16:
case FLAGS_ROL32:
case FLAGS_ROR8:
case FLAGS_ROR16:
case FLAGS_ROR32:
case FLAGS_UNKNOWN:
return cpu_state.flags & Z_FLAG;
}
return 0;
}
static inline int NF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ADD8:
case FLAGS_SUB8:
case FLAGS_SHL8:
case FLAGS_SHR8:
case FLAGS_SAR8:
case FLAGS_INC8:
case FLAGS_DEC8:
case FLAGS_ADC8:
case FLAGS_SBC8:
return cpu_state.flags_res & 0x80;
case FLAGS_ZN16:
case FLAGS_ADD16:
case FLAGS_SUB16:
case FLAGS_SHL16:
case FLAGS_SHR16:
case FLAGS_SAR16:
case FLAGS_INC16:
case FLAGS_DEC16:
case FLAGS_ADC16:
case FLAGS_SBC16:
return cpu_state.flags_res & 0x8000;
case FLAGS_ZN32:
case FLAGS_ADD32:
case FLAGS_SUB32:
case FLAGS_SHL32:
case FLAGS_SHR32:
case FLAGS_SAR32:
case FLAGS_INC32:
case FLAGS_DEC32:
case FLAGS_ADC32:
case FLAGS_SBC32:
return cpu_state.flags_res & 0x80000000;
case FLAGS_ROL8:
case FLAGS_ROL16:
case FLAGS_ROL32:
case FLAGS_ROR8:
case FLAGS_ROR16:
case FLAGS_ROR32:
case FLAGS_UNKNOWN:
return cpu_state.flags & N_FLAG;
}
return 0;
}
static inline int PF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
case FLAGS_ADC8:
case FLAGS_ADC16:
case FLAGS_ADC32:
case FLAGS_SBC8:
case FLAGS_SBC16:
case FLAGS_SBC32:
return znptable8[cpu_state.flags_res & 0xff] & P_FLAG;
case FLAGS_ROL8:
case FLAGS_ROL16:
case FLAGS_ROL32:
case FLAGS_ROR8:
case FLAGS_ROR16:
case FLAGS_ROR32:
case FLAGS_UNKNOWN:
return cpu_state.flags & P_FLAG;
}
return 0;
}
static inline int VF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
return 0;
case FLAGS_ADC8:
case FLAGS_ADD8:
case FLAGS_INC8:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80);
case FLAGS_ADC16:
case FLAGS_ADD16:
case FLAGS_INC16:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000);
case FLAGS_ADC32:
case FLAGS_ADD32:
case FLAGS_INC32:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000);
case FLAGS_SBC8:
case FLAGS_SUB8:
case FLAGS_DEC8:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80);
case FLAGS_SBC16:
case FLAGS_SUB16:
case FLAGS_DEC16:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000);
case FLAGS_SBC32:
case FLAGS_SUB32:
case FLAGS_DEC32:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000);
case FLAGS_SHL8:
return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80);
case FLAGS_SHL16:
return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x8000);
case FLAGS_SHL32:
return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80000000);
case FLAGS_SHR8:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80));
case FLAGS_SHR16:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000));
case FLAGS_SHR32:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000));
case FLAGS_ROL8:
return (cpu_state.flags_res ^ (cpu_state.flags_res >> 7)) & 1;
case FLAGS_ROL16:
return (cpu_state.flags_res ^ (cpu_state.flags_res >> 15)) & 1;
case FLAGS_ROL32:
return (cpu_state.flags_res ^ (cpu_state.flags_res >> 31)) & 1;
case FLAGS_ROR8:
return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40;
case FLAGS_ROR16:
return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x4000;
case FLAGS_ROR32:
return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40000000;
case FLAGS_UNKNOWN:
return cpu_state.flags & V_FLAG;
}
return 0;
}
static inline int AF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
return 0;
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10;
case FLAGS_ADC8:
return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) ||
((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xff);
case FLAGS_ADC16:
return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) ||
((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffff);
case FLAGS_ADC32:
return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) ||
((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffffffff);
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10;
case FLAGS_SBC8:
case FLAGS_SBC16:
case FLAGS_SBC32:
return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) ||
((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0);
case FLAGS_ROL8:
case FLAGS_ROL16:
case FLAGS_ROL32:
case FLAGS_ROR8:
case FLAGS_ROR16:
case FLAGS_ROR32:
case FLAGS_UNKNOWN:
return cpu_state.flags & A_FLAG;
}
return 0;
}
static inline int CF_SET()
{
switch (cpu_state.flags_op)
{
case FLAGS_ADD8:
return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100) ? 1 : 0;
case FLAGS_ADD16:
return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000) ? 1 : 0;
case FLAGS_ADD32:
return (cpu_state.flags_res < cpu_state.flags_op1);
case FLAGS_ADC8:
return (cpu_state.flags_res < cpu_state.flags_op1) ||
(cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xff);
case FLAGS_ADC16:
return (cpu_state.flags_res < cpu_state.flags_op1) ||
(cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffff);
case FLAGS_ADC32:
return (cpu_state.flags_res < cpu_state.flags_op1) ||
(cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffffffff);
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
return (cpu_state.flags_op1 < cpu_state.flags_op2);
case FLAGS_SBC8:
case FLAGS_SBC16:
case FLAGS_SBC32:
return (cpu_state.flags_op1 < cpu_state.flags_op2) ||
(cpu_state.flags_op1 == cpu_state.flags_op2 && cpu_state.flags_res != 0);
case FLAGS_SHL8:
return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80) ? 1 : 0;
case FLAGS_SHL16:
return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000) ? 1 : 0;
case FLAGS_SHL32:
return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000) ? 1 : 0;
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
return (cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_SAR8:
return ((int8_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_SAR16:
return ((int16_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_SAR32:
return ((int32_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1;
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
return 0;
case FLAGS_ROL8:
case FLAGS_ROL16:
case FLAGS_ROL32:
return cpu_state.flags_res & 1;
case FLAGS_ROR8:
return (cpu_state.flags_res & 0x80) ? 1 : 0;
case FLAGS_ROR16:
return (cpu_state.flags_res & 0x8000) ? 1 :0;
case FLAGS_ROR32:
return (cpu_state.flags_res & 0x80000000) ? 1 : 0;
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_UNKNOWN:
return cpu_state.flags & C_FLAG;
}
return 0;
}
//#define ZF_SET() (flags & Z_FLAG)
//#define NF_SET() (flags & N_FLAG)
//#define PF_SET() (flags & P_FLAG)
//#define VF_SET() (flags & V_FLAG)
//#define CF_SET() (flags & C_FLAG)
//#define AF_SET() (flags & A_FLAG)
static inline void flags_rebuild()
{
if (cpu_state.flags_op != FLAGS_UNKNOWN)
{
uint16_t tempf = 0;
if (CF_SET()) tempf |= C_FLAG;
if (PF_SET()) tempf |= P_FLAG;
if (AF_SET()) tempf |= A_FLAG;
if (ZF_SET()) tempf |= Z_FLAG;
if (NF_SET()) tempf |= N_FLAG;
if (VF_SET()) tempf |= V_FLAG;
cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf;
cpu_state.flags_op = FLAGS_UNKNOWN;
}
}
static inline void flags_extract()
{
cpu_state.flags_op = FLAGS_UNKNOWN;
}
static inline void flags_rebuild_c()
{
if (cpu_state.flags_op != FLAGS_UNKNOWN)
{
if (CF_SET())
cpu_state.flags |= C_FLAG;
else
cpu_state.flags &= ~C_FLAG;
}
}
static inline int flags_res_valid()
{
if (cpu_state.flags_op == FLAGS_UNKNOWN ||
(cpu_state.flags_op >= FLAGS_ROL8 && cpu_state.flags_op <= FLAGS_ROR32))
return 0;
return 1;
}
static inline void setznp8(uint8_t val)
{
cpu_state.flags_op = FLAGS_ZN8;
cpu_state.flags_res = val;
}
static inline void setznp16(uint16_t val)
{
cpu_state.flags_op = FLAGS_ZN16;
cpu_state.flags_res = val;
}
static inline void setznp32(uint32_t val)
{
cpu_state.flags_op = FLAGS_ZN32;
cpu_state.flags_res = val;
}
#define set_flags_shift(op, orig, shift, res) \
cpu_state.flags_op = op; \
cpu_state.flags_res = res; \
cpu_state.flags_op1 = orig; \
cpu_state.flags_op2 = shift;
#define set_flags_rotate(op, res) \
cpu_state.flags_op = op; \
cpu_state.flags_res = res;
static inline void setadd8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xff;
cpu_state.flags_op = FLAGS_ADD8;
}
static inline void setadd16(uint16_t a, uint16_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xffff;
cpu_state.flags_op = FLAGS_ADD16;
}
static inline void setadd32(uint32_t a, uint32_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a + b;
cpu_state.flags_op = FLAGS_ADD32;
}
static inline void setadd8nc(uint8_t a, uint8_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xff;
cpu_state.flags_op = FLAGS_INC8;
}
static inline void setadd16nc(uint16_t a, uint16_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b) & 0xffff;
cpu_state.flags_op = FLAGS_INC16;
}
static inline void setadd32nc(uint32_t a, uint32_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a + b;
cpu_state.flags_op = FLAGS_INC32;
}
static inline void setsub8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xff;
cpu_state.flags_op = FLAGS_SUB8;
}
static inline void setsub16(uint16_t a, uint16_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xffff;
cpu_state.flags_op = FLAGS_SUB16;
}
static inline void setsub32(uint32_t a, uint32_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a - b;
cpu_state.flags_op = FLAGS_SUB32;
}
static inline void setsub8nc(uint8_t a, uint8_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xff;
cpu_state.flags_op = FLAGS_DEC8;
}
static inline void setsub16nc(uint16_t a, uint16_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - b) & 0xffff;
cpu_state.flags_op = FLAGS_DEC16;
}
static inline void setsub32nc(uint32_t a, uint32_t b)
{
flags_rebuild_c();
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a - b;
cpu_state.flags_op = FLAGS_DEC32;
}
static inline void setadc8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b + tempc) & 0xff;
cpu_state.flags_op = FLAGS_ADC8;
}
static inline void setadc16(uint16_t a, uint16_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a + b + tempc) & 0xffff;
cpu_state.flags_op = FLAGS_ADC16;
}
static inline void setadc32(uint32_t a, uint32_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a + b + tempc;
cpu_state.flags_op = FLAGS_ADC32;
}
static inline void setsbc8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - (b + tempc)) & 0xff;
cpu_state.flags_op = FLAGS_SBC8;
}
static inline void setsbc16(uint16_t a, uint16_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = (a - (b + tempc)) & 0xffff;
cpu_state.flags_op = FLAGS_SBC16;
}
static inline void setsbc32(uint32_t a, uint32_t b)
{
cpu_state.flags_op1 = a;
cpu_state.flags_op2 = b;
cpu_state.flags_res = a - (b + tempc);
cpu_state.flags_op = FLAGS_SBC32;
}
extern void cpu_386_flags_extract();
extern void cpu_386_flags_rebuild();

View File

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

View File

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

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