From 08254b8dfb18174a0ce1dbc76ebaebab1ba42fdf Mon Sep 17 00:00:00 2001 From: TomW Date: Sat, 18 Jul 2015 12:11:54 +0100 Subject: [PATCH] Initial 64-bit recompiler. Various 64-bit fixes. Various fixes to allow building under MinGW-w64. --- src/386_common.h | 12 +- src/386_dynarec.c | 18 +- src/386_dynarec_ops.c | 125 ++++ src/808x.c | 2 +- src/Makefile.mingw64 | 47 ++ src/cdrom-ioctl.c | 8 +- src/codegen.h | 10 + src/codegen_x86-64.c | 1039 ++++++++++++++++++++++++++++++++++ src/codegen_x86-64.h | 19 + src/ibm.h | 6 +- src/pc.rc | 4 + src/resid-fp/convolve-sse.cc | 2 +- src/soundopenal.c | 37 ++ src/x86.h | 2 +- src/x86seg.c | 8 +- 15 files changed, 1314 insertions(+), 25 deletions(-) create mode 100644 src/Makefile.mingw64 create mode 100644 src/codegen_x86-64.c create mode 100644 src/codegen_x86-64.h diff --git a/src/386_common.h b/src/386_common.h index eedfdc2..33cc033 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -4,14 +4,14 @@ extern uint16_t ea_rseg; #undef writememb -#define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[((s)+(a))>>12] + (s) + (a)) ) -#define readmemq(s,a) ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFF8)?readmemql(s,a):*(uint64_t *)(readlookup2[((s)+(a))>>12]+(s)+(a))) +#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) ) +#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFF8)?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) -#define writememb(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v +#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v -#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *(uint16_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v -#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *(uint32_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v -#define writememq(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFF8) writememql(s,a,v); else *(uint64_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v +#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v +#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFF8) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v #define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \ diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3449507..3c83e0b 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -135,10 +135,11 @@ static inline void fetch_ea_32_long(uint32_t rmdat) } if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) { - if ( readlookup2[(easeg + eaaddr) >> 12] != -1) - eal_r = (uint32_t *)(readlookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr); - if (writelookup2[(easeg + eaaddr) >> 12] != -1) - eal_w = (uint32_t *)(writelookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr); + uint32_t addr = easeg + eaaddr; + if ( readlookup2[addr >> 12] != -1) + eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != -1) + eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } } @@ -176,10 +177,11 @@ static inline void fetch_ea_16_long(uint32_t rmdat) } if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) { - if ( readlookup2[(easeg + eaaddr) >> 12] != -1) - eal_r = (uint32_t *)(readlookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr); - if (writelookup2[(easeg + eaaddr) >> 12] != -1) - eal_w = (uint32_t *)(writelookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr); + uint32_t addr = easeg + eaaddr; + if ( readlookup2[addr >> 12] != -1) + eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != -1) + eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } } diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index fd2cf05..853a736 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -18,6 +18,127 @@ extern uint32_t *mod1seg[8]; /*Copy-and-pasted from 386_dynarec.c, is not in a header file because it will eventually be different for the dynarec ops*/ +#ifdef __amd64__ +static inline void fetch_ea_32_long(uint32_t rmdat) +{ + eal_r = eal_w = NULL; + easeg = ea_seg->base; + ea_rseg = ea_seg->seg; + if (rm == 4) + { + uint8_t sib = rmdat >> 8; + + switch (mod) + { + case 0: + eaaddr = regs[sib & 7].l; + pc++; + break; + case 1: + pc++; + eaaddr = ((uint32_t)(int8_t)getbyte()) + regs[sib & 7].l; +// pc++; + break; + case 2: + eaaddr = (fastreadl(cs + pc + 1)) + regs[sib & 7].l; + pc += 5; + break; + } + /*SIB byte present*/ + if ((sib & 7) == 5 && !mod) + eaaddr = getlong(); + else if ((sib & 6) == 4 && !ssegs) + { + easeg = ss; + ea_rseg = SS; + ea_seg = &_ss; + } + if (((sib >> 3) & 7) != 4) + eaaddr += regs[(sib >> 3) & 7].l << (sib >> 6); + } + else + { + eaaddr = regs[rm].l; + if (mod) + { + if (rm == 5 && !ssegs) + { + easeg = ss; + ea_rseg = SS; + ea_seg = &_ss; + } + if (mod == 1) + { + eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); + pc++; + } + else + { + eaaddr += getlong(); + } + } + else if (rm == 5) + { + eaaddr = getlong(); + } + } + if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) + { + uint32_t addr = easeg + eaaddr; + if ( readlookup2[addr >> 12] != -1) + eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != -1) + eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); + } +} + +static inline void fetch_ea_16_long(uint32_t rmdat) +{ + eal_r = eal_w = NULL; + easeg = ea_seg->base; + ea_rseg = ea_seg->seg; + if (!mod && rm == 6) + { + eaaddr = getword(); + } + else + { + switch (mod) + { + case 0: + eaaddr = 0; + break; + case 1: + eaaddr = (uint16_t)(int8_t)(rmdat >> 8); pc++; + break; + case 2: + eaaddr = getword(); + break; + } + eaaddr += (*mod1add[0][rm]) + (*mod1add[1][rm]); + if (mod1seg[rm] == &ss && !ssegs) + { + easeg = ss; + ea_rseg = SS; + ea_seg = &_ss; + } + eaaddr &= 0xFFFF; + } + if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) + { + uint32_t addr = easeg + eaaddr; + if ( readlookup2[addr >> 12] != -1) + eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); + if (writelookup2[addr >> 12] != -1) + eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); + } +} + +#define fetch_ea_16(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_16_long(rmdat); if (abrt) return 1; } +#define fetch_ea_32(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_32_long(rmdat); } if (abrt) return 1 + +#else /*__amd64__*/ + static inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; @@ -49,6 +170,10 @@ static inline void fetch_ea_16_long(uint32_t rmdat) #define fetch_ea_16(rmdat) pc++; if (mod != 3) fetch_ea_16_long(rmdat); #define fetch_ea_32(rmdat) pc++; if (mod != 3) fetch_ea_32_long(rmdat); +#endif /*__amd64__*/ + + + #define OP_TABLE(name) dynarec_ops_ ## name #define CLOCK_CYCLES(c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) diff --git a/src/808x.c b/src/808x.c index d276a4b..bb5d347 100644 --- a/src/808x.c +++ b/src/808x.c @@ -594,7 +594,7 @@ chdir(pcempath); printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); if (is386) { - printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); + printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); } printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 new file mode 100644 index 0000000..670f25f --- /dev/null +++ b/src/Makefile.mingw64 @@ -0,0 +1,47 @@ +VPATH = . dosbox resid-fp +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +CFLAGS = -O3 -fomit-frame-pointer +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ + codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ + device.o disc.o disc_fdi.o disc_img.o dma.o fdc.o fdc37c665.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \ + i430vx.o ide.o intel.o intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ + keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \ + mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \ + serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ + sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_resid.o \ + sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ + soundopenal.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ + vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \ + vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o \ + vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ + vid_pcjr.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ + vid_svga_render.o vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ + vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ + win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \ + win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res +FMOBJ = dbopl.o +SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o + + +LIBS = -mwindows -lwinmm -lopenal32 -lddraw -ldinput -ldxguid -ld3d9 -lstdc++ + +PCem64.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) + $(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) -o "PCem64.exe" $(LIBS) + +all : PCem64.exe + +clean : + rm *.o + rm *.exe + rm *.res + +%.o : %.c + $(CC) $(CFLAGS) -c $< + +%.o : %.cc + $(CPP) $(CFLAGS) -c $< + +pc.res: pc.rc + $(WINDRES) -i pc.rc --input-format=rc -o pc.res -O coff diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 4c4f61b..54a96d5 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -2,20 +2,26 @@ #include #include +#ifdef __MINGW64__ +#include "ntddcdrm.h" +#else #include "ddk/ntddcdrm.h" -//#include "ntddcdrm.h" +#endif #include "ibm.h" #include "ide.h" #include "cdrom-ioctl.h" int cdrom_drive; +#ifndef __MINGW64__ typedef struct _CDROM_TOC_SESSION_DATA { UCHAR Length[2]; UCHAR FirstCompleteSession; UCHAR LastCompleteSession; TRACK_DATA TrackData[1]; } CDROM_TOC_SESSION_DATA, *PCDROM_TOC_SESSION_DATA; +#endif + static ATAPI ioctl_atapi; static uint32_t last_block = 0; diff --git a/src/codegen.h b/src/codegen.h index bf144f2..7292a24 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -138,6 +138,16 @@ static inline void addlong(uint32_t val) } } +static inline void addquad(uint64_t val) +{ + *(uint64_t *)&codeblock[block_current].data[block_pos] = val; + block_pos += 8; + if (block_pos >= 1760) + { + CPU_BLOCK_END(); + } +} + /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; diff --git a/src/codegen_x86-64.c b/src/codegen_x86-64.c new file mode 100644 index 0000000..dd1422c --- /dev/null +++ b/src/codegen_x86-64.c @@ -0,0 +1,1039 @@ +#ifdef DYNAREC +#ifdef __amd64__ + +#include +#include "ibm.h" +#include "cpu.h" +#include "x86.h" +#include "x86_flags.h" +#include "x86_ops.h" +#include "x87.h" +#include "mem.h" + +#include "386_common.h" + +#include "codegen.h" +#include "codegen_ops.h" +//#include "codegen_ops_x86.h" + +#ifdef __linux__ +#include +#include +#endif +#if WIN64 +#include +#endif + +int codegen_flags_changed = 0; +int codegen_fpu_entered = 0; +int codegen_fpu_loaded_iq[8]; +x86seg *op_ea_seg; +int op_ssegs; +uint32_t op_old_pc; + +uint32_t recomp_page = -1; + +int host_reg_mapping[NR_HOST_REGS]; +codeblock_t *codeblock; +codeblock_t **codeblock_hash; + + +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; + +static 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; + +void codegen_init() +{ + int c; +#ifdef __linux__ + void *start; + size_t len; + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); +#endif + +#if WIN64 + codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); +#endif + codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + +#ifdef __linux__ + start = (void *)((long)codeblock & pagemask); + len = ((BLOCK_SIZE * sizeof(codeblock_t)) + pagesize) & pagemask; + if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + perror("mprotect"); + exit(-1); + } +#endif +// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); +} + +void codegen_reset() +{ + memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); + memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); + mem_reset_page_blocks(); +} + +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 delete_block(codeblock_t *block) +{ +// pclog("delete_block: pc=%08x\n", block->pc); + codeblock_hash[HASH(block->phys)] = NULL; + + if (!block->pc) + fatal("Deleting deleted block\n"); + block->pc = 0; + + if (block->prev) + { + block->prev->next = block->next; + if (block->next) + block->next->prev = block->prev; + } + else + { + pages[block->phys >> 12].block = block->next; + if (block->next) + block->next->prev = NULL; + else + mem_flush_write_page(block->phys, 0); + } + if (!block->page_mask2) + { + if (block->prev_2 || block->next_2) + fatal("Invalid block_2\n"); + return; + } + + if (block->prev_2) + { + block->prev_2->next_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = block->prev_2; + } + else + { +// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); + pages[block->phys_2 >> 12].block_2 = block->next_2; + if (block->next_2) + block->next_2->prev_2 = NULL; + else + mem_flush_write_page(block->phys_2, 0); + } +} + +void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr) +{ + struct codeblock_t *block = page->block; + + while (block) + { + if (mask & block->page_mask) + { + delete_block(block); + cpu_recomp_evicted++; + } + if (block == block->next) + fatal("Broken 1\n"); + block = block->next; + } + + block = page->block_2; + + while (block) + { + if (mask & block->page_mask2) + { + delete_block(block); + cpu_recomp_evicted++; + } + if (block == block->next_2) + fatal("Broken 2\n"); + block = block->next_2; + } +} + +void codegen_block_init(uint32_t phys_addr) +{ + codeblock_t *block; + int has_evicted = 0; + page_t *page = &pages[phys_addr >> 12]; + + if (!page->block) + mem_flush_write_page(phys_addr, cs+pc); + + block_current = (block_current + 1) & BLOCK_MASK; + block = &codeblock[block_current]; + +// if (block->pc == 0xb00b4ff5) +// pclog("Init target block\n"); + if (block->pc != 0) + { +// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); + delete_block(block); + cpu_recomp_reuse++; + } + block_num = HASH(phys_addr); + codeblock_hash[block_num] = &codeblock[block_current]; + block->ins = 0; + block->pc = cs + pc; + block->_cs = cs; + block->pnt = block_current; + block->phys = phys_addr; + block->use32 = use32; + block->stack32 = stack32; + block->next = block->prev = NULL; + + block_pos = BLOCK_GPF_OFFSET; + addbyte(0x48); /*XOR RCX, RCX*/ + addbyte(0x31); + addbyte(0xc9); + addbyte(0xe1); /*XOR EDX, EDX*/ + addbyte(0xd2); + addbyte(0xe8); /*CALL x86gpf*/ + addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ + addbyte(0x48); /*ADDL $32,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x20); + addbyte(0x5d); /*POP RBP*/ + addbyte(0xC3); /*RET*/ + cpu_block_end = 0; + block_pos = 0; /*Entry code*/ + addbyte(0x55); /*PUSH RBP*/ + addbyte(0x48); /*SUBL $32,%rsp*/ + addbyte(0x83); + addbyte(0xEC); + addbyte(0x20); + addbyte(0x48); /*MOVL EBP, &EAX*/ + addbyte(0xBD); + addquad((uint64_t)&EAX); + +// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num); + + 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 = phys_addr & ~0xfff; + + codegen_flags_changed = 0; + codegen_fpu_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; + + _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; +} + +void codegen_block_remove() +{ + codeblock_t *block = &codeblock[block_current]; +//if ((block->phys & ~0xfff) == 0x119000) pclog("codegen_block_remove %08x\n", block->pc); +// if (block->pc == 0xb00b4ff5) +// pclog("Remove target block\n"); + codeblock_hash[block_num] = NULL; + block->pc = 0;//xffffffff; + cpu_recomp_removed++; +// pclog("Remove block %i\n", block_num); + recomp_page = -1; +} + +void codegen_block_end() +{ + codeblock_t *block = &codeblock[block_current]; + codeblock_t *block_prev = pages[block->phys >> 12].block; + uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); + uint32_t end_pc = ((codegen_endpc + 3) & 0xffc) | (block->phys & ~0xfff); + + block->endpc = codegen_endpc; + +// if (block->pc == 0xb00b4ff5) +// pclog("End target block\n"); + + if (block_prev) + { + block->next = block_prev; + block_prev->prev = block; + pages[block->phys >> 12].block = block; + } + else + { + block->next = NULL; + pages[block->phys >> 12].block = block; + } + + if (block->next) + { +// pclog(" next->pc=%08x\n", block->next->pc); + if (!block->next->pc) + fatal("block->next->pc=0 %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos); + } + + block->page_mask = 0; + start_pc = block->pc & 0xffc; + start_pc &= ~PAGE_MASK_MASK; + end_pc = ((block->endpc & 0xffc) + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + if (end_pc > 0xfff || end_pc < start_pc) + end_pc = 0xfff; + start_pc >>= PAGE_MASK_SHIFT; + end_pc >>= PAGE_MASK_SHIFT; + +// pclog("block_end: %08x %08x\n", start_pc, end_pc); + for (; start_pc <= end_pc; start_pc++) + { + block->page_mask |= ((uint64_t)1 << start_pc); +// pclog(" %08x %llx\n", start_pc, block->page_mask); + } + + pages[block->phys >> 12].code_present_mask |= block->page_mask; + + block->phys_2 = -1; + block->page_mask2 = 0; + block->next_2 = block->prev_2 = NULL; + if ((block->pc ^ block->endpc) & ~0xfff) + { + block->phys_2 = get_phys_noabrt(block->endpc); + if (block->phys_2 != -1) + { +// pclog("start block - %08x %08x %p %p %p %08x\n", block->pc, block->endpc, (void *)block, (void *)block->next_2, (void *)pages[block->phys_2 >> 12].block_2, block->phys_2); + + if (pages[block->phys_2 >> 12].block_2 == block) + fatal("Block same\n"); + + block_prev = pages[block->phys_2 >> 12].block_2; + + if (block_prev) + { + block->next_2 = block_prev; + block_prev->prev_2 = block; + pages[block->phys_2 >> 12].block_2 = block; +// pclog(" pages.block_2=%p\n", (void *)block); + } + else + { + block->next_2 = NULL; + pages[block->phys_2 >> 12].block_2 = block; +// pclog(" pages.block_2=%p 2\n", (void *)block); + } + + start_pc = 0; + end_pc = (block->endpc & 0xfff) >> PAGE_MASK_SHIFT; + for (; start_pc <= end_pc; start_pc++) + block->page_mask2 |= ((uint64_t)1 << start_pc); + + if (!pages[block->phys_2 >> 12].block_2) + mem_flush_write_page(block->phys_2, block->endpc); +// pclog("New block - %08x %08x %p %p phys %08x %08x %016llx\n", block->pc, block->endpc, (void *)block, (void *)block->next_2, block->phys, block->phys_2, block->page_mask2); + if (!block->page_mask2) + fatal("!page_mask2\n"); + if (block->next_2) + { +// pclog(" next_2->pc=%08x\n", block->next_2->pc); + if (!block->next_2->pc) + fatal("block->next_2->pc=0 %p\n", (void *)block->next_2); + } + } + } + +// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); + + codegen_timing_block_end(); + + if (codegen_block_cycles) + { + addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uint32_t)&cycles); + addlong((uint32_t)codegen_block_cycles); + } + if (codegen_block_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&cpu_recomp_ins); + addlong(codegen_block_ins); + } +#if 0 + if (codegen_block_full_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&cpu_recomp_full_ins); + addlong(codegen_block_full_ins); + } +#endif + addbyte(0x48); /*ADDL $32,%rsp*/ + addbyte(0x83); + addbyte(0xC4); + addbyte(0x20); + addbyte(0x5d); /*POP RBP*/ + addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); +// pclog("End block %i\n", block_num); + + recomp_page = -1; +} + +void codegen_flush() +{ + return; +} + +static int opcode_needs_tempc[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*00*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*20*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*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*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*c0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*e0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*f0*/ +}; + +static int opcode_conditional_jump[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ + 0, 0, 0, 0, 0, 0, 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*/ + + 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*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*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*/ + 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*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*d0*/ + 1, 1, 1, 1, 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*/ +}; + +static int opcode_modrm[256] = +{ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; +int opcode_0f_modrm[256] = +{ + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*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*/ + + 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*/ + 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, 0, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; + +void codegen_debug() +{ + if (output) + { + pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); + } +} +#if 0 +static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + if (!mod && rm == 6) + { + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x05); + addlong((uint32_t)&eaaddr); + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } + else + { + switch (mod) + { + case 0: + addbyte(0xa1); /*MOVL *mod1add[0][rm], %eax*/ + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL *mod1add[1][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + break; + case 1: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((uint32_t)(int8_t)(rmdat >> 8));// pc++; + addbyte(0x03); /*ADDL *mod1add[0][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL *mod1add[1][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + (*op_pc)++; + break; + case 2: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((fetchdat >> 8) & 0xffff);// pc++; + addbyte(0x03); /*ADDL *mod1add[0][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL *mod1add[1][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + (*op_pc) += 2; + break; + } + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + addbyte(0xa3); + addlong((uint32_t)&eaaddr); + + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &_ss; + } + return op_ea_seg; +} + +static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + uint32_t new_eaaddr; + + if (rm == 4) + { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (mod) + { + case 0: + if ((sib & 7) == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL ,%eax*/ + addlong(new_eaaddr);// pc++; + (*op_pc) += 4; + } + else + { + addbyte(0xa1); /*MOVL regs[sib&7].l, %eax*/ + addlong((uint32_t)®s[sib & 7].l); + } + break; + case 1: + new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x05); + addlong((uint32_t)®s[sib & 7].l); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x05); + addlong((uint32_t)®s[sib & 7].l); + (*op_pc) += 4; + break; + } + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &_ss; + if (((sib >> 3) & 7) != 4) + { + switch (sib >> 6) + { + case 0: + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x05); + addlong((uint32_t)®s[(sib >> 3) & 7].l); + break; + case 1: + addbyte(0x8B); addbyte(0x1D); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL armregs[RD],%ebx*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 2: + addbyte(0x8B); addbyte(0x1D); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); addbyte(0xE3); addbyte(2); /*SHL $2,%ebx*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 3: + addbyte(0x8B); addbyte(0x1D); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); addbyte(0xE3); addbyte(3); /*SHL $2,%ebx*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + } + } + addbyte(0xa3); + addlong((uint32_t)&eaaddr); + } + else + { + if (!mod && rm == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ + addbyte(0x05); + addlong((uint32_t)&eaaddr); + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0xa1); /*MOVL regs[rm].l, %eax*/ + addlong((uint32_t)®s[rm].l); + eaaddr = regs[rm].l; + if (mod) + { + if (rm == 5 && !op_ssegs) + op_ea_seg = &_ss; + if (mod == 1) + { + addbyte(0x05); + addlong((uint32_t)(int8_t)(fetchdat >> 8)); + (*op_pc)++; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + addbyte(0xa3); + addlong((uint32_t)&eaaddr); + } + return op_ea_seg; +} +#endif +void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) +{ + codeblock_t *block = &codeblock[block_current]; + uint32_t op_32 = use32; + uint32_t op_pc = new_pc; + OpFn *op_table = x86_dynarec_opcodes; + RecompOpFn *recomp_op_table = recomp_opcodes; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + int over = 0; + int pc_off = 0; + int test_modrm = 1; + int c; + + op_ea_seg = &_ds; + op_ssegs = 0; + op_old_pc = old_pc; + + for (c = 0; c < NR_HOST_REGS; c++) + host_reg_mapping[c] = -1; + + codegen_timing_start(); + + while (!over) + { + switch (opcode) + { + case 0x0f: + op_table = x86_dynarec_opcodes_0f; + recomp_op_table = recomp_opcodes_0f; + over = 1; + break; + + case 0x26: /*ES:*/ + op_ea_seg = &_es; + op_ssegs = 1; + break; + case 0x2e: /*CS:*/ + op_ea_seg = &_cs; + op_ssegs = 1; + break; + case 0x36: /*SS:*/ + op_ea_seg = &_ss; + op_ssegs = 1; + break; + case 0x3e: /*DS:*/ + op_ea_seg = &_ds; + op_ssegs = 1; + break; + case 0x64: /*FS:*/ + op_ea_seg = &_fs; + op_ssegs = 1; + break; + case 0x65: /*GS:*/ + op_ea_seg = &_gs; + op_ssegs = 1; + break; + + case 0x66: /*Data size select*/ + op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200); + break; + case 0x67: /*Address size select*/ + op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100); + break; + + case 0xd8: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = recomp_opcodes_d8; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = recomp_opcodes_d9; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = recomp_opcodes_da; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = recomp_opcodes_db; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = recomp_opcodes_dc; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = recomp_opcodes_dd; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = recomp_opcodes_de; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = recomp_opcodes_df; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + test_modrm = 0; + break; + + case 0xf0: /*LOCK*/ + break; + + default: + goto generate_call; + } + fetchdat = fastreadl(cs + op_pc); + codegen_timing_prefix(opcode, fetchdat); + if (abrt) + return; + opcode = fetchdat & 0xff; + if (!pc_off) + fetchdat >>= 8; + + op_pc++; + } + +generate_call: + codegen_timing_opcode(opcode, fetchdat, op_32); + + 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)))) + { + /*Opcode is likely to cause block to exit, update cycle count*/ + if (codegen_block_cycles) + { + addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uint32_t)&cycles); + addlong((uint32_t)codegen_block_cycles); + codegen_block_cycles = 0; + } + if (codegen_block_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&cpu_recomp_ins); + addlong(codegen_block_ins); + codegen_block_ins = 0; + } +#if 0 + if (codegen_block_full_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&cpu_recomp_full_ins); + addlong(codegen_block_full_ins); + codegen_block_full_ins = 0; + } +#endif + } +#if 0 + if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) + { + uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); + if (new_pc) + { + if (new_pc != -1) + STORE_IMM_ADDR_L((uintptr_t)&pc, new_pc); + + codegen_block_ins++; + block->ins++; + codegen_block_full_ins++; + codegen_endpc = (cs + pc) + 8; + + return; + } + } +#endif + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; +// if (output) +// pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); + if (opcode_needs_tempc[opcode]) + { + addbyte(0x8b); /*MOVL (flags), %eax*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&flags); + addbyte(0x83); /*ANDL $1, %eax*/ + addbyte(0xe0); + addbyte(0x01); + addbyte(0x89); /*MOVL %eax, (tempc)*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&tempc); + } + if (op_ssegs != last_ssegs) + { + last_ssegs = op_ssegs; + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&ssegs); + addlong(op_ssegs); + } +#if 0 + if (!test_modrm || + (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || + (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) + { + int stack_offset = 0; + + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; + + mod = (fetchdat >> 6) & 3; + reg = (fetchdat >> 3) & 7; + rm = fetchdat & 7; + + addbyte(0xC7); /*MOVL $mod,(mod)*/ + addbyte(0x05); + addlong((uint32_t)&mod); + addlong(mod); + addbyte(0xC7); /*MOVL $reg,(reg)*/ + addbyte(0x05); + addlong((uint32_t)®); + addlong(reg); + addbyte(0xC7); /*MOVL $rm,(rm)*/ + addbyte(0x05); + addlong((uint32_t)&rm); + addlong(rm); + + op_pc += pc_off; + if (mod != 3 && !(op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); + if (mod != 3 && (op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); + op_pc -= pc_off; + } +#endif +// if (op_ea_seg != last_ea_seg) +// { +// last_ea_seg = op_ea_seg; + addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&ea_seg); + addlong((uint32_t)op_ea_seg); +// } + + + addbyte(0xC7); /*MOVL $new_pc,(pc)*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&pc); + addlong(op_pc + pc_off); + addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&oldpc); + addlong(old_pc); + if (op_32 != last_op32) + { + last_op32 = op_32; + addbyte(0xC7); /*MOVL $use32,(op32)*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&op32); + addlong(op_32); + } + + addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ + addlong(fetchdat); + + addbyte(0xE8); /*CALL*/ + addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4]))); + + codegen_block_ins++; + + block->ins++; + + addbyte(0x85); /*OR %eax, %eax*/ + addbyte(0xc0); + addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); + +// addbyte(0xE8); /*CALL*/ +// addlong(((uint8_t *)codegen_debug - (uint8_t *)(&block->data[block_pos + 4]))); + + codegen_endpc = (cs + pc) + 8; +} + +void codegen_check_abrt() +{ + codeblock_t *block = &codeblock[block_current]; +// pclog("Generate check abrt at %08X\n", &codeblock[block_current][block_pos]); + addbyte(0xf7); addbyte(0x04); /*TESTL $-1, (abrt)*/ + addbyte(0x25); + addlong((uint32_t)&abrt); addlong(0xffffffff); + addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ + addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4])); +} + +#endif +#endif diff --git a/src/codegen_x86-64.h b/src/codegen_x86-64.h new file mode 100644 index 0000000..8567979 --- /dev/null +++ b/src/codegen_x86-64.h @@ -0,0 +1,19 @@ +#define BLOCK_SIZE 0x4000 +#define BLOCK_MASK 0x3fff +#define BLOCK_START 0 + +#define HASH_SIZE 0x20000 +#define HASH_MASK 0x1ffff + +#define HASH(l) ((l) & 0x1ffff) + +#define BLOCK_EXIT_OFFSET 0x7f0 +#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) + +enum +{ + OP_RET = 0xc3 +}; + +#define NR_HOST_REGS 3 +extern int host_reg_mapping[NR_HOST_REGS]; diff --git a/src/ibm.h b/src/ibm.h index 23c3748..6a65a2e 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -18,8 +18,8 @@ int writelnext; extern int mmu_perm; #define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a))) -#define readmemw(s,a) ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE)?readmemwl(s,a):*(uint16_t *)(readlookup2[((s)+(a))>>12]+(s)+(a))) -#define readmeml(s,a) ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC)?readmemll(s,a):*(uint32_t *)(readlookup2[((s)+(a))>>12]+(s)+(a))) +#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE)?readmemwl(s,a):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) +#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC)?readmemll(s,a):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) //#define writememb(a,v) if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v); else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v //#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v @@ -142,7 +142,7 @@ uint8_t *pccache2; #define ds _ds.base #define es _es.base #define ss _ss.base -#define fs _fs.base +#define seg_fs _fs.base #define gs _gs.base #define CPL ((_cs.access>>5)&3) diff --git a/src/pc.rc b/src/pc.rc index f60784f..8901bfe 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -1,6 +1,10 @@ #include #include "resources.h" +#ifndef UPDOWN_CLASS +#define UPDOWN_CLASS L"msctls_updown32" +#endif + MainMenu MENU DISCARDABLE BEGIN POPUP "&File" diff --git a/src/resid-fp/convolve-sse.cc b/src/resid-fp/convolve-sse.cc index 708a2ad..92c35d4 100644 --- a/src/resid-fp/convolve-sse.cc +++ b/src/resid-fp/convolve-sse.cc @@ -32,7 +32,7 @@ float convolve_sse(const float *a, const float *b, int n) int diff = (int) (a - b) & 0xf; /* long cast is no-op for x86-32, but x86-64 gcc needs 64 bit intermediate * to convince compiler we mean this. */ - unsigned int a_align = (unsigned int) (unsigned long) a & 0xf; + unsigned int a_align = (unsigned int) (uintptr_t) a & 0xf; /* advance if necessary. We can't let n fall < 0, so no while (n --). */ while (n > 0 && a_align != 0 && a_align != 16) { diff --git a/src/soundopenal.c b/src/soundopenal.c index ecad5b2..8e0a329 100644 --- a/src/soundopenal.c +++ b/src/soundopenal.c @@ -4,8 +4,12 @@ #include #ifdef USE_OPENAL #include +#ifdef __MINGW64__ +#include +#else #include #endif +#endif #include "ibm.h" FILE *allog; @@ -18,7 +22,40 @@ ALenum format; // internal format #define BUFLEN SOUNDBUFLEN void closeal(); +#ifdef __MINGW64__ +ALvoid alutInit(ALint *argc,ALbyte **argv) +{ + ALCcontext *Context; + ALCdevice *Device; + + //Open device + Device=alcOpenDevice((ALubyte*)"DirectSound3D"); + //Create context(s) + Context=alcCreateContext(Device,NULL); + //Set active context + alcMakeContextCurrent(Context); + //Register extensions +} +ALvoid alutExit(ALvoid) +{ + ALCcontext *Context; + ALCdevice *Device; + + //Unregister extensions + + //Get active context + Context=alcGetCurrentContext(); + //Get device for active context + Device=alcGetContextsDevice(Context); + //Disable context + alcMakeContextCurrent(NULL); + //Release context(s) + alcDestroyContext(Context); + //Close device + alcCloseDevice(Device); +} +#endif void initalmain(int argc, char *argv[]) { #ifdef USE_OPENAL diff --git a/src/x86.h b/src/x86.h index c5cf782..83c28bc 100644 --- a/src/x86.h +++ b/src/x86.h @@ -50,7 +50,7 @@ int optype; #define JMP 1 #define CALL 2 #define IRET 3 -#define INT 4 +#define OPTYPE_INT 4 uint32_t oxpc; diff --git a/src/x86seg.c b/src/x86seg.c index 8de8923..82b158a 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -1934,7 +1934,7 @@ void pmodeint(int num, int soft) x86np("Int task gate not present\n", segdat[1] & 0xfffc); return; } - optype=INT; + optype=OPTYPE_INT; cpl_override=1; taskswitch286(seg,segdat2,segdat2[2]&0x800); cpl_override=0; @@ -2366,7 +2366,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) new_ldt=readmemw(base,0x60); if (abrt) return; - if (optype==JMP || optype==INT) + if (optype==JMP || optype==OPTYPE_INT) { if (tr.seg&4) tempw=readmemw(ldt.base,(tr.seg&~7)+4); else tempw=readmemw(gdt.base,(tr.seg&~7)+4); @@ -2402,13 +2402,13 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32) writememl(tr.base,0x5C,GS); writememl(tr.base,0x60,ldt.seg); - if (optype==INT) + if (optype==OPTYPE_INT) { writememl(base,0,tr.seg); new_flags|=NT_FLAG; } if (abrt) return; - if (optype==JMP || optype==INT) + if (optype==JMP || optype==OPTYPE_INT) { if (tr.seg&4) tempw=readmemw(ldt.base,(seg&~7)+4); else tempw=readmemw(gdt.base,(seg&~7)+4);