- merge JIT branch into trunk;

- remove JIT branch;
This commit is contained in:
mtabachenko 2012-07-10 12:39:40 +00:00
parent d9f13c57c0
commit 64073a2558
72 changed files with 57527 additions and 6013 deletions

View File

@ -150,11 +150,6 @@ void mmu_log_debug_ARM7(u32 adr, const char *fmt, ...)
//#define LOG_DMA2
//#define LOG_DIV
#define DUP2(x) x, x
#define DUP4(x) x, x, x, x
#define DUP8(x) x, x, x, x, x, x, x, x
#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
MMU_struct MMU;
MMU_struct_new MMU_new;
MMU_struct_timing MMU_timing;
@ -1981,6 +1976,7 @@ void DmaController::doCopy()
u32 src = saddr;
u32 dst = daddr;
//if these do not use MMU_AT_DMA and the corresponding code in the read/write routines,
//then danny phantom title screen will be filled with a garbage char which is made by
//dmaing from 0x00000000 to 0x06000000
@ -2132,7 +2128,10 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
if(adr < 0x02000000)
{
T1WriteByte(MMU.ARM9_ITCM, adr&0x7FFF, val);
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0;
#endif
T1WriteByte(MMU.ARM9_ITCM, adr & 0x7FFF, val);
return;
}
@ -2393,7 +2392,12 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
adr = MMU_LCDmap<ARMCPU_ARM9>(adr, unmapped, restricted);
if(unmapped) return;
if(restricted) return; //block 8bit vram writes
#ifdef HAVE_JIT
if (JIT_MAPPED(adr, ARMCPU_ARM9))
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 0) = 0;
#endif
// Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash]
MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val;
}
@ -2407,7 +2411,10 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
if (adr < 0x02000000)
{
T1WriteWord(MMU.ARM9_ITCM, adr&0x7FFF, val);
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0;
#endif
T1WriteWord(MMU.ARM9_ITCM, adr & 0x7FFF, val);
return;
}
@ -2849,6 +2856,11 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
adr = MMU_LCDmap<ARMCPU_ARM9>(adr, unmapped, restricted);
if(unmapped) return;
#ifdef HAVE_JIT
if (JIT_MAPPED(adr, ARMCPU_ARM9))
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 0) = 0;
#endif
// Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash]
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val);
}
@ -2862,7 +2874,11 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
if(adr<0x02000000)
{
T1WriteLong(MMU.ARM9_ITCM, adr&0x7FFF, val);
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 0) = 0;
JIT_COMPILED_FUNC_KNOWNBANK(adr, ARM9_ITCM, 0x7FFF, 1) = 0;
#endif
T1WriteLong(MMU.ARM9_ITCM, adr & 0x7FFF, val);
return ;
}
@ -3280,6 +3296,14 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
adr = MMU_LCDmap<ARMCPU_ARM9>(adr, unmapped, restricted);
if(unmapped) return;
#ifdef HAVE_JIT
if (JIT_MAPPED(adr, ARMCPU_ARM9))
{
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 0) = 0;
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM9, 1) = 0;
}
#endif
// Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash]
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val);
}
@ -3702,6 +3726,11 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val)
bool unmapped, restricted;
adr = MMU_LCDmap<ARMCPU_ARM7>(adr,unmapped, restricted);
if(unmapped) return;
#ifdef HAVE_JIT
if (JIT_MAPPED(adr, ARMCPU_ARM7))
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 0) = 0;
#endif
// Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash]
MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]=val;
@ -4138,6 +4167,11 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
adr = MMU_LCDmap<ARMCPU_ARM7>(adr,unmapped, restricted);
if(unmapped) return;
#ifdef HAVE_JIT
if (JIT_MAPPED(adr, ARMCPU_ARM7))
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 0) = 0;
#endif
// Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash]
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val);
}
@ -4235,6 +4269,14 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
adr = MMU_LCDmap<ARMCPU_ARM7>(adr,unmapped, restricted);
if(unmapped) return;
#ifdef HAVE_JIT
if (JIT_MAPPED(adr, ARMCPU_ARM7))
{
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 0) = 0;
JIT_COMPILED_FUNC_PREMASKED(adr, ARMCPU_ARM7, 1) = 0;
}
#endif
// Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash]
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val);
}

View File

@ -32,6 +32,10 @@
#include "lua-engine.h"
#endif
#ifdef HAVE_JIT
#include "arm_jit.h"
#endif
#define ARMCPU_ARM7 1
#define ARMCPU_ARM9 0
#define ARMPROC (PROCNUM ? NDS_ARM7:NDS_ARM9)
@ -313,6 +317,11 @@ typedef struct
} nds_dscard;
#define DUP2(x) x, x
#define DUP4(x) x, x, x, x
#define DUP8(x) x, x, x, x, x, x, x, x
#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
struct MMU_struct
{
//ARM9 mem
@ -795,6 +804,9 @@ FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
}
if ( (addr & 0x0F000000) == 0x02000000) {
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK, 0) = 0;
#endif
T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
@ -831,6 +843,9 @@ FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
}
if ( (addr & 0x0F000000) == 0x02000000) {
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK16, 0) = 0;
#endif
T1WriteWord( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
@ -867,6 +882,10 @@ FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
}
if ( (addr & 0x0F000000) == 0x02000000) {
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK32, 0) = 0;
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK32, 1) = 0;
#endif
T1WriteLong( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);

View File

@ -13,6 +13,7 @@ noinst_LIBRARIES = libdesmume.a
libdesmume_a_SOURCES = \
armcpu.cpp armcpu.h \
arm_instructions.cpp arm_instructions.h \
arm_jit.cpp arm_jit.h instruction_attributes.h \
agg2d.h agg2d.inl \
bios.cpp bios.h bits.h cp15.cpp cp15.h \
commandline.h commandline.cpp \
@ -92,6 +93,44 @@ libdesmume_a_SOURCES = \
version.cpp version.h \
desmume_config.cpp desmume_config.h
if HAVE_JIT
libdesmume_a_SOURCES += \
utils/AsmJit/ApiBegin.h \
utils/AsmJit/ApiEnd.h \
utils/AsmJit/AsmJit.h \
utils/AsmJit/Assembler.h \
utils/AsmJit/AssemblerX86X64.cpp \
utils/AsmJit/AssemblerX86X64.h \
utils/AsmJit/Build.h \
utils/AsmJit/CodeGenerator.cpp \
utils/AsmJit/CodeGenerator.h \
utils/AsmJit/Compiler.cpp \
utils/AsmJit/Compiler.h \
utils/AsmJit/CompilerX86X64.cpp \
utils/AsmJit/CompilerX86X64.h \
utils/AsmJit/Config.h \
utils/AsmJit/CpuInfo.cpp \
utils/AsmJit/CpuInfo.h \
utils/AsmJit/Defs.cpp \
utils/AsmJit/Defs.h \
utils/AsmJit/DefsX86X64.cpp \
utils/AsmJit/DefsX86X64.h \
utils/AsmJit/Logger.cpp \
utils/AsmJit/Logger.h \
utils/AsmJit/MemoryManager.cpp \
utils/AsmJit/MemoryManager.h \
utils/AsmJit/MemoryMarker.cpp \
utils/AsmJit/MemoryMarker.h \
utils/AsmJit/Operand.h \
utils/AsmJit/OperandX86X64.cpp \
utils/AsmJit/OperandX86X64.h \
utils/AsmJit/Platform.cpp \
utils/AsmJit/Platform.h \
utils/AsmJit/Util.cpp \
utils/AsmJit/Util.h \
utils/AsmJit/Util_p.h
endif
if HAVE_GL
libdesmume_a_SOURCES += OGLRender.cpp
endif

View File

@ -30,6 +30,7 @@
#include "gfx3d.h"
#include "utils/decrypt/decrypt.h"
#include "utils/decrypt/crc.h"
#include "cp15.h"
#include "bios.h"
#include "debug.h"
#include "cheatSystem.h"
@ -47,6 +48,7 @@
//#define LOG_ARM9
//#define LOG_ARM7
//#define dolog (currFrameCounter>15)
//bool dolog=true;
//#define LOG_TO_FILE
//#define LOG_TO_FILE_REGS
@ -332,7 +334,7 @@ const RomBanner& GameInfo::getRomBanner()
void GameInfo::populate()
{
const char *regions[] = { "JPFSEDIRKH",
const char *regions[] = { "JPFSEDIRKHX",
"JPN",
"EUR",
"FRA",
@ -343,6 +345,7 @@ void GameInfo::populate()
"RUS",
"KOR",
"HOL",
"EUU",
};
@ -1937,7 +1940,11 @@ static FORCEINLINE s32 minarmtime(s32 arm9, s32 arm7)
return arm7;
}
#ifdef HAVE_JIT
template<bool doarm9, bool doarm7, bool jit>
#else
template<bool doarm9, bool doarm7>
#endif
static /*donotinline*/ std::pair<s32,s32> armInnerLoop(
const u64 nds_timer_base, const s32 s32next, s32 arm9, s32 arm7)
{
@ -1950,7 +1957,11 @@ static /*donotinline*/ std::pair<s32,s32> armInnerLoop(
{
arm9log();
debug();
#ifdef HAVE_JIT
arm9 += armcpu_exec<ARMCPU_ARM9,jit>();
#else
arm9 += armcpu_exec<ARMCPU_ARM9>();
#endif
#ifdef DEVELOPER
nds_debug_continuing[0] = false;
#endif
@ -1968,7 +1979,11 @@ static /*donotinline*/ std::pair<s32,s32> armInnerLoop(
if(!NDS_ARM7.waitIRQ&&!nds.freezeBus)
{
arm7log();
#ifdef HAVE_JIT
arm7 += (armcpu_exec<ARMCPU_ARM7,jit>()<<1);
#else
arm7 += (armcpu_exec<ARMCPU_ARM7>()<<1);
#endif
#ifdef DEVELOPER
nds_debug_continuing[1] = false;
#endif
@ -1981,7 +1996,11 @@ static /*donotinline*/ std::pair<s32,s32> armInnerLoop(
if(arm7 == s32next)
{
nds_timer = nds_timer_base + minarmtime<doarm9,false>(arm9,arm7);
#ifdef HAVE_JIT
return armInnerLoop<doarm9,false,jit>(nds_timer_base, s32next, arm9, arm7);
#else
return armInnerLoop<doarm9,false>(nds_timer_base, s32next, arm9, arm7);
#endif
}
}
}
@ -2085,7 +2104,13 @@ void NDS_exec(s32 nb)
}
#endif
std::pair<s32,s32> arm9arm7 = armInnerLoop<true,true>(nds_timer_base,s32next,arm9,arm7);
#ifdef HAVE_JIT
std::pair<s32,s32> arm9arm7 = CommonSettings.use_jit
? armInnerLoop<true,true,true>(nds_timer_base,s32next,arm9,arm7)
: armInnerLoop<true,true,false>(nds_timer_base,s32next,arm9,arm7);
#else
std::pair<s32,s32> arm9arm7 = armInnerLoop<true,true>(nds_timer_base,s32next,arm9,arm7);
#endif
#ifdef DEVELOPER
if(singleStep)
@ -2237,11 +2262,16 @@ void NDS_Reset()
// }
//}
#ifdef HAVE_JIT
arm_jit_reset(CommonSettings.use_jit);
#endif
NDS_ARM7.BIOS_loaded = false;
NDS_ARM9.BIOS_loaded = false;
memset(MMU.ARM7_BIOS, 0, sizeof(MMU.ARM7_BIOS));
memset(MMU.ARM9_BIOS, 0, sizeof(MMU.ARM9_BIOS));
NDS_ARM7.swi_tab = 0;
NDS_ARM9.swi_tab = 0;
//ARM7 BIOS IRQ HANDLER
if(CommonSettings.UseExtBIOS == true)
@ -2255,7 +2285,7 @@ void NDS_Reset()
fclose(inf);
if((CommonSettings.SWIFromBIOS) && (NDS_ARM7.BIOS_loaded)) NDS_ARM7.swi_tab = 0;
else NDS_ARM7.swi_tab = ARM7_swi_tab;
else NDS_ARM7.swi_tab = ARM_swi_tab[ARMCPU_ARM7];
if (CommonSettings.PatchSWI3)
_MMU_write16<ARMCPU_ARM7>(0x00002F08, 0x4770);
@ -2264,7 +2294,7 @@ void NDS_Reset()
}
else
{
NDS_ARM7.swi_tab = ARM7_swi_tab;
NDS_ARM7.swi_tab = ARM_swi_tab[ARMCPU_ARM7];
#if 0
// TODO
@ -2298,7 +2328,7 @@ void NDS_Reset()
fclose(inf);
if((CommonSettings.SWIFromBIOS) && (NDS_ARM9.BIOS_loaded)) NDS_ARM9.swi_tab = 0;
else NDS_ARM9.swi_tab = ARM9_swi_tab;
else NDS_ARM9.swi_tab = ARM_swi_tab[ARMCPU_ARM9];
if (CommonSettings.PatchSWI3)
_MMU_write16<ARMCPU_ARM9>(0xFFFF07CC, 0x4770);
@ -2307,7 +2337,7 @@ void NDS_Reset()
}
else
{
NDS_ARM9.swi_tab = ARM9_swi_tab;
NDS_ARM9.swi_tab = ARM_swi_tab[ARMCPU_ARM9];
//bios chains data abort to fast irq
@ -2460,6 +2490,10 @@ void NDS_Reset()
_MMU_write08<ARMCPU_ARM9>(REG_POSTFLG, 1);
_MMU_write08<ARMCPU_ARM7>(REG_POSTFLG, 1);
}
// only ARM9 have co-processor
reconstruct(&cp15);
cp15.reset(&NDS_ARM9);
//bitbox 4k demo is so stripped down it relies on default stack values
//otherwise the arm7 will crash before making a sound
//(these according to gbatek softreset bios docs)

View File

@ -523,6 +523,11 @@ extern struct TCommonSettings {
for(int g=0;g<2;g++)
for(int x=0;x<5;x++)
dispLayers[g][x]=true;
#ifdef HAVE_JIT
use_jit = true;
#else
use_jit = false;
#endif
}
bool GFX3D_HighResolutionInterpolateColor;
bool GFX3D_EdgeMark;
@ -557,6 +562,8 @@ extern struct TCommonSettings {
bool dispLayers[2][5];
FAST_ALIGN bool advanced_timing;
bool use_jit;
struct _Wifi {
int mode;

View File

@ -31,7 +31,6 @@
#include "MMU.h"
#include "armcpu.h"
#include "NDSSystem.h"
#include "arm_instructions.h"
#include "MMU_timing.h"
#define cpu (&ARMPROC)
@ -1900,10 +1899,13 @@ TEMPLATE static u32 FASTCALL OP_ORR_S_IMM_VAL(const u32 i)
cpu->CPSR.bits.C = c; \
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \
return a; \
return a;
TEMPLATE static u32 FASTCALL OP_MOV_LSL_IMM(const u32 i)
{
if (i == 0xE1A00000) // nop: MOV R0, R0
return 1;
LSL_IMM;
OP_MOV(1,3);
}
@ -2975,228 +2977,99 @@ TEMPLATE static u32 FASTCALL OP_MRS_SPSR(const u32 i)
return 1;
}
#define v4_UNALLOC_MASK 0x0FFFFF00
#define v4_USER_MASK 0xF0000000
#define v4_PRIV_MASK 0x0000000F
#define v4_STATE_MASK 0x00000020
#define v5_UNALLOC_MASK 0x07FFFF00
#define v5_USER_MASK 0xF8000000
#define v5_PRIV_MASK 0x0000000F
#define v5_STATE_MASK 0x00000020
#define OP_MSR_CPSR_(operand) \
u32 byte_mask = (cpu->CPSR.bits.mode == USR)?(BIT19(i)?0xFF000000:0x00000000): \
(BIT16(i)?0x000000FF:0x00000000) | \
(BIT17(i)?0x0000FF00:0x00000000) | \
(BIT18(i)?0x00FF0000:0x00000000) | \
(BIT19(i)?0xFF000000:0x00000000); \
if(cpu->CPSR.bits.mode != USR && BIT16(i)) \
{ armcpu_switchMode(cpu, operand & 0x1F); } \
cpu->CPSR.val = (cpu->CPSR.val & ~byte_mask) | (operand & byte_mask); \
cpu->changeCPSR();
#define OP_MSR_SPSR_(operand) \
if(cpu->CPSR.bits.mode == USR || cpu->CPSR.bits.mode == SYS) return 1; \
u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | \
(BIT17(i)?0x0000FF00:0x00000000) | \
(BIT18(i)?0x00FF0000:0x00000000) | \
(BIT19(i)?0xFF000000:0x00000000); \
cpu->SPSR.val = (cpu->SPSR.val & ~byte_mask) | (operand & byte_mask); \
cpu->changeCPSR();
//#define __NEW_MSR
#ifdef __NEW_MSR
#define v4T_UNALLOC_MASK 0x0FFFFF00
#define v4T_USER_MASK 0xF0000000
#define v4T_PRIV_MASK 0x0000000F
#define v4T_STATE_MASK 0x00000020
#define v5TE_UNALLOC_MASK 0x07FFFF00
#define v5TE_USER_MASK 0xF8000000
#define v5TE_PRIV_MASK 0x0000000F
#define v5TE_STATE_MASK 0x00000020
#endif
TEMPLATE static u32 FASTCALL OP_MSR_CPSR(const u32 i)
{
u32 operand = cpu->R[REG_POS(i,0)];
#if 0
// TODO
#ifdef __NEW_MSR
u32 mask = 0;
u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) |
(BIT17(i)?0x0000FF00:0x00000000) |
(BIT18(i)?0x00FF0000:0x00000000) |
(BIT19(i)?0xFF000000:0x00000000);
if (PROCNUM == 0)
const u32 unallocMask = PROCNUM?v4T_UNALLOC_MASK: v5TE_UNALLOC_MASK;
const u32 userMask = PROCNUM?v4T_USER_MASK : v5TE_USER_MASK;
const u32 privMask = PROCNUM?v4T_PRIV_MASK : v5TE_PRIV_MASK;
const u32 stateMask = PROCNUM?v4T_STATE_MASK : v5TE_STATE_MASK;
if ((operand & unallocMask) != 0) printf("ARM%c: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", PROCNUM?'7':'9', operand);
if (cpu->CPSR.bits.mode != USR) // Privileged mode
{
if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
if (cpu->CPSR.bits.mode != USR) // Privileged mode
{
if ((operand & v5_STATE_MASK) != 0) printf("ARM9: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", operand);
mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK);
}
if (BIT16(i)) armcpu_switchMode(cpu, operand & 0x1F);
if ((operand & stateMask) != 0)
printf("ARM%c: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", PROCNUM?'7':'9', operand);
else
mask = byte_mask & v5_USER_MASK;
mask = byte_mask & (userMask | privMask);
}
else
{
if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
if(cpu->CPSR.bits.mode != USR) // Privileged mode
{
if ((operand & v4_STATE_MASK) != 0) printf("ARM7: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", operand);
mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK);
}
else
mask = byte_mask & v4_USER_MASK;
}
mask = byte_mask & userMask;
u32 new_val = ((cpu->CPSR.val & (~mask)) | (operand & mask));
cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask));
if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode);
cpu->changeCPSR();
#else
if(cpu->CPSR.bits.mode!=USR)
{
if(BIT16(i))
{
armcpu_switchMode(cpu, operand & 0x1F);
cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF);
}
if(BIT17(i))
cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00);
if(BIT18(i))
cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000);
}
if(BIT19(i))
cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000);
cpu->changeCPSR();
OP_MSR_CPSR_(operand);
#endif
return 1;
}
TEMPLATE static u32 FASTCALL OP_MSR_SPSR(const u32 i)
{
//printf("OP_MSR_SPSR\n");
u32 operand = cpu->R[REG_POS(i,0)];
#if 0
// TODO
u32 mask = 0;
u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) |
(BIT17(i)?0x0000FF00:0x00000000) |
(BIT18(i)?0x00FF0000:0x00000000) |
(BIT19(i)?0xFF000000:0x00000000);
if (PROCNUM == 0)
{
if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_SPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
// if CurrentModeHasSPSR
mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK | v5_STATE_MASK);
}
else
{
if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_SPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
// if CurrentModeHasSPSR
mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK);
}
cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask));
cpu->changeCPSR();
#else
if(cpu->CPSR.bits.mode!=USR)
{
if(BIT16(i))
{
cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0xFF);
}
if(BIT17(i))
cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0xFF00);
if(BIT18(i))
cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0xFF0000);
}
if(BIT19(i))
cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0xFF000000);
cpu->changeCPSR();
#endif
OP_MSR_SPSR_(operand);
return 1;
}
TEMPLATE static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(const u32 i)
{
//printf("OP_MSR_CPSR_IMM_VAL\n");
IMM_VALUE;
#if 0
// TODO
u32 operand = shift_op;
u32 mask = 0;
u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) |
(BIT17(i)?0x0000FF00:0x00000000) |
(BIT18(i)?0x00FF0000:0x00000000) |
(BIT19(i)?0xFF000000:0x00000000);
if (PROCNUM == 0)
{
if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_CPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
if (cpu->CPSR.bits.mode != USR) // Privileged mode
{
if ((operand & v5_STATE_MASK) != 0) printf("ARM9: MSR_CPSR_IMM UNPREDICTABLE STATE (operand %08X)\n", operand);
mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK);
}
else
mask = byte_mask & v5_USER_MASK;
}
else
{
if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_CPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
if(cpu->CPSR.bits.mode != USR) // Privileged mode
{
if ((operand & v4_STATE_MASK) != 0) printf("ARM7: MSR_CPSR_IMM UNPREDICTABLE STATE (operand %08X)\n", operand);
mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK);
}
else
mask = byte_mask & v4_USER_MASK;
}
cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask));
if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode);
cpu->changeCPSR();
#else
if(cpu->CPSR.bits.mode!=USR)
{
if(BIT16(i))
{
armcpu_switchMode(cpu, shift_op & 0x1F);
cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0xFF);
}
if(BIT17(i))
cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0xFF00);
if(BIT18(i))
cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0xFF0000);
}
if(BIT19(i))
{
//cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0xFF000000);
cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000);
}
cpu->changeCPSR();
#endif
OP_MSR_CPSR_(shift_op);
return 1;
}
TEMPLATE static u32 FASTCALL OP_MSR_SPSR_IMM_VAL(const u32 i)
{
//printf("OP_MSR_SPSR_IMM_VAL\n");
IMM_VALUE;
#if 0
// TODO
u32 operand = shift_op;
u32 mask = 0;
u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) |
(BIT17(i)?0x0000FF00:0x00000000) |
(BIT18(i)?0x00FF0000:0x00000000) |
(BIT19(i)?0xFF000000:0x00000000);
if (PROCNUM == 0)
{
if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_SPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
// if CurrentModeHasSPSR
mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK | v5_STATE_MASK);
}
else
{
if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_SPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand);
// if CurrentModeHasSPSR
mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK);
}
cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask));
#else
if(cpu->CPSR.bits.mode!=USR)
{
if(BIT16(i))
{
cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0xFF);
}
if(BIT17(i))
cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0xFF00);
if(BIT18(i))
cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0xFF0000);
}
if(BIT19(i))
{
cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0xFF000000);
}
cpu->changeCPSR();
#endif
OP_MSR_SPSR_(shift_op);
return 1;
}
@ -3314,7 +3187,7 @@ TEMPLATE static u32 FASTCALL OP_CLZ(const u32 i)
CLZ_TAB[(Rm>>28)&0xF];
cpu->R[REG_POS(i,12)]=32 - pos;
return 2;
}
@ -3369,7 +3242,6 @@ TEMPLATE static u32 FASTCALL OP_QDADD(const u32 i)
u32 mul = cpu->R[REG_POS(i,16)]<<1;
u32 res;
//LOG("spe add\n");
if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul))
{
@ -3399,7 +3271,6 @@ TEMPLATE static u32 FASTCALL OP_QDSUB(const u32 i)
u32 mul = cpu->R[REG_POS(i,16)]<<1;
u32 res;
//LOG("spe add\n");
if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul))
{
@ -3486,7 +3357,7 @@ TEMPLATE static u32 FASTCALL OP_SMLA_B_T(const u32 i)
u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
u32 a = cpu->R[REG_POS(i,12)];
//INFO("SMLABT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
//INFO("SMLABT R%d:%08X * R%d:%08X + R%d:%08X = %08X\n", REG_POS(i,0), cpu->R[REG_POS(i,0)], REG_POS(i,8), cpu->R[REG_POS(i,8)], REG_POS(i,12), a, tmp + a);
cpu->R[REG_POS(i,16)] = tmp + a;
if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
@ -3650,7 +3521,7 @@ TEMPLATE static u32 FASTCALL OP_SMLAW_T(const u32 i)
\
if(REG_POS(i,12)==15) \
{ \
if (cpu->LDTBit) \
if (PROCNUM == 0) \
{ \
cpu->CPSR.bits.T = BIT0(cpu->R[15]); \
cpu->R[15] &= 0xFFFFFFFE; \
@ -3672,7 +3543,7 @@ TEMPLATE static u32 FASTCALL OP_SMLAW_T(const u32 i)
\
if(REG_POS(i,12)==15) \
{ \
if (cpu->LDTBit) \
if (PROCNUM == 0) \
{ \
cpu->CPSR.bits.T = BIT0(cpu->R[15]); \
cpu->R[15] &= 0xFFFFFFFE; \
@ -3695,7 +3566,7 @@ TEMPLATE static u32 FASTCALL OP_SMLAW_T(const u32 i)
\
if(REG_POS(i,12)==15) \
{ \
if (cpu->LDTBit) \
if (PROCNUM == 0) \
{ \
cpu->CPSR.bits.T = BIT0(cpu->R[15]); \
cpu->R[15] &= 0xFFFFFFFE; \
@ -3723,13 +3594,6 @@ TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF(const u32 i)
OP_LDR(3, 5);
}
TEMPLATE static u32 FASTCALL OP_LDREX(const u32 i)
{
u32 adr = cpu->R[REG_POS(i,16)];
cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3));
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3,adr);
}
TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF(const u32 i)
{
LSL_IMM;
@ -3912,6 +3776,17 @@ TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(const u32 i)
OP_LDR_W2(3, 5, -shift_op);
}
//-----------------------------------------------------------------------------
// LDREX
//-----------------------------------------------------------------------------
TEMPLATE static u32 FASTCALL OP_LDREX(const u32 i)
{
printf("LDREX\n");
u32 adr = cpu->R[REG_POS(i,16)];
cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3));
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3,adr);
}
//-----------------------------------------------------------------------------
// LDRB
//-----------------------------------------------------------------------------
@ -4220,15 +4095,6 @@ TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF(const u32 i)
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr);
}
TEMPLATE static u32 FASTCALL OP_STREX(const u32 i)
{
u32 adr = cpu->R[REG_POS(i,16)];
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]);
cpu->R[REG_POS(i,12)] = 0;
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr);
}
TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF(const u32 i)
{
LSL_IMM;
@ -4497,6 +4363,19 @@ TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_POSTIND(const u32 i)
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr);
}
//-----------------------------------------------------------------------------
// STREX
//-----------------------------------------------------------------------------
TEMPLATE static u32 FASTCALL OP_STREX(const u32 i)
{
printf("STREX\n");
u32 adr = cpu->R[REG_POS(i,16)];
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]);
cpu->R[REG_POS(i,12)] = 0;
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr);
}
//-----------------------------------------------------------------------------
// STRB
//-----------------------------------------------------------------------------
@ -4857,7 +4736,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIA(const u32 i)
// T Bit = value[0]
//else
// pc = value AND 0xFFFFFFFC
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -4901,7 +4780,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIB(const u32 i)
start += 4;
c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start);
u32 tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -4925,7 +4804,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDA(const u32 i)
if(BIT15(i))
{
u32 tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -4967,7 +4846,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDB(const u32 i)
{
start -= 4;
u32 tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -5002,9 +4881,8 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_W(const u32 i)
u32 c = 0;
u32 start = cpu->R[REG_POS(i,16)];
u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
u32 * registres = cpu->R;
OP_L_IA(0, start);
OP_L_IA(1, start);
OP_L_IA(2, start);
@ -5024,7 +4902,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_W(const u32 i)
if(BIT15(i))
{
u32 tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -5043,7 +4921,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_W(const u32 i)
else
cpu->R[REG_POS(i,16)] = start;
return MMU_aluMemCycles<PROCNUM>(2, c);
return MMU_aluMemCycles<PROCNUM>(BIT15(i)?4:2, c);
}
TEMPLATE static u32 FASTCALL OP_LDMIB_W(const u32 i)
@ -5076,7 +4954,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIB_W(const u32 i)
start += 4;
c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start);
tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -5093,10 +4971,7 @@ TEMPLATE static u32 FASTCALL OP_LDMIB_W(const u32 i)
else
cpu->R[REG_POS(i,16)] = start;
if(BIT15(i))
return MMU_aluMemCycles<PROCNUM>(4, c);
else
return MMU_aluMemCycles<PROCNUM>(2, c);
return MMU_aluMemCycles<PROCNUM>(BIT15(i)?4:2, c);
}
TEMPLATE static u32 FASTCALL OP_LDMDA_W(const u32 i)
@ -5110,7 +4985,7 @@ TEMPLATE static u32 FASTCALL OP_LDMDA_W(const u32 i)
if(BIT15(i))
{
u32 tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE;
@ -5160,10 +5035,11 @@ TEMPLATE static u32 FASTCALL OP_LDMDB_W(const u32 i)
u32 tmp;
start -= 4;
tmp = READ32(cpu->mem_if->data, start);
if (cpu->LDTBit)
if (PROCNUM == 0)
{
cpu->CPSR.bits.T = BIT0(tmp);
registres[15] = tmp & 0xFFFFFFFE; }
registres[15] = tmp & 0xFFFFFFFE;
}
else
registres[15] = tmp & 0xFFFFFFFC;
cpu->next_instruction = registres[15];
@ -6239,7 +6115,7 @@ TEMPLATE static u32 FASTCALL OP_MCR(const u32 i)
{
u32 cpnum = REG_POS(i, 8);
if(!cpu->coproc[cpnum])
if(cpnum != 15)
{
//emu_halt();
//INFO("Stopped (OP_MCR) \n");
@ -6248,8 +6124,8 @@ TEMPLATE static u32 FASTCALL OP_MCR(const u32 i)
return 2;
}
armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
//cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
cp15.moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
return 2;
}
@ -6259,7 +6135,7 @@ TEMPLATE static u32 FASTCALL OP_MRC(const u32 i)
u32 cpnum = REG_POS(i, 8);
if(!cpu->coproc[cpnum])
if(cpnum != 15)
{
//emu_halt();
//INFO("Stopped (OP_MRC) \n");
@ -6278,8 +6154,8 @@ TEMPLATE static u32 FASTCALL OP_MRC(const u32 i)
//else /* Rd is not R15 */
// Rd = data
u32 data = 0;
armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &data, REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
u32 data = 0;
cp15.moveCP2ARM(&data, REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7);
if (REG_POS(i, 12) == 15)
{
cpu->CPSR.bits.N = BIT31(data);
@ -6300,7 +6176,7 @@ TEMPLATE static u32 FASTCALL OP_MRC(const u32 i)
TEMPLATE static u32 FASTCALL OP_SWI(const u32 i)
{
u32 swinum = (i>>16)&0xFF;
//ideas-style debug prints (execute this SWI with the null terminated string address in R0)
if(swinum==0xFC)
{
@ -6335,7 +6211,7 @@ TEMPLATE static u32 FASTCALL OP_SWI(const u32 i)
cpu->changeCPSR();
cpu->R[15] = cpu->intVector + 0x08;
cpu->next_instruction = cpu->R[15];
return 4;
return 3;
}
}
@ -6345,6 +6221,21 @@ TEMPLATE static u32 FASTCALL OP_SWI(const u32 i)
TEMPLATE static u32 FASTCALL OP_BKPT(const u32 i)
{
/* ARM-ref
if (not overridden by debug hardware)
R14_abt = address of BKPT instruction + 4
SPSR_abt = CPSR
CPSR[4:0] = 0b10111 // Enter Abort mode
CPSR[5] = 0 // Execute in ARM state
// CPSR[6] is unchanged
CPSR[7] = 1 // Disable normal interrupts
CPSR[8] = 1 // Disable imprecise aborts - v6 only
CPSR[9] = CP15_reg1_EEbit
if high vectors configured then
PC = 0xFFFF000C
else
PC = 0x0000000C
*/
static u32 last_bkpt = 0xFFFFFFFF;
if(i != last_bkpt)
printf("ARM OP_BKPT triggered\n");
@ -6369,17 +6260,15 @@ TEMPLATE static u32 FASTCALL OP_CDP(const u32 i)
// The End
//-----------------------------------------------------------------------------
const OpFunc arm_instructions_set[2][4096] = {{
#define TABDECL(x) x<0>
const ArmOpFunc arm_instructions_set_0[4096] = {
#include "instruction_tabdef.inc"
};
#undef TABDECL
},{
#define TABDECL(x) x<1>
const ArmOpFunc arm_instructions_set_1[4096] = {
#include "instruction_tabdef.inc"
};
#undef TABDECL
}};
#define TABDECL(x) #x
const char* arm_instruction_names[4096] = {

View File

@ -1,32 +0,0 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2009 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARMINSTRUCTION_H
#define ARMINSTRUCTION_H
#include "armcpu.h"
typedef u32 (FASTCALL* ArmOpFunc)(const u32 i);
extern const ArmOpFunc arm_instructions_set_0[4096];
extern const ArmOpFunc arm_instructions_set_1[4096];
extern const char* arm_instruction_names[4096];
#endif

4216
desmume/src/arm_jit.cpp Normal file

File diff suppressed because it is too large Load Diff

65
desmume/src/arm_jit.h Normal file
View File

@ -0,0 +1,65 @@
/* Copyright (C) 2006 yopyop
Copyright (C) 2011 Loren Merritt
Copyright (C) 2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARM_JIT
#define ARM_JIT
#include "types.h"
typedef u32 (FASTCALL* ArmOpCompiled)();
void arm_jit_reset(bool enable);
void arm_jit_sync();
template<int PROCNUM> u32 arm_jit_compile();
#ifdef _WINDOWS
#define MAPPED_JIT_FUNCS
#endif
#ifdef MAPPED_JIT_FUNCS
struct JIT_struct
{
// only include the memory types that code can execute from
uintptr_t MAIN_MEM[16*1024*1024/2];
uintptr_t SWIRAM[0x8000/2];
uintptr_t ARM9_ITCM[0x8000/2];
uintptr_t ARM9_LCDC[0xA4000/2];
uintptr_t ARM9_BIOS[0x8000/2];
uintptr_t ARM7_BIOS[0x4000/2];
uintptr_t ARM7_ERAM[0x10000/2];
uintptr_t ARM7_WIRAM[0x10000/2];
uintptr_t ARM7_WRAM[0x40000/2];
static uintptr_t *JIT_MEM[2][0x4000];
};
extern CACHE_ALIGN JIT_struct JIT;
#define JIT_COMPILED_FUNC(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][((adr)&0x0FFFC000)>>14][((adr)&0x00003FFE)>>1]
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT.JIT_MEM[PROCNUM][(adr)>>14][(((adr)&0x00003FFE)>>1)+ofs]
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT.bank[(((adr)&(mask))>>1)+ofs]
#define JIT_MAPPED(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][(adr)>>14]
#else
// actually an array of function pointers, but they fit in 32bit address space, so might as well save memory
extern uintptr_t compiled_funcs[];
// there isn't anything mapped between 07000000 and 0EFFFFFF, so we can mask off bit 27 and get away with a smaller array
#define JIT_COMPILED_FUNC(adr, PROCNUM) compiled_funcs[((adr) & 0x07FFFFFE) >> 1]
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT_COMPILED_FUNC(adr, PROCNUM)
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT_COMPILED_FUNC(adr, PROCNUM)
#define JIT_MAPPED(adr, PROCNUM) true
#endif
#endif

View File

@ -21,8 +21,7 @@
#include <assert.h>
#include <algorithm>
#include "types.h"
#include "arm_instructions.h"
#include "thumb_instructions.h"
#include "instructions.h"
#include "cp15.h"
#include "bios.h"
#include "debug.h"
@ -32,6 +31,9 @@
#ifdef HAVE_LUA
#include "lua-engine.h"
#endif
#ifdef HAVE_JIT
#include "arm_jit.h"
#endif
template<u32> static u32 armcpu_prefetch();
@ -40,57 +42,6 @@ FORCEINLINE u32 armcpu_prefetch(armcpu_t *armcpu) {
else return armcpu_prefetch<1>();
}
const unsigned char arm_cond_table[16*16] = {
/* N=0, Z=0, C=0, V=0 */
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=0, Z=0, C=0, V=1 */
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=0, Z=0, C=1, V=0 */
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=0, Z=0, C=1, V=1 */
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=0, V=0 */
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=0, V=1 */
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=1, V=0 */
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
/* N=0, Z=1, C=1, V=1 */
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=0, C=0, V=0 */
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=0, C=0, V=1 */
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00,
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=1, Z=0, C=1, V=0 */
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF,
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=0, C=1, V=1 */
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00,
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
/* N=1, Z=1, C=0, V=0 */
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=1, C=0, V=1 */
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
/* N=1, Z=1, C=1, V=0 */
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
/* N=1, Z=1, C=1, V=1 */
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
};
armcpu_t NDS_ARM7;
armcpu_t NDS_ARM9;
@ -216,7 +167,7 @@ void armcpu_t::changeCPSR()
void armcpu_init(armcpu_t *armcpu, u32 adr)
{
armcpu->LDTBit = (armcpu->proc_ID==0); //arm9 is ARMv5 style. this should be renamed, or more likely, all references to this should poll a function to return an architecture level enum
armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load
armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
armcpu->waitIRQ = FALSE;
armcpu->halt_IE_and_IF = FALSE;
@ -227,11 +178,7 @@ void armcpu_init(armcpu_t *armcpu, u32 adr)
//#endif
for(int i = 0; i < 16; ++i)
{
armcpu->R[i] = 0;
if(armcpu->coproc[i]) free(armcpu->coproc[i]);
armcpu->coproc[i] = NULL;
}
armcpu->CPSR.val = armcpu->SPSR.val = SYS;
@ -253,10 +200,6 @@ void armcpu_init(armcpu_t *armcpu, u32 adr)
armcpu->next_instruction = adr;
// only ARM9 have co-processor
if (armcpu->proc_ID==0)
armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu);
//#ifndef GDB_STUB
armcpu_prefetch(armcpu);
//#endif
@ -361,8 +304,9 @@ u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
armcpu->SPSR = armcpu->SPSR_und;
break;
default :
break;
default :
printf("switchMode: WRONG mode %02X\n",mode);
break;
}
armcpu->CPSR.bits.mode = mode & 0x1F;
@ -666,18 +610,10 @@ u32 armcpu_exec()
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false?
#endif
if(PROCNUM==0) {
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[0].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
#endif
cExecute = arm_instructions_set_0[INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction);
}
else {
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[1].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
#endif
cExecute = arm_instructions_set_1[INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction);
}
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
#endif
cExecute = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction);
}
else
cExecute = 1; // If condition=false: 1S cycle
@ -695,19 +631,10 @@ u32 armcpu_exec()
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC);
#endif
if(PROCNUM==0)
{
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[0].thumb[ARMPROC.instruction>>6]++;
#endif
cExecute = thumb_instructions_set_0[ARMPROC.instruction>>6](ARMPROC.instruction);
}
else {
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[1].thumb[ARMPROC.instruction>>6]++;
#endif
cExecute = thumb_instructions_set_1[ARMPROC.instruction>>6](ARMPROC.instruction);
}
#ifdef DEVELOPER
DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++;
#endif
cExecute = thumb_instructions_set[PROCNUM][ARMPROC.instruction>>6](ARMPROC.instruction);
#ifdef GDB_STUB
if ( ARMPROC.post_ex_fn != NULL) {
@ -723,3 +650,31 @@ u32 armcpu_exec()
//these templates needed to be instantiated manually
template u32 armcpu_exec<0>();
template u32 armcpu_exec<1>();
#ifdef HAVE_JIT
void arm_jit_sync()
{
NDS_ARM7.next_instruction = NDS_ARM7.instruct_adr;
NDS_ARM9.next_instruction = NDS_ARM9.instruct_adr;
armcpu_prefetch<0>();
armcpu_prefetch<1>();
}
template<int PROCNUM, bool jit>
u32 armcpu_exec()
{
if (jit)
{
ArmOpCompiled f = (ArmOpCompiled)JIT_COMPILED_FUNC(ARMPROC.instruct_adr, PROCNUM);
return f ? f() : arm_jit_compile<PROCNUM>();
}
return armcpu_exec<PROCNUM>();
}
template u32 armcpu_exec<0,false>();
template u32 armcpu_exec<0,true>();
template u32 armcpu_exec<1,false>();
template u32 armcpu_exec<1,true>();
#endif

View File

@ -23,6 +23,8 @@
#include "bits.h"
#include "MMU.h"
#include "common.h"
#include "instructions.h"
#include "cp15.h"
#define CODE(i) (((i)>>25)&0x7)
#define OPCODE(i) (((i)>>21)&0xF)
@ -95,7 +97,56 @@ inline bool OverflowFromSUB(s32 alu_out, s32 left, s32 right)
//#define LE 0xD
//#define AL 0xE
extern const unsigned char arm_cond_table[16*16];
static const u8 arm_cond_table[16*16] = {
// N=0, Z=0, C=0, V=0
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x00
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, // 0x00
// N=0, Z=0, C=0, V=1
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x10
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=0, Z=0, C=1, V=0
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x20
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
// N=0, Z=0, C=1, V=1
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x30
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=0, V=0
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x40
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=0, V=1
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x50
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=1, V=0
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x60
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
// N=0, Z=1, C=1, V=1
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x70
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=0, C=0, V=0
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0x80
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=0, C=0, V=1
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0x90
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
// N=1, Z=0, C=1, V=0
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xA0
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=0, C=1, V=1
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xB0
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
// N=1, Z=1, C=0, V=0
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0xC0
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=1, C=0, V=1
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0xD0
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
// N=1, Z=1, C=1, V=0
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xE0
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
// N=1, Z=1, C=1, V=1
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xF0
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20
};
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst)))
@ -201,8 +252,6 @@ struct armcpu_t
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
armcp_t *coproc[16];
u32 intVector;
u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 (earlier)
BOOL waitIRQ;
@ -213,8 +262,17 @@ struct armcpu_t
u32 (* *swi_tab)();
// flag indicating if the processor is stalled (for debugging)
int stalled;
// flag indicating if the processor is stalled (for debugging)
int stalled;
#if defined(_M_X64) || defined(__x86_64__)
u8 cond_table[16*16];
armcpu_t()
{
memcpy(&cond_table[0], &arm_cond_table[0], sizeof(arm_cond_table));
}
#endif
#ifdef GDB_STUB
/** there is a pending irq for the cpu */
@ -246,8 +304,6 @@ void armcpu_init(armcpu_t *armcpu, u32 adr);
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
template<int PROCNUM> u32 armcpu_exec();
BOOL armcpu_irqException(armcpu_t *armcpu);
BOOL armcpu_flagIrq( armcpu_t *armcpu);
void armcpu_exception(armcpu_t *cpu, u32 number);
@ -257,6 +313,10 @@ u32 armcpu_Wait4IRQ(armcpu_t *cpu);
extern armcpu_t NDS_ARM7;
extern armcpu_t NDS_ARM9;
template<int PROCNUM> u32 armcpu_exec();
#ifdef HAVE_JIT
template<int PROCNUM, bool jit> u32 armcpu_exec();
#endif
static INLINE void setIF(int PROCNUM, u32 flag)
{

View File

@ -199,9 +199,7 @@ TEMPLATE static u32 WaitByLoop()
//INFO("ARM%c: SWI 0x03 (WaitByLoop)\n", PROCNUM?'7':'9');
if (PROCNUM == ARMCPU_ARM9)
{
armcp15_t *cp = (armcp15_t*)(cpu->coproc[15]);
if (cp->ctrl & ((1<<16)|(1<<18))) // DTCM or ITCM is on (cache)
if (cp15.ctrl & ((1<<16)|(1<<18))) // DTCM or ITCM is on (cache)
elapsed = cpu->R[0] * 2;
else
elapsed = cpu->R[0] * 8;
@ -219,13 +217,13 @@ TEMPLATE static u32 wait4IRQ()
return 1;
}
TEMPLATE u32 intrWaitARM()
TEMPLATE static u32 intrWaitARM()
{
//TODO - account for differences between arm7 and arm9 (according to gbatek, the "bug doesn't work")
const u32 intrFlagAdr = (PROCNUM == ARMCPU_ARM7)
? 0x380FFF8
: (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
: (cp15.DTCMRegion&0xFFFFF000)+0x3FF8;
//set IME=1
//without this, no irq handlers can happen (even though IF&IE waits can happily happen)
@ -329,7 +327,7 @@ TEMPLATE static u32 copy()
break;
case 1:
{
u32 val = _MMU_read16<PROCNUM>(src);
u16 val = _MMU_read16<PROCNUM>(src);
cnt &= 0x1FFFFF;
while(cnt)
{
@ -1108,7 +1106,8 @@ TEMPLATE static u32 getBootProcs()
return 1;
}
u32 (* ARM9_swi_tab[32])()={
u32 (* ARM_swi_tab[2][32])()={
{
bios_nop<ARMCPU_ARM9>, // 0x00
bios_nop<ARMCPU_ARM9>, // 0x01
bios_nop<ARMCPU_ARM9>, // 0x02
@ -1141,9 +1140,8 @@ u32 (* ARM9_swi_tab[32])()={
bios_nop<ARMCPU_ARM9>, // 0x1D
bios_nop<ARMCPU_ARM9>, // 0x1E
setHaltCR<ARMCPU_ARM9>, // 0x1F
};
u32 (* ARM7_swi_tab[32])()={
},
{
bios_nop<ARMCPU_ARM7>, // 0x00
bios_nop<ARMCPU_ARM7>, // 0x01
bios_nop<ARMCPU_ARM7>, // 0x02
@ -1176,4 +1174,5 @@ u32 (* ARM7_swi_tab[32])()={
getBootProcs<ARMCPU_ARM7>, // 0x1D
bios_nop<ARMCPU_ARM7>, // 0x1E
setHaltCR<ARMCPU_ARM7>, // 0x1F
}
};

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2009 DeSmuME team
Copyright (C) 2006-2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -21,8 +21,7 @@
#include "armcpu.h"
extern u32 (* ARM9_swi_tab[32])();
extern u32 (* ARM7_swi_tab[32])();
extern u32 (* ARM_swi_tab[2][32])();;
#endif

View File

@ -49,6 +49,9 @@ CommandLine::CommandLine()
, _advanced_timing(-1)
, _slot1(NULL)
, _slot1_fat_dir(NULL)
#ifdef HAVE_JIT
, _cpu_mode(-1)
#endif
, _console_type(NULL)
, depth_threshold(-1)
, load_slot(-1)
@ -96,6 +99,9 @@ void CommandLine::loadCommonOptions()
{ "slot1-fat-dir", 0, 0, G_OPTION_ARG_STRING, &_slot1_fat_dir, "Directory to scan for slot 1", "SLOT1_DIR"},
{ "depth-threshold", 0, 0, G_OPTION_ARG_INT, &depth_threshold, "Depth comparison threshold (default 0)", "DEPTHTHRESHOLD"},
{ "console-type", 0, 0, G_OPTION_ARG_STRING, &_console_type, "Select console type: {fat,lite,ique,debug,dsi}", "CONSOLETYPE" },
#ifdef HAVE_JIT
{ "cpu-mode", 0, 0, G_OPTION_ARG_INT, &_cpu_mode, "ARM CPU emulation mode: 0 - interpreter, 1 - dynarec (default 1)", NULL},
#endif
#ifndef _MSC_VER
{ "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL},
{ "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL},
@ -136,6 +142,9 @@ bool CommandLine::parse(int argc,char **argv)
if(_num_cores != -1) CommonSettings.num_cores = _num_cores;
if(_rigorous_timing) CommonSettings.rigorous_timing = true;
if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1;
#ifdef HAVE_JIT
if(_cpu_mode != -1) CommonSettings.use_jit = (_cpu_mode==1);
#endif
if(depth_threshold != -1)
CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = depth_threshold;
@ -221,6 +230,11 @@ bool CommandLine::validate()
g_printerr("Invalid autodetect save method (0 - internal, 1 - from database)\n");
}
#ifdef HAVE_JIT
if (_cpu_mode < -1 || _cpu_mode > 1) {
g_printerr("Invalid cpu mode emulation (0 - interpreter, 1 - dynarec)\n");
}
#endif
return true;
}

View File

@ -19,6 +19,7 @@
#define _COMMANDLINE_H_
#include <string>
#include "types.h"
//I hate C. we have to forward declare these with more detail than I like
typedef struct _GOptionContext GOptionContext;
@ -89,6 +90,9 @@ private:
int _num_cores;
int _rigorous_timing;
int _advanced_timing;
#ifdef HAVE_JIT
int _cpu_mode;
#endif
char* _slot1;
char *_slot1_fat_dir;
char* _console_type;

View File

@ -22,60 +22,58 @@
#include "debug.h"
#include "MMU.h"
armcp15_t *armcp15_new(armcpu_t * c)
armcp15_t cp15;
bool armcp15_t::reset(armcpu_t * c)
{
int i;
armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t));
if(!armcp15) return NULL;
//printf("CP15 Reset\n");
cpu = c;
IDCode = 0x41059461;
cacheType = 0x0F0D2112;
TCMSize = 0x00140180;
ctrl = 0x00012078;
DCConfig = 0x0;
ICConfig = 0x0;
writeBuffCtrl = 0x0;
und = 0x0;
DaccessPerm = 0x22222222;
IaccessPerm = 0x22222222;
protectBaseSize0 = 0x0;
protectBaseSize1 = 0x0;
protectBaseSize2 = 0x0;
protectBaseSize3 = 0x0;
protectBaseSize4 = 0x0;
protectBaseSize5 = 0x0;
protectBaseSize6 = 0x0;
protectBaseSize7 = 0x0;
cacheOp = 0x0;
DcacheLock = 0x0;
IcacheLock = 0x0;
ITCMRegion = 0x0C;
DTCMRegion = 0x0080000A;
processID = 0;
armcp15->cpu = c;
armcp15->IDCode = 0x41059461;
armcp15->cacheType = 0x0F0D2112;
armcp15->TCMSize = 0x00140180;
armcp15->ctrl = 0x00012078;
armcp15->DCConfig = 0x0;
armcp15->ICConfig = 0x0;
armcp15->writeBuffCtrl = 0x0;
armcp15->und = 0x0;
armcp15->DaccessPerm = 0x22222222;
armcp15->IaccessPerm = 0x22222222;
armcp15->protectBaseSize0 = 0x0;
armcp15->protectBaseSize1 = 0x0;
armcp15->protectBaseSize2 = 0x0;
armcp15->protectBaseSize3 = 0x0;
armcp15->protectBaseSize4 = 0x0;
armcp15->protectBaseSize5 = 0x0;
armcp15->protectBaseSize6 = 0x0;
armcp15->protectBaseSize7 = 0x0;
armcp15->cacheOp = 0x0;
armcp15->DcacheLock = 0x0;
armcp15->IcacheLock = 0x0;
armcp15->ITCMRegion = 0x0C;
armcp15->DTCMRegion = 0x0080000A;
armcp15->processID = 0;
MMU.ARM9_RW_MODE = BIT7(armcp15->ctrl);
armcp15->cpu->intVector = 0xFFFF0000 * (BIT13(armcp15->ctrl));
armcp15->cpu->LDTBit = !BIT15(armcp15->ctrl); //TBit
MMU.ARM9_RW_MODE = BIT7(ctrl);
cpu->intVector = 0xFFFF0000 * (BIT13(ctrl));
cpu->LDTBit = !BIT15(ctrl); //TBit
/* preset calculated regionmasks */
for (i=0;i<8;i++) {
armcp15->regionWriteMask_USR[i] = 0 ;
armcp15->regionWriteMask_SYS[i] = 0 ;
armcp15->regionReadMask_USR[i] = 0 ;
armcp15->regionReadMask_SYS[i] = 0 ;
armcp15->regionExecuteMask_USR[i] = 0 ;
armcp15->regionExecuteMask_SYS[i] = 0 ;
armcp15->regionWriteSet_USR[i] = 0 ;
armcp15->regionWriteSet_SYS[i] = 0 ;
armcp15->regionReadSet_USR[i] = 0 ;
armcp15->regionReadSet_SYS[i] = 0 ;
armcp15->regionExecuteSet_USR[i] = 0 ;
armcp15->regionExecuteSet_SYS[i] = 0 ;
for (u8 i=0;i<8;i++) {
regionWriteMask_USR[i] = 0 ;
regionWriteMask_SYS[i] = 0 ;
regionReadMask_USR[i] = 0 ;
regionReadMask_SYS[i] = 0 ;
regionExecuteMask_USR[i] = 0 ;
regionExecuteMask_SYS[i] = 0 ;
regionWriteSet_USR[i] = 0 ;
regionWriteSet_SYS[i] = 0 ;
regionReadSet_USR[i] = 0 ;
regionReadSet_SYS[i] = 0 ;
regionExecuteSet_USR[i] = 0 ;
regionExecuteSet_SYS[i] = 0 ;
} ;
return armcp15;
return true;
}
#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F)
@ -84,7 +82,7 @@ armcp15_t *armcp15_new(armcpu_t * c)
#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F))
#define SETFROMREG(val) ((val) & MASKFROMREG(val))
/* sets the precalculated regions to mask,set for the affected accesstypes */
static void armcp15_setSingleRegionAccess(armcp15_t *armcp15,u32 dAccess,u32 iAccess,unsigned char num, u32 mask,u32 set) {
void armcp15_t::setSingleRegionAccess(u32 dAccess,u32 iAccess,unsigned char num, u32 mask,u32 set) {
switch (ACCESSTYPE(dAccess,num)) {
case 4: /* UNP */
@ -98,64 +96,64 @@ static void armcp15_setSingleRegionAccess(armcp15_t *armcp15,u32 dAccess,u32 iAc
case 14: /* UNP */
case 15: /* UNP */
case 0: /* no access at all */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = 0 ;
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionWriteMask_SYS[num] = 0 ;
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_SYS[num] = 0 ;
armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ;
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = 0 ;
regionReadSet_USR[num] = 0xFFFFFFFF ;
regionWriteMask_SYS[num] = 0 ;
regionWriteSet_SYS[num] = 0xFFFFFFFF ;
regionReadMask_SYS[num] = 0 ;
regionReadSet_SYS[num] = 0xFFFFFFFF ;
break ;
case 1: /* no access at USR, all to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = 0 ;
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionWriteMask_SYS[num] = mask ;
armcp15->regionWriteSet_SYS[num] = set ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = 0 ;
regionReadSet_USR[num] = 0xFFFFFFFF ;
regionWriteMask_SYS[num] = mask ;
regionWriteSet_SYS[num] = set ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 2: /* read at USR, all to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = mask ;
armcp15->regionReadSet_USR[num] = set ;
armcp15->regionWriteMask_SYS[num] = mask ;
armcp15->regionWriteSet_SYS[num] = set ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = mask ;
regionReadSet_USR[num] = set ;
regionWriteMask_SYS[num] = mask ;
regionWriteSet_SYS[num] = set ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 3: /* all to USR, all to sys */
armcp15->regionWriteMask_USR[num] = mask ;
armcp15->regionWriteSet_USR[num] = set ;
armcp15->regionReadMask_USR[num] = mask ;
armcp15->regionReadSet_USR[num] = set ;
armcp15->regionWriteMask_SYS[num] = mask ;
armcp15->regionWriteSet_SYS[num] = set ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
regionWriteMask_USR[num] = mask ;
regionWriteSet_USR[num] = set ;
regionReadMask_USR[num] = mask ;
regionReadSet_USR[num] = set ;
regionWriteMask_SYS[num] = mask ;
regionWriteSet_SYS[num] = set ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 5: /* no access at USR, read to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = 0 ;
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionWriteMask_SYS[num] = 0 ;
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = 0 ;
regionReadSet_USR[num] = 0xFFFFFFFF ;
regionWriteMask_SYS[num] = 0 ;
regionWriteSet_SYS[num] = 0xFFFFFFFF ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
case 6: /* read at USR, read to sys */
armcp15->regionWriteMask_USR[num] = 0 ;
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_USR[num] = mask ;
armcp15->regionReadSet_USR[num] = set ;
armcp15->regionWriteMask_SYS[num] = 0 ;
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
armcp15->regionReadMask_SYS[num] = mask ;
armcp15->regionReadSet_SYS[num] = set ;
regionWriteMask_USR[num] = 0 ;
regionWriteSet_USR[num] = 0xFFFFFFFF ;
regionReadMask_USR[num] = mask ;
regionReadSet_USR[num] = set ;
regionWriteMask_SYS[num] = 0 ;
regionWriteSet_SYS[num] = 0xFFFFFFFF ;
regionReadMask_SYS[num] = mask ;
regionReadSet_SYS[num] = set ;
break ;
}
switch (ACCESSTYPE(iAccess,num)) {
@ -170,43 +168,43 @@ static void armcp15_setSingleRegionAccess(armcp15_t *armcp15,u32 dAccess,u32 iAc
case 14: /* UNP */
case 15: /* UNP */
case 0: /* no access at all */
armcp15->regionExecuteMask_USR[num] = 0 ;
armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionExecuteMask_SYS[num] = 0 ;
armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
regionExecuteMask_USR[num] = 0 ;
regionExecuteSet_USR[num] = 0xFFFFFFFF ;
regionExecuteMask_SYS[num] = 0 ;
regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
break ;
case 1:
armcp15->regionExecuteMask_USR[num] = 0 ;
armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
armcp15->regionExecuteMask_SYS[num] = mask ;
armcp15->regionExecuteSet_SYS[num] = set ;
regionExecuteMask_USR[num] = 0 ;
regionExecuteSet_USR[num] = 0xFFFFFFFF ;
regionExecuteMask_SYS[num] = mask ;
regionExecuteSet_SYS[num] = set ;
break ;
case 2:
case 3:
case 6:
armcp15->regionExecuteMask_USR[num] = mask ;
armcp15->regionExecuteSet_USR[num] = set ;
armcp15->regionExecuteMask_SYS[num] = mask ;
armcp15->regionExecuteSet_SYS[num] = set ;
regionExecuteMask_USR[num] = mask ;
regionExecuteSet_USR[num] = set ;
regionExecuteMask_SYS[num] = mask ;
regionExecuteSet_SYS[num] = set ;
break ;
}
} ;
/* precalculate region masks/sets from cp15 register */
static void armcp15_maskPrecalc(armcp15_t *armcp15)
void armcp15_t::maskPrecalc()
{
#define precalc(num) { \
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \
if (BIT_N(protectBaseSize##num,0)) /* if region is enabled */ \
{ /* reason for this define: naming includes var */ \
mask = MASKFROMREG(armcp15->protectBaseSize##num) ; \
set = SETFROMREG(armcp15->protectBaseSize##num) ; \
if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F) \
mask = MASKFROMREG(protectBaseSize##num) ; \
set = SETFROMREG(protectBaseSize##num) ; \
if (SIZEIDENTIFIER(protectBaseSize##num)==0x1F) \
{ /* for the 4GB region, u32 suffers wraparound */ \
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
} \
} \
armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ; \
setSingleRegionAccess(DaccessPerm,IaccessPerm,num,mask,set) ; \
}
precalc(0) ;
precalc(1) ;
@ -216,31 +214,32 @@ static void armcp15_maskPrecalc(armcp15_t *armcp15)
precalc(5) ;
precalc(6) ;
precalc(7) ;
#undef precalc
}
BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access)
BOOL armcp15_t::isAccessAllowed(u32 address,u32 access)
{
int i ;
if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */
if (!(ctrl & 1)) return TRUE ; /* protection checking is not enabled */
for (i=0;i<8;i++) {
switch (access) {
case CP15_ACCESS_WRITEUSR:
if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ;
if ((address & regionWriteMask_USR[i]) == regionWriteSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_WRITESYS:
if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ;
if ((address & regionWriteMask_SYS[i]) == regionWriteSet_SYS[i]) return TRUE ;
break ;
case CP15_ACCESS_READUSR:
if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ;
if ((address & regionReadMask_USR[i]) == regionReadSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_READSYS:
if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ;
if ((address & regionReadMask_SYS[i]) == regionReadSet_SYS[i]) return TRUE ;
break ;
case CP15_ACCESS_EXECUSR:
if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ;
if ((address & regionExecuteMask_USR[i]) == regionExecuteSet_USR[i]) return TRUE ;
break ;
case CP15_ACCESS_EXECSYS:
if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ;
if ((address & regionExecuteMask_SYS[i]) == regionExecuteSet_SYS[i]) return TRUE ;
break ;
}
}
@ -248,27 +247,32 @@ BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access)
return FALSE ;
}
BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
BOOL armcp15_t::dataProcess(u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
LOG("Unsupported CP15 operation : DataProcess\n");
return FALSE;
}
BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr)
BOOL armcp15_t::load(u8 CRd, u8 adr)
{
LOG("Unsupported CP15 operation : Load\n");
return FALSE;
}
BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr)
BOOL armcp15_t::store(u8 CRd, u8 adr)
{
LOG("Unsupported CP15 operation : Store\n");
return FALSE;
}
BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
BOOL armcp15_t::moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
if (!cpu)
{
printf("ERROR: cp15 don\'t allocated\n");
return FALSE;
}
if(cpu->CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
@ -278,13 +282,13 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 1:
*R = armcp15->cacheType;
*R = cacheType;
return TRUE;
case 2:
*R = armcp15->TCMSize;
*R = TCMSize;
return TRUE;
default:
*R = armcp15->IDCode;
*R = IDCode;
return TRUE;
}
}
@ -292,8 +296,8 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
case 1:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
*R = armcp15->ctrl;
//LOG("CP15: CPtoARM ctrl %08X\n", armcp15->ctrl);
*R = ctrl;
//LOG("CP15: CPtoARM ctrl %08X\n", ctrl);
return TRUE;
}
return FALSE;
@ -304,10 +308,10 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 0:
*R = armcp15->DCConfig;
*R = DCConfig;
return TRUE;
case 1:
*R = armcp15->ICConfig;
*R = ICConfig;
return TRUE;
default:
return FALSE;
@ -317,8 +321,8 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
case 3:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
*R = armcp15->writeBuffCtrl;
//LOG("CP15: CPtoARM writeBuffer ctrl %08X\n", armcp15->writeBuffCtrl);
*R = writeBuffCtrl;
//LOG("CP15: CPtoARM writeBuffer ctrl %08X\n", writeBuffCtrl);
return TRUE;
}
return FALSE;
@ -328,10 +332,10 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 2:
*R = armcp15->DaccessPerm;
*R = DaccessPerm;
return TRUE;
case 3:
*R = armcp15->IaccessPerm;
*R = IaccessPerm;
return TRUE;
default:
return FALSE;
@ -344,28 +348,28 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
switch(CRm)
{
case 0:
*R = armcp15->protectBaseSize0;
*R = protectBaseSize0;
return TRUE;
case 1:
*R = armcp15->protectBaseSize1;
*R = protectBaseSize1;
return TRUE;
case 2:
*R = armcp15->protectBaseSize2;
*R = protectBaseSize2;
return TRUE;
case 3:
*R = armcp15->protectBaseSize3;
*R = protectBaseSize3;
return TRUE;
case 4:
*R = armcp15->protectBaseSize4;
*R = protectBaseSize4;
return TRUE;
case 5:
*R = armcp15->protectBaseSize5;
*R = protectBaseSize5;
return TRUE;
case 6:
*R = armcp15->protectBaseSize6;
*R = protectBaseSize6;
return TRUE;
case 7:
*R = armcp15->protectBaseSize7;
*R = protectBaseSize7;
return TRUE;
default:
return FALSE;
@ -381,10 +385,10 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 0:
*R = armcp15->DcacheLock;
*R = DcacheLock;
return TRUE;
case 1:
*R = armcp15->IcacheLock;
*R = IcacheLock;
return TRUE;
default:
return FALSE;
@ -393,10 +397,10 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 0:
*R = armcp15->DTCMRegion;
*R = DTCMRegion;
return TRUE;
case 1:
*R = armcp15->ITCMRegion;
*R = ITCMRegion;
return TRUE;
default:
return FALSE;
@ -410,17 +414,14 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
}
}
static u32 CP15wait4IRQ(armcpu_t *cpu)
BOOL armcp15_t::moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
cpu->waitIRQ = TRUE;
cpu->halt_IE_and_IF = TRUE;
//IME set deliberately omitted: only SWI sets IME to 1
return 1;
}
BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
{
if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
if (!cpu)
{
printf("ERROR: cp15 don\'t allocated\n");
return FALSE;
}
if(cpu->CPSR.bits.mode == USR) return FALSE;
switch(CRn)
{
@ -429,12 +430,12 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
{
//On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero.
armcp15->ctrl = (val & 0x000FF085) | 0x00000078;
ctrl = (val & 0x000FF085) | 0x00000078;
MMU.ARM9_RW_MODE = BIT7(val);
//zero 31-jan-2010: change from 0x0FFF0000 to 0xFFFF0000 per gbatek
armcp15->cpu->intVector = 0xFFFF0000 * (BIT13(val));
armcp15->cpu->LDTBit = !BIT15(val); //TBit
//LOG("CP15: ARMtoCP ctrl %08X (val %08X)\n", armcp15->ctrl, val);
cpu->intVector = 0xFFFF0000 * (BIT13(val));
cpu->LDTBit = !BIT15(val); //TBit
//LOG("CP15: ARMtoCP ctrl %08X (val %08X)\n", ctrl, val);
return TRUE;
}
return FALSE;
@ -444,10 +445,10 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 0:
armcp15->DCConfig = val;
DCConfig = val;
return TRUE;
case 1:
armcp15->ICConfig = val;
ICConfig = val;
return TRUE;
default:
return FALSE;
@ -457,8 +458,8 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
case 3:
if((opcode1==0) && (opcode2==0) && (CRm==0))
{
armcp15->writeBuffCtrl = val;
//LOG("CP15: ARMtoCP writeBuffer ctrl %08X\n", armcp15->writeBuffCtrl);
writeBuffCtrl = val;
//LOG("CP15: ARMtoCP writeBuffer ctrl %08X\n", writeBuffCtrl);
return TRUE;
}
return FALSE;
@ -468,12 +469,12 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 2:
armcp15->DaccessPerm = val;
armcp15_maskPrecalc(armcp15);
DaccessPerm = val;
maskPrecalc();
return TRUE;
case 3:
armcp15->IaccessPerm = val;
armcp15_maskPrecalc(armcp15);
IaccessPerm = val;
maskPrecalc();
return TRUE;
default:
return FALSE;
@ -486,36 +487,36 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
switch(CRm)
{
case 0:
armcp15->protectBaseSize0 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize0 = val;
maskPrecalc();
return TRUE;
case 1:
armcp15->protectBaseSize1 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize1 = val;
maskPrecalc();
return TRUE;
case 2:
armcp15->protectBaseSize2 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize2 = val;
maskPrecalc();
return TRUE;
case 3:
armcp15->protectBaseSize3 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize3 = val;
maskPrecalc();
return TRUE;
case 4:
armcp15->protectBaseSize4 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize4 = val;
maskPrecalc();
return TRUE;
case 5:
armcp15->protectBaseSize5 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize5 = val;
maskPrecalc();
return TRUE;
case 6:
armcp15->protectBaseSize6 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize6 = val;
maskPrecalc();
return TRUE;
case 7:
armcp15->protectBaseSize7 = val;
armcp15_maskPrecalc(armcp15) ;
protectBaseSize7 = val;
maskPrecalc();
return TRUE;
default:
return FALSE;
@ -525,7 +526,10 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
case 7:
if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
{
CP15wait4IRQ(armcp15->cpu);
//CP15wait4IRQ;
cpu->waitIRQ = TRUE;
cpu->halt_IE_and_IF = TRUE;
//IME set deliberately omitted: only SWI sets IME to 1
return TRUE;
}
return FALSE;
@ -538,10 +542,10 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 0:
armcp15->DcacheLock = val;
DcacheLock = val;
return TRUE;
case 1:
armcp15->IcacheLock = val;
IcacheLock = val;
return TRUE;
default:
return FALSE;
@ -550,10 +554,10 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
switch(opcode2)
{
case 0:
MMU.DTCMRegion = armcp15->DTCMRegion = val & 0x0FFFF000;
MMU.DTCMRegion = DTCMRegion = val & 0x0FFFF000;
return TRUE;
case 1:
armcp15->ITCMRegion = val;
ITCMRegion = val;
//ITCM base is not writeable!
MMU.ITCMRegion = 0;
return TRUE;
@ -568,5 +572,119 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
}
}
// Save state
void armcp15_t::saveone(EMUFILE* os)
{
write32le(IDCode,os);
write32le(cacheType,os);
write32le(TCMSize,os);
write32le(ctrl,os);
write32le(DCConfig,os);
write32le(ICConfig,os);
write32le(writeBuffCtrl,os);
write32le(und,os);
write32le(DaccessPerm,os);
write32le(IaccessPerm,os);
write32le(protectBaseSize0,os);
write32le(protectBaseSize1,os);
write32le(protectBaseSize2,os);
write32le(protectBaseSize3,os);
write32le(protectBaseSize4,os);
write32le(protectBaseSize5,os);
write32le(protectBaseSize6,os);
write32le(protectBaseSize7,os);
write32le(cacheOp,os);
write32le(DcacheLock,os);
write32le(IcacheLock,os);
write32le(ITCMRegion,os);
write32le(DTCMRegion,os);
write32le(processID,os);
write32le(RAM_TAG,os);
write32le(testState,os);
write32le(cacheDbg,os);
for(int i=0;i<8;i++) write32le(regionWriteMask_USR[i],os);
for(int i=0;i<8;i++) write32le(regionWriteMask_SYS[i],os);
for(int i=0;i<8;i++) write32le(regionReadMask_USR[i],os);
for(int i=0;i<8;i++) write32le(regionReadMask_SYS[i],os);
for(int i=0;i<8;i++) write32le(regionExecuteMask_USR[i],os);
for(int i=0;i<8;i++) write32le(regionExecuteMask_SYS[i],os);
for(int i=0;i<8;i++) write32le(regionWriteSet_USR[i],os);
for(int i=0;i<8;i++) write32le(regionWriteSet_SYS[i],os);
for(int i=0;i<8;i++) write32le(regionReadSet_USR[i],os);
for(int i=0;i<8;i++) write32le(regionReadSet_SYS[i],os);
for(int i=0;i<8;i++) write32le(regionExecuteSet_USR[i],os);
for(int i=0;i<8;i++) write32le(regionExecuteSet_SYS[i],os);
}
bool armcp15_t::loadone(EMUFILE* is)
{
if(!read32le(&IDCode,is)) return false;
if(!read32le(&cacheType,is)) return false;
if(!read32le(&TCMSize,is)) return false;
if(!read32le(&ctrl,is)) return false;
if(!read32le(&DCConfig,is)) return false;
if(!read32le(&ICConfig,is)) return false;
if(!read32le(&writeBuffCtrl,is)) return false;
if(!read32le(&und,is)) return false;
if(!read32le(&DaccessPerm,is)) return false;
if(!read32le(&IaccessPerm,is)) return false;
if(!read32le(&protectBaseSize0,is)) return false;
if(!read32le(&protectBaseSize1,is)) return false;
if(!read32le(&protectBaseSize2,is)) return false;
if(!read32le(&protectBaseSize3,is)) return false;
if(!read32le(&protectBaseSize4,is)) return false;
if(!read32le(&protectBaseSize5,is)) return false;
if(!read32le(&protectBaseSize6,is)) return false;
if(!read32le(&protectBaseSize7,is)) return false;
if(!read32le(&cacheOp,is)) return false;
if(!read32le(&DcacheLock,is)) return false;
if(!read32le(&IcacheLock,is)) return false;
if(!read32le(&ITCMRegion,is)) return false;
if(!read32le(&DTCMRegion,is)) return false;
if(!read32le(&processID,is)) return false;
if(!read32le(&RAM_TAG,is)) return false;
if(!read32le(&testState,is)) return false;
if(!read32le(&cacheDbg,is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionWriteMask_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionWriteMask_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionReadMask_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionReadMask_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionExecuteMask_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionExecuteMask_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionWriteSet_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionWriteSet_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionReadSet_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionReadSet_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionExecuteSet_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&regionExecuteSet_SYS[i],is)) return false;
return true;
}
/* precalculate region masks/sets from cp15 register ----- JIT */
void maskPrecalc()
{
#define precalc(num) { \
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
if (BIT_N(cp15.protectBaseSize##num,0)) /* if region is enabled */ \
{ /* reason for this define: naming includes var */ \
mask = MASKFROMREG(cp15.protectBaseSize##num) ; \
set = SETFROMREG(cp15.protectBaseSize##num) ; \
if (SIZEIDENTIFIER(cp15.protectBaseSize##num)==0x1F) \
{ /* for the 4GB region, u32 suffers wraparound */ \
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
} \
} \
cp15.setSingleRegionAccess(cp15.DaccessPerm,cp15.IaccessPerm,num,mask,set) ; \
}
precalc(0) ;
precalc(1) ;
precalc(2) ;
precalc(3) ;
precalc(4) ;
precalc(5) ;
precalc(6) ;
precalc(7) ;
#undef precalc
}

View File

@ -20,9 +20,21 @@
#define __CP15_H__
#include "armcpu.h"
#include "emufile.h"
#define CP15_ACCESS_WRITE 0
#define CP15_ACCESS_READ 2
#define CP15_ACCESS_EXECUTE 4
#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE
#define CP15_ACCESS_WRITESYS 1
#define CP15_ACCESS_READUSR CP15_ACCESS_READ
#define CP15_ACCESS_READSYS 3
#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE
#define CP15_ACCESS_EXECSYS 5
struct armcp15_t
{
public:
u32 IDCode;
u32 cacheType;
u32 TCMSize;
@ -65,27 +77,66 @@ struct armcp15_t
u32 regionExecuteSet_USR[8] ;
u32 regionExecuteSet_SYS[8] ;
armcpu_t * cpu;
armcpu_t *cpu;
void setSingleRegionAccess(u32 dAccess,u32 iAccess,unsigned char num, u32 mask,u32 set);
void maskPrecalc();
public:
armcp15_t() : IDCode(0),
cacheType(0),
TCMSize(0),
ctrl(0),
DCConfig(0),
ICConfig(0),
writeBuffCtrl(0),
und(0),
DaccessPerm(0),
IaccessPerm(0),
protectBaseSize0(0),
protectBaseSize1(0),
protectBaseSize2(0),
protectBaseSize3(0),
protectBaseSize4(0),
protectBaseSize5(0),
protectBaseSize6(0),
protectBaseSize7(0),
cacheOp(0),
DcacheLock(0),
IcacheLock(0),
ITCMRegion(0),
DTCMRegion(0),
processID(0),
RAM_TAG(0),
testState(0),
cacheDbg(0),
cpu(NULL)
{
memset(&regionWriteMask_USR[0], 0, sizeof(regionWriteMask_USR));
memset(&regionWriteMask_SYS[0], 0, sizeof(regionWriteMask_SYS));
memset(&regionReadMask_USR[0], 0, sizeof(regionReadMask_USR));
memset(&regionReadMask_SYS[0], 0, sizeof(regionReadMask_SYS));
memset(&regionExecuteMask_USR[0], 0, sizeof(regionExecuteMask_USR));
memset(&regionExecuteMask_SYS[0], 0, sizeof(regionExecuteMask_SYS));
memset(&regionWriteSet_USR[0], 0, sizeof(regionWriteSet_USR));
memset(&regionWriteSet_SYS[0], 0, sizeof(regionWriteSet_SYS));
memset(&regionReadSet_USR[0], 0, sizeof(regionReadSet_USR));
memset(&regionReadSet_SYS[0], 0, sizeof(regionReadSet_SYS));
memset(&regionExecuteSet_USR[0], 0, sizeof(regionExecuteSet_USR));
memset(&regionExecuteSet_SYS[0], 0, sizeof(regionExecuteSet_SYS));
}
bool reset(armcpu_t * c);
BOOL dataProcess(u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL load(u8 CRd, u8 adr);
BOOL store(u8 CRd, u8 adr);
BOOL moveCP2ARM(u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL moveARM2CP(u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL isAccessAllowed(u32 address,u32 access);
// savestate
void saveone(EMUFILE* os);
bool loadone(EMUFILE* is);
};
armcp15_t *armcp15_new(armcpu_t *c);
BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr);
BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr);
BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access);
#define CP15_ACCESS_WRITE 0
#define CP15_ACCESS_READ 2
#define CP15_ACCESS_EXECUTE 4
#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE
#define CP15_ACCESS_WRITESYS 1
#define CP15_ACCESS_READUSR CP15_ACCESS_READ
#define CP15_ACCESS_READSYS 3
#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE
#define CP15_ACCESS_EXECSYS 5
extern armcp15_t cp15;
void maskPrecalc();
#endif /* __CP15_H__*/

View File

@ -23,8 +23,7 @@
#include <stdio.h>
#include "MMU.h"
#include "armcpu.h"
#include "arm_instructions.h"
#include "thumb_instructions.h"
#include "instructions.h"
#include "cp15.h"
#include "NDSSystem.h"
#include "utils/xstring.h"
@ -49,7 +48,7 @@ static bool acl_check_access(u32 adr, u32 access) {
if(NDS_ARM9.CPSR.bits.mode != USR)
access |= 1;
if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) {
if (cp15.isAccessAllowed(adr,access)==FALSE) {
HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION);
}
return true;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,27 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2009 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef THUMB_INSTRUCTIONS_H
#define THUMB_INSTRUCTIONS_H
#include "armcpu.h"
typedef u32 (FASTCALL* ThumbOpFunc)(const u32 i);
extern const ThumbOpFunc thumb_instructions_set_0[1024];
extern const ThumbOpFunc thumb_instructions_set_1[1024];
extern const char* thumb_instruction_names[1024];
#endif
/* Copyright (C) 2006 yopyop
Copyright (C) 2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INSTRUCIONS_H_
#define _INSTRUCIONS_H_
typedef u32 (FASTCALL* OpFunc)(const u32 i);
extern const OpFunc arm_instructions_set[2][4096];
extern const char* arm_instruction_names[4096];
extern const OpFunc thumb_instructions_set[2][1024];
extern const char* thumb_instruction_names[1024];
#endif

View File

@ -1054,8 +1054,9 @@ public:
static SoftRasterizerEngine mainSoftRasterizer;
static Task rasterizerUnitTask[4];
static RasterizerUnit<true> rasterizerUnit[4];
#define _MAX_CORES 16
static Task rasterizerUnitTask[_MAX_CORES];
static RasterizerUnit<true> rasterizerUnit[_MAX_CORES];
static RasterizerUnit<false> _HACK_viewer_rasterizerUnit;
static int rasterizerCores;
static bool rasterizerUnitTasksInited = false;
@ -1076,35 +1077,25 @@ static char SoftRastInit(void)
_HACK_viewer_rasterizerUnit.SLI_MASK = 1;
_HACK_viewer_rasterizerUnit.SLI_VALUE = 0;
if(CommonSettings.num_cores>=4)
rasterizerCores = CommonSettings.num_cores;
if (rasterizerCores > _MAX_CORES)
rasterizerCores = _MAX_CORES;
if(CommonSettings.num_cores == 1)
{
rasterizerCores = 4;
rasterizerUnit[0].SLI_MASK = 3;
rasterizerUnit[1].SLI_MASK = 3;
rasterizerUnit[2].SLI_MASK = 3;
rasterizerUnit[3].SLI_MASK = 3;
rasterizerUnit[0].SLI_VALUE = 0;
rasterizerUnit[1].SLI_VALUE = 1;
rasterizerUnit[2].SLI_VALUE = 2;
rasterizerUnit[3].SLI_VALUE = 3;
rasterizerUnitTask[0].start(false);
rasterizerUnitTask[1].start(false);
rasterizerUnitTask[2].start(false);
rasterizerUnitTask[3].start(false);
} else if(CommonSettings.num_cores>1)
{
rasterizerCores = 2;
rasterizerUnit[0].SLI_MASK = 1;
rasterizerUnit[1].SLI_MASK = 1;
rasterizerUnit[0].SLI_VALUE = 0;
rasterizerUnit[1].SLI_VALUE = 1;
rasterizerUnitTask[0].start(false);
rasterizerUnitTask[1].start(false);
} else {
rasterizerCores = 1;
rasterizerUnit[0].SLI_MASK = 0;
rasterizerUnit[0].SLI_VALUE = 0;
}
else
{
for (u8 i = 0; i < rasterizerCores; i++)
{
rasterizerUnit[i].SLI_MASK = (rasterizerCores - 1);
rasterizerUnit[i].SLI_VALUE = i;
rasterizerUnitTask[i].start(false);
}
}
}
static bool tables_generated = false;
@ -1149,7 +1140,7 @@ static void SoftRastReset() {
static void SoftRastClose()
{
for(int i=0;i<4;i++)
for(int i=0; i<_MAX_CORES; i++)
rasterizerUnitTask[i].shutdown();
rasterizerUnitTasksInited = false;
}

View File

@ -456,104 +456,16 @@ static bool mmu_loadstate(EMUFILE* is, int size)
return ok;
}
static void cp15_saveone(armcp15_t *cp15, EMUFILE* os)
{
write32le(cp15->IDCode,os);
write32le(cp15->cacheType,os);
write32le(cp15->TCMSize,os);
write32le(cp15->ctrl,os);
write32le(cp15->DCConfig,os);
write32le(cp15->ICConfig,os);
write32le(cp15->writeBuffCtrl,os);
write32le(cp15->und,os);
write32le(cp15->DaccessPerm,os);
write32le(cp15->IaccessPerm,os);
write32le(cp15->protectBaseSize0,os);
write32le(cp15->protectBaseSize1,os);
write32le(cp15->protectBaseSize2,os);
write32le(cp15->protectBaseSize3,os);
write32le(cp15->protectBaseSize4,os);
write32le(cp15->protectBaseSize5,os);
write32le(cp15->protectBaseSize6,os);
write32le(cp15->protectBaseSize7,os);
write32le(cp15->cacheOp,os);
write32le(cp15->DcacheLock,os);
write32le(cp15->IcacheLock,os);
write32le(cp15->ITCMRegion,os);
write32le(cp15->DTCMRegion,os);
write32le(cp15->processID,os);
write32le(cp15->RAM_TAG,os);
write32le(cp15->testState,os);
write32le(cp15->cacheDbg,os);
for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_USR[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_SYS[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionReadMask_USR[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionReadMask_SYS[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_USR[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_SYS[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_USR[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_SYS[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionReadSet_USR[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionReadSet_SYS[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_USR[i],os);
for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_SYS[i],os);
}
static void cp15_savestate(EMUFILE* os)
{
//version
write32le(1,os);
cp15_saveone((armcp15_t *)NDS_ARM9.coproc[15],os);
cp15.saveone(os);
//ARM7 not have coprocessor
//cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os);
}
static bool cp15_loadone(armcp15_t *cp15, EMUFILE* is)
{
if(!read32le(&cp15->IDCode,is)) return false;
if(!read32le(&cp15->cacheType,is)) return false;
if(!read32le(&cp15->TCMSize,is)) return false;
if(!read32le(&cp15->ctrl,is)) return false;
if(!read32le(&cp15->DCConfig,is)) return false;
if(!read32le(&cp15->ICConfig,is)) return false;
if(!read32le(&cp15->writeBuffCtrl,is)) return false;
if(!read32le(&cp15->und,is)) return false;
if(!read32le(&cp15->DaccessPerm,is)) return false;
if(!read32le(&cp15->IaccessPerm,is)) return false;
if(!read32le(&cp15->protectBaseSize0,is)) return false;
if(!read32le(&cp15->protectBaseSize1,is)) return false;
if(!read32le(&cp15->protectBaseSize2,is)) return false;
if(!read32le(&cp15->protectBaseSize3,is)) return false;
if(!read32le(&cp15->protectBaseSize4,is)) return false;
if(!read32le(&cp15->protectBaseSize5,is)) return false;
if(!read32le(&cp15->protectBaseSize6,is)) return false;
if(!read32le(&cp15->protectBaseSize7,is)) return false;
if(!read32le(&cp15->cacheOp,is)) return false;
if(!read32le(&cp15->DcacheLock,is)) return false;
if(!read32le(&cp15->IcacheLock,is)) return false;
if(!read32le(&cp15->ITCMRegion,is)) return false;
if(!read32le(&cp15->DTCMRegion,is)) return false;
if(!read32le(&cp15->processID,is)) return false;
if(!read32le(&cp15->RAM_TAG,is)) return false;
if(!read32le(&cp15->testState,is)) return false;
if(!read32le(&cp15->cacheDbg,is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_SYS[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_USR[i],is)) return false;
for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_SYS[i],is)) return false;
return true;
}
static bool cp15_loadstate(EMUFILE* is, int size)
{
//read version
@ -561,14 +473,14 @@ static bool cp15_loadstate(EMUFILE* is, int size)
if(read32le(&version,is) != 1) return false;
if(version > 1) return false;
if(!cp15_loadone((armcp15_t *)NDS_ARM9.coproc[15],is)) return false;
if(!cp15.loadone(is)) return false;
if(version == 0)
{
//ARM7 not have coprocessor
u8 *tmp_buf = new u8 [sizeof(armcp15_t)];
if (!tmp_buf) return false;
if(!cp15_loadone((armcp15_t *)tmp_buf,is)) return false;
if(!cp15.loadone(is)) return false;
delete [] tmp_buf;
tmp_buf = NULL;
}
@ -902,6 +814,9 @@ static void writechunks(EMUFILE* os);
bool savestate_save(EMUFILE* outstream, int compressionLevel)
{
#ifdef HAVE_JIT
arm_jit_sync();
#endif
#ifndef HAVE_LIBZ
compressionLevel = Z_NO_COMPRESSION;
#endif

View File

@ -21,7 +21,6 @@
#include "debug.h"
#include "MMU.h"
#include "NDSSystem.h"
#include "thumb_instructions.h"
#include "MMU_timing.h"
#include <assert.h>
@ -634,7 +633,7 @@ TEMPLATE static u32 FASTCALL OP_MUL_REG(const u32 i)
//In earlier versions of the architecture, the value of the C flag was UNPREDICTABLE
//after a MUL instruction.
if (!cpu->LDTBit) // ARM4T 1S + mI, m = 3
if (PROCNUM == 1) // ARM4T 1S + mI, m = 3
return 4;
MUL_Mxx_END_THUMB(1);
@ -786,7 +785,7 @@ TEMPLATE static u32 FASTCALL OP_STR_SPREL(const u32 i)
u32 adr = cpu->R[13] + ((i&0xFF)<<2);
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]);
return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2, adr);
return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2, adr);
}
TEMPLATE static u32 FASTCALL OP_LDR_SPREL(const u32 i)
@ -906,7 +905,7 @@ TEMPLATE static u32 FASTCALL OP_POP_PC(const u32 i)
v = READ32(cpu->mem_if->data, adr);
c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(adr);
if(cpu->LDTBit)
if(PROCNUM==0)
cpu->CPSR.bits.T = BIT0(v);
cpu->R[15] = v & 0xFFFFFFFE;
@ -1044,8 +1043,8 @@ TEMPLATE static u32 FASTCALL OP_SWI_THUMB(const u32 i)
//-----------------------------------------------------------------------------
// Branch
//-----------------------------------------------------------------------------
#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800))
#define SIGNEXTEND_11(i) (((s32)i<<21)>>21)
TEMPLATE static u32 FASTCALL OP_B_COND(const u32 i)
{
@ -1084,7 +1083,7 @@ TEMPLATE static u32 FASTCALL OP_BLX(const u32 i)
TEMPLATE static u32 FASTCALL OP_BL_10(const u32 i)
{
cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12);
cpu->R[14] = cpu->R[15] + (SIGNEXTEND_11(i)<<12);
return 1;
}
@ -1139,9 +1138,7 @@ TEMPLATE static u32 FASTCALL OP_BX_THUMB(const u32 i)
TEMPLATE static u32 FASTCALL OP_BLX_THUMB(const u32 i)
{
u32 Rm = cpu->R[REG_POS(i, 3)];
cpu->CPSR.bits.T = BIT0(Rm);
//cpu->R[15] = (Rm & (0xFFFFFFFC|(1<<cpu->CPSR.bits.T)));
cpu->R[15] = Rm & 0xFFFFFFFE;
cpu->R[14] = cpu->next_instruction | 1;
cpu->next_instruction = cpu->R[15];
@ -1153,17 +1150,15 @@ TEMPLATE static u32 FASTCALL OP_BLX_THUMB(const u32 i)
// The End
//-----------------------------------------------------------------------------
const OpFunc thumb_instructions_set[2][1024] = {{
#define TABDECL(x) x<0>
const ThumbOpFunc thumb_instructions_set_0[1024] = {
#include "thumb_tabdef.inc"
};
#undef TABDECL
},{
#define TABDECL(x) x<1>
const ThumbOpFunc thumb_instructions_set_1[1024] = {
#include "thumb_tabdef.inc"
};
#undef TABDECL
}};
#define TABDECL(x) #x
const char* thumb_instruction_names[1024] = {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2005 Guillaume Duhamel
Copyright (C) 2008-2011 DeSmuME team
Copyright (C) 2008-2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -45,6 +45,7 @@
#ifdef DEVELOPER
#define HAVE_LUA
#endif
#define HAVE_JIT
#endif
#ifdef __GNUC__
@ -95,16 +96,18 @@
//use this for example when you want a byte value to be better-aligned
#define FAST_ALIGN DS_ALIGN(4)
#ifndef FASTCALL
#ifdef __MINGW32__
#define FASTCALL __attribute__((fastcall))
#define ASMJIT_CALL_CONV CALL_CONV_GCCFASTCALL
#elif defined (__i386__) && !defined(__clang__)
#define FASTCALL __attribute__((regparm(3)))
#define ASMJIT_CALL_CONV CALL_CONV_GCCREGPARM_3
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define FASTCALL
#define ASMJIT_CALL_CONV CALL_CONV_DEFAULT
#else
#define FASTCALL
#endif
#define ASMJIT_CALL_CONV CALL_CONV_DEFAULT
#endif
#ifdef _MSC_VER
@ -131,6 +134,14 @@
#endif
#endif
#ifndef NOINLINE
#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE
#endif
#endif
#if defined(__LP64__)
typedef unsigned char u8;
typedef unsigned short u16;

View File

@ -0,0 +1,24 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// MSVC
#if defined(_MSC_VER)
// Disable some warnings we know about
#pragma warning(push)
#pragma warning(disable: 4127) // conditional expression is constant
#pragma warning(disable: 4251) // struct needs to have dll-interface to be used
// by clients of struct ...
#pragma warning(disable: 4275) // non dll-interface struct ... used as base for
// dll-interface struct
#pragma warning(disable: 4355) // this used in base member initializer list
#pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
// Rename symbols.
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#endif // _MSC_VER

View File

@ -0,0 +1,16 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
#if defined(_MSC_VER)
// Pop disabled warnings by ApiBegin.h
#pragma warning(pop)
// Rename symbols back.
#undef vsnprintf
#undef snprintf
#endif // _MSC_VER

View File

@ -0,0 +1,352 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_H
#define _ASMJIT_H
//! @mainpage
//!
//! @brief AsmJit is complete x86/x64 JIT Assembler for C++ language
//!
//! It supports FPU, MMX, 3dNow, SSE, SSE2, SSE3 and SSE4 intrinsics, powerful
//! compiler that helps to write portable functions for 32-bit (x86) and 64-bit
//! (x64) architectures. AsmJit can be used to create functions at runtime that
//! can be called from existing (but also generated) C/C++ code.
//!
//! AsmJit is crossplatform library that supports various compilers and
//! operating systems. Currently only limitation is x86 (32-bit) or x64 (64-bit)
//! processor. Currently tested operating systems are Windows (32-bit and 64-bit),
//! Linux (32-bit and 64-bit) and MacOSX (32-bit).
//!
//! @section AsmJit_Main_Introduction Introduction
//!
//! AsmJit library contains two main classes for code generation with different
//! goals. First main code generation class is called @c AsmJit::Assembler and
//! contains low level API that can be used to generate JIT binary code. It
//! directly emits binary stream that represents encoded x86/x64 assembler
//! opcodes. Together with operands and labels it can be used to generate
//! complete code. For details look to @ref AsmJit_Core and @ref AsmJit_Compiler
//! sections.
//!
//! There is also class named @c AsmJit::Compiler that allows to develop
//! cross-platform assembler code without worring about function calling
//! conventions and registers allocation. It can be also used to write 32-bit
//! and 64-bit portable code. Compiler is recommended class to use for code
//! generation.
//!
//! Everything in AsmJit library is in @c AsmJit namespace.
//!
//! @section AsmJit_Main_CodeGeneration Code Generation
//!
//! - @ref AsmJit_Core "Assembler core" - Operands, intrinsics and low-level assembler.
//! - @ref AsmJit_Compiler "Compiler" - High level code generation.
//! - @ref AsmJit_CpuInfo "Cpu Information" - Get information about host processor.
//! - @ref AsmJit_Logging "Logging" - Logging and error handling.
//! - @ref AsmJit_MemoryManagement "Memory Management" - Virtual memory management.
//!
//! @section AsmJit_Main_Configuration Configuration, Definitions and Utilities
//!
//! - @ref AsmJit_Config "Configuration" - Macros used to configure AsmJit.
//! - @ref AsmJit_Util "Utilities" - Utilities and helper classes.
//!
//! @section AsmJit_Main_HomePage AsmJit Homepage
//!
//! - http://code.google.com/p/asmjit/
//!
//! @section AsmJit_Main_X86X64Resources External X86/X64 Assembler Resources
//! - http://www.agner.org/optimize/
//! - http://www.mark.masmcode.com/ (Assembler Tips)
//! - http://avisynth.org/mediawiki/Filter_SDK/Assembler_optimizing (Optimizing)
//! - http://www.ragestorm.net/distorm/ (Disassembling)
//!
//! @section AsmJit_Main_Terminology Terminology
//!
//! - <b>Non-volatile (preserved) register</b> - Register that can't be changed
//! by callee (callee must save and restore it if it want to use it inside).
//!
//! - <b>Volatile (non-preserved) register</b> - The opossite. Register that can
//! be freely used by callee. The caller must free all registers before calling
//! other function.
//! @defgroup AsmJit_Core Assembler core (operands, intrinsics and low-level assembler).
//!
//! Contains classes related to @c AsmJit::Assembler that're directly used
//! to generate machine code stream. It's one of oldest and fastest method
//! to generate machine code using AsmJit library.
//!
//! - See @c AsmJit::Assembler class for low level code generation
//! documentation.
//! - See @c AsmJit::Operand for AsmJit operand's overview.
//!
//! @section AsmJit_Core_Registers Registers
//!
//! There are static objects that represents X86 and X64 registers. They can
//! be used directly (like @c eax, @c mm, @c xmm, ...) or created through
//! these functions:
//!
//! - @c AsmJit::mk_gpb() - make general purpose byte register
//! - @c AsmJit::mk_gpw() - make general purpose word register
//! - @c AsmJit::mk_gpd() - make general purpose dword register
//! - @c AsmJit::mk_gpq() - make general purpose qword register
//! - @c AsmJit::mk_mm() - make mmx register
//! - @c AsmJit::mk_xmm() - make sse register
//! - @c AsmJit::st() - make x87 register
//!
//! @section AsmJit_Core_Addressing Addressing
//!
//! X86 and x64 architectures contains several addressing modes and most ones
//! are possible with AsmJit library. Memory represents are represented by
//! @c AsmJit::Mem class. These functions are used to make operands that
//! represents memory addresses:
//!
//! - @c AsmJit::ptr()
//! - @c AsmJit::byte_ptr()
//! - @c AsmJit::word_ptr()
//! - @c AsmJit::dword_ptr()
//! - @c AsmJit::qword_ptr()
//! - @c AsmJit::tword_ptr()
//! - @c AsmJit::dqword_ptr()
//! - @c AsmJit::mmword_ptr()
//! - @c AsmJit::xmmword_ptr()
//! - @c AsmJit::sysint_ptr()
//!
//! Most useful function to make pointer should be @c AsmJit::ptr(). It creates
//! pointer to the target with unspecified size. Unspecified size works in all
//! intrinsics where are used registers (this means that size is specified by
//! register operand or by instruction itself). For example @c AsmJit::ptr()
//! can't be used with @c AsmJit::Assembler::inc() instruction. In this case
//! size must be specified and it's also reason to make difference between
//! pointer sizes.
//!
//! Supported are simple address forms (register + displacement) and complex
//! address forms (register + (register << shift) + displacement).
//!
//! @section AsmJit_Core_Immediates Immediates
//!
//! Immediate values are constants thats passed directly after instruction
//! opcode. To create such value use @c AsmJit::imm() or @c AsmJit::uimm()
//! methods to create signed or unsigned immediate value.
//!
//! @sa @c AsmJit::Compiler.
//! @defgroup AsmJit_Compiler Compiler (high-level code generation).
//!
//! Contains classes related to @c AsmJit::Compiler that can be used
//! to generate code using high-level constructs.
//!
//! - See @c AsmJit::Compiler class for high level code generation
//! documentation - calling conventions, function declaration
//! and variables management.
//! @defgroup AsmJit_Config Configuration.
//!
//! Contains macros that can be redefined to fit into any project.
//! @defgroup AsmJit_CpuInfo CPU information.
//!
//! X86 or x64 cpuid instruction allows to get information about processor
//! vendor and it's features. It's always used to detect features like MMX,
//! SSE and other newer ones.
//!
//! AsmJit library supports low level cpuid call implemented internally as
//! C++ function using inline assembler or intrinsics and also higher level
//! CPU features detection. The low level function (also used by higher level
//! one) is @c AsmJit::cpuid().
//!
//! AsmJit library also contains higher level function @c AsmJit::getCpuInfo()
//! that returns features detected by the library. The detection process is
//! done only once and it's cached for all next calls. @c AsmJit::CpuInfo
//! structure not contains only information through @c AsmJit::cpuid(), but
//! there is also small multiplatform code to detect number of processors
//! (or cores) through operating system API.
//!
//! It's recommended to use @c AsmJit::cpuInfo to detect and check for
//! host processor features.
//!
//! Example how to use AsmJit::cpuid():
//!
//! @code
//! // All functions and structures are in AsmJit namesapce.
//! using namespace AsmJit;
//!
//! // Here will be retrieved result of cpuid call.
//! CpuId out;
//!
//! // Use cpuid function to do the job.
//! cpuid(0 /* eax */, &out /* eax, ebx, ecx, edx */);
//!
//! // Id eax argument to cpuid is 0, ebx, ecx and edx registers
//! // are filled with cpu vendor.
//! char vendor[13];
//! memcpy(i->vendor, &out.ebx, 4);
//! memcpy(i->vendor + 4, &out.edx, 4);
//! memcpy(i->vendor + 8, &out.ecx, 4);
//! vendor[12] = '\0';
//!
//! // Print vendor
//! puts(vendor);
//! @endcode
//!
//! If you want to use AsmJit::cpuid() function instead of higher level
//! @c AsmJit::getCpuInfo(), please read processor manuals provided by Intel,
//! AMD or other manufacturers for cpuid instruction details.
//!
//! Example of using @c AsmJit::getCpuInfo():
//!
//! @code
//! // All functions and structures are in AsmJit namesapce.
//! using namespace AsmJit;
//!
//! // Call to cpuInfo return CpuInfo structure that shouldn't be modified.
//! // Make it const by default.
//! const CpuInfo *i = getCpuInfo();
//!
//! // Now you are able to get specific features.
//!
//! // Processor has SSE2
//! if (i->features & CPU_FEATURE_SSE2)
//! {
//! // your code...
//! }
//! // Processor has MMX
//! else if (i->features & CPU_FEATURE__MMX)
//! {
//! // your code...
//! }
//! // Processor is old, no SSE2 or MMX support.
//! else
//! {
//! // your code...
//! }
//! @endcode
//!
//! Better example is in AsmJit/Test/testcpu.cpp file.
//!
//! @sa AsmJit::cpuid, @c AsmJit::cpuInfo.
//! @defgroup AsmJit_Logging Logging and error handling.
//!
//! Contains classes related to loging assembler output. Currently logging
//! is implemented in @c AsmJit::Logger class.You can override
//! @c AsmJit::Logger::log() to log messages into your stream. There is also
//! @c FILE based logger implemented in @c AsmJit::FileLogger class.
//!
//! To log your assembler output to FILE stream use this code:
//!
//! @code
//! // Create assembler
//! Assembler a;
//!
//! // Create and set file based logger
//! FileLogger logger(stderr);
//! a.setLogger(&logger);
//! @endcode
//!
//! You can see that logging goes through @c AsmJit::Assembler. If you are
//! using @c AsmJit::Compiler and you want to log messages in correct assembler
//! order, you should look at @c AsmJit::Compiler::comment() method. It allows
//! you to insert text message into @c AsmJit::Emittable list and
//! @c AsmJit::Compiler will send your message to @c AsmJit::Assembler in
//! correct order.
//!
//! @sa @c AsmJit::Logger, @c AsmJit::FileLogger.
//! @defgroup AsmJit_MemoryManagement Virtual memory management.
//!
//! Using @c AsmJit::Assembler or @c AsmJit::Compiler to generate machine
//! code is not final step. Each generated code needs to run in memory
//! that is not protected against code execution. To alloc this code it's
//! needed to use operating system functions provided to enable execution
//! code in specified memory block or to allocate memory that is not
//! protected. The solution is always to use @c See AsmJit::Assembler::make()
//! and @c AsmJit::Compiler::make() functions that can allocate memory and
//! relocate code for you. But AsmJit also contains classes for manual memory
//! management thats internally used by AsmJit but can be used by programmers
//! too.
//!
//! Memory management contains low level and high level classes related to
//! allocating and freeing virtual memory. Low level class is
//! @c AsmJit::VirtualMemory that can allocate and free full pages of
//! virtual memory provided by operating system. Higher level class is
//! @c AsmJit::MemoryManager that is able to manage complete allocation and
//! free mechanism. It internally uses larger chunks of memory to make
//! allocation fast and effective.
//!
//! Using @c AsmJit::VirtualMemory::alloc() is crossplatform way how to
//! allocate this kind of memory without worrying about operating system
//! and it's API. Each memory block that is no longer needed should be
//! freed by @c AsmJit::VirtualMemory::free() method. If you want better
//! comfort and malloc()/free() interface, look at the
//! @c AsmJit::MemoryManager class.
//!
//! @sa @c AsmJit::VirtualMemory, @ AsmJit::MemoryManager.
//! @defgroup AsmJit_Util Utilities and helper classes.
//!
//! Contains some helper classes that's used by AsmJit library.
//! @addtogroup AsmJit_Config
//! @{
//! @def ASMJIT_WINDOWS
//! @brief Macro that is declared if AsmJit is compiled for Windows.
//! @def ASMJIT_POSIX
//! @brief Macro that is declared if AsmJit is compiled for unix like
//! operating system.
//! @def ASMJIT_API
//! @brief Attribute that's added to classes that can be exported if AsmJit
//! is compiled as a dll library.
//! @def ASMJIT_MALLOC
//! @brief Function to call to allocate dynamic memory.
//! @def ASMJIT_REALLOC
//! @brief Function to call to reallocate dynamic memory.
//! @def ASMJIT_FREE
//! @brief Function to call to free dynamic memory.
//! @def ASMJIT_ASSERT
//! @brief Assertion macro. Default implementation calls
//! @c AsmJit::assertionFailure() function.
//! @}
//! @namespace AsmJit
//! @brief Main AsmJit library namespace.
//!
//! There are not other namespaces used in AsmJit library.
// [Includes]
#include "Build.h"
#include "Assembler.h"
#include "CodeGenerator.h"
#include "Compiler.h"
#include "CpuInfo.h"
#include "Defs.h"
#include "Logger.h"
#include "MemoryManager.h"
#include "MemoryMarker.h"
#include "Operand.h"
#include "Platform.h"
#include "Util.h"
// [Guard]
#endif // _ASMJIT_H

View File

@ -0,0 +1,36 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_ASSEMBLER_H
#define _ASMJIT_ASSEMBLER_H
// [Dependencies]
#include "Build.h"
namespace AsmJit {
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct Logger;
struct MemoryManager;
struct EInstruction;
} // AsmJit namespace
// ============================================================================
// [Platform Specific]
// ============================================================================
// [X86 / X64]
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
#include "AssemblerX86X64.h"
#endif // ASMJIT_X86 || ASMJIT_X64
// [Guard]
#endif // _ASMJIT_ASSEMBLER_H

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,285 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_BUILD_H
#define _ASMJIT_BUILD_H
// [Include]
#include "Config.h"
// Here should be optional include files that's needed fo successfuly
// use macros defined here. Remember, AsmJit uses only AsmJit namespace
// and all macros are used within it.
#include <stdio.h>
#include <stdlib.h>
// ----------------------------------------------------------------------------
// [AsmJit - OS]
// ----------------------------------------------------------------------------
#if defined(WINDOWS) || defined(__WINDOWS__) || defined(_WIN32) || defined(_WIN64)
# define ASMJIT_WINDOWS
#elif defined(__linux__) || defined(__unix__) || \
defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__) || defined(__BSD__) || defined(__FREEBSD__) || \
defined(__APPLE__)
# define ASMJIT_POSIX
#else
# warning "AsmJit - Can't match operating system, using ASMJIT_POSIX"
# define ASMJIT_POSIX
#endif
// ----------------------------------------------------------------------------
// [AsmJit - Architecture]
// ----------------------------------------------------------------------------
// define it only if it's not defined. In some systems we can
// use -D command in compiler to bypass this autodetection.
#if !defined(ASMJIT_X86) && !defined(ASMJIT_X64)
# if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || \
defined(_M_X64) || defined(_WIN64)
# define ASMJIT_X64 // x86-64
# else
// _M_IX86, __INTEL__, __i386__
# define ASMJIT_X86
# endif
#endif
// ----------------------------------------------------------------------------
// [AsmJit - API]
// ----------------------------------------------------------------------------
// Hide AsmJit symbols that we don't want to export (AssemblerIntrinsics class for example).
#if !defined(ASMJIT_HIDDEN)
# if defined(__GNUC__) && __GNUC__ >= 4
# define ASMJIT_HIDDEN __attribute__((visibility("hidden")))
# endif // __GNUC__ && __GNUC__ >= 4
#endif // ASMJIT_HIDDEN
// Make AsmJit as shared library by default.
#if !defined(ASMJIT_API)
# if defined(ASMJIT_WINDOWS)
# if defined(__GNUC__)
# if defined(AsmJit_EXPORTS)
# define ASMJIT_API __attribute__((dllexport))
# else
# define ASMJIT_API __attribute__((dllimport))
# endif // AsmJit_EXPORTS
# else
# if defined(AsmJit_EXPORTS)
# define ASMJIT_API __declspec(dllexport)
# else
# define ASMJIT_API __declspec(dllimport)
# endif // AsmJit_EXPORTS
# endif // __GNUC__
# else
# if defined(__GNUC__)
# if __GNUC__ >= 4
# define ASMJIT_API __attribute__((visibility("default")))
# define ASMJIT_VAR extern ASMJIT_API
# endif // __GNUC__ >= 4
# endif // __GNUC__
# endif
#endif // ASMJIT_API
#if defined(ASMJIT_API)
# define ASMJIT_VAR extern ASMJIT_API
#else
# define ASMJIT_API
# define ASMJIT_VAR
#endif // ASMJIT_API
// If not detected, fallback to nothing.
#if !defined(ASMJIT_HIDDEN)
# define ASMJIT_HIDDEN
#endif // ASMJIT_HIDDEN
#if !defined(ASMJIT_NOTHROW)
#define ASMJIT_NOTHROW throw()
#endif // ASMJIT_NOTHROW
// [AsmJit - Memory Management]
#if !defined(ASMJIT_MALLOC)
# define ASMJIT_MALLOC ::malloc
#endif // ASMJIT_MALLOC
#if !defined(ASMJIT_REALLOC)
# define ASMJIT_REALLOC ::realloc
#endif // ASMJIT_REALLOC
#if !defined(ASMJIT_FREE)
# define ASMJIT_FREE ::free
#endif // ASMJIT_FREE
// ----------------------------------------------------------------------------
// [AsmJit - Calling Conventions]
// ----------------------------------------------------------------------------
#if defined(ASMJIT_X86)
# if defined(__GNUC__)
# define ASMJIT_REGPARM_1 __attribute__((regparm(1)))
# define ASMJIT_REGPARM_2 __attribute__((regparm(2)))
# define ASMJIT_REGPARM_3 __attribute__((regparm(3)))
# define ASMJIT_FASTCALL __attribute__((fastcall))
# define ASMJIT_STDCALL __attribute__((stdcall))
# define ASMJIT_CDECL __attribute__((cdecl))
# else
# define ASMJIT_FASTCALL __fastcall
# define ASMJIT_STDCALL __stdcall
# define ASMJIT_CDECL __cdecl
# endif
#else
# define ASMJIT_FASTCALL
# define ASMJIT_STDCALL
# define ASMJIT_CDECL
#endif // ASMJIT_X86
#if !defined(ASMJIT_UNUSED)
# define ASMJIT_UNUSED(var) ((void)var)
#endif // ASMJIT_UNUSED
#if !defined(ASMJIT_NOP)
# define ASMJIT_NOP() ((void)0)
#endif // ASMJIT_NOP
// [AsmJit - C++ Compiler Support]
#define ASMJIT_TYPE_TO_TYPE(type) type
#define ASMJIT_HAS_STANDARD_DEFINE_OPTIONS
#define ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION
// Support for VC6
#if defined(_MSC_VER) && (_MSC_VER < 1400)
#undef ASMJIT_TYPE_TO_TYPE
namespace AsmJit {
template<typename T>
struct _Type2Type { typedef T Type; };
}
#define ASMJIT_TYPE_TO_TYPE(T) _Type2Type<T>::Type
#undef ASMJIT_HAS_STANDARD_DEFINE_OPTIONS
#undef ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION
#endif
// ----------------------------------------------------------------------------
// [AsmJit - Types]
// ----------------------------------------------------------------------------
#if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1600)
// Use <stdint.h>
#include <stdint.h>
#else
// Use typedefs.
#if defined(_MSC_VER)
#if (_MSC_VER < 1300)
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#endif
#endif // _MSC_VER
#endif // STDINT.H
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#if defined(ASMJIT_X86)
typedef int32_t sysint_t;
typedef uint32_t sysuint_t;
#else
typedef int64_t sysint_t;
typedef uint64_t sysuint_t;
#endif
#if defined(_MSC_VER)
# define ASMJIT_INT64_C(num) num##i64
# define ASMJIT_UINT64_C(num) num##ui64
#else
# define ASMJIT_INT64_C(num) num##LL
# define ASMJIT_UINT64_C(num) num##ULL
#endif
// ----------------------------------------------------------------------------
// [AsmJit - C++ Macros]
// ----------------------------------------------------------------------------
#define ASMJIT_ARRAY_SIZE(A) (sizeof(A) / sizeof(*A))
#define ASMJIT_DISABLE_COPY(__type__) \
private: \
inline __type__(const __type__& other); \
inline __type__& operator=(const __type__& other);
// ----------------------------------------------------------------------------
// [AsmJit - Debug]
// ----------------------------------------------------------------------------
// If ASMJIT_DEBUG and ASMJIT_NO_DEBUG is not defined then ASMJIT_DEBUG will be
// detected using the compiler specific macros. This enables to set the build
// type using IDE.
#if !defined(ASMJIT_DEBUG) && !defined(ASMJIT_NO_DEBUG)
#if defined(_DEBUG)
#define ASMJIT_DEBUG
#endif // _DEBUG
#endif // !ASMJIT_DEBUG && !ASMJIT_NO_DEBUG
// ----------------------------------------------------------------------------
// [AsmJit - Assert]
// ----------------------------------------------------------------------------
namespace AsmJit {
ASMJIT_API void assertionFailure(const char* file, int line, const char* exp);
} // AsmJit namespace
#if defined(ASMJIT_DEBUG)
# if !defined(ASMJIT_ASSERT)
# define ASMJIT_ASSERT(exp) do { if (!(exp)) ::AsmJit::assertionFailure(__FILE__, __LINE__, #exp); } while(0)
# endif
#else
# if !defined(ASMJIT_ASSERT)
# define ASMJIT_ASSERT(exp) ASMJIT_NOP()
# endif
#endif // DEBUG
// GCC warnings fix: I can't understand why GCC has no interface to push/pop
// specific warnings.
// #if defined(__GNUC__)
// # if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 402001
// # pragma GCC diagnostic ignored "-w"
// # endif
// #endif // __GNUC__
// ----------------------------------------------------------------------------
// [AsmJit - OS Support]
// ----------------------------------------------------------------------------
#if defined(ASMJIT_WINDOWS)
#include <Windows.h>
#endif // ASMJIT_WINDOWS
// [Guard]
#endif // _ASMJIT_BUILD_H

View File

@ -0,0 +1,17 @@
Copyright (c) 2008-2012, Petr Kobalicek <kobalicek.petr@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -0,0 +1,102 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include "Assembler.h"
#include "CodeGenerator.h"
#include "Defs.h"
#include "MemoryManager.h"
#include "MemoryMarker.h"
namespace AsmJit {
// ============================================================================
// [AsmJit::CodeGenerator - Construction / Destruction]
// ============================================================================
CodeGenerator::CodeGenerator()
{
}
CodeGenerator::~CodeGenerator()
{
}
// ============================================================================
// [AsmJit::CodeGenerator - GetGlobal]
// ============================================================================
JitCodeGenerator* CodeGenerator::getGlobal()
{
static JitCodeGenerator global;
return &global;
}
// ============================================================================
// [AsmJit::JitCodeGenerator - Construction / Destruction]
// ============================================================================
JitCodeGenerator::JitCodeGenerator() :
_memoryManager(NULL),
_memoryMarker(NULL),
_allocType(MEMORY_ALLOC_FREEABLE)
{
}
JitCodeGenerator::~JitCodeGenerator()
{
}
// ============================================================================
// [AsmJit::JitCodeGenerator - Generate]
// ============================================================================
uint32_t JitCodeGenerator::generate(void** dest, Assembler* assembler)
{
// Disallow empty code generation.
sysuint_t codeSize = assembler->getCodeSize();
if (codeSize == 0)
{
*dest = NULL;
return AsmJit::ERROR_NO_FUNCTION;
}
// Switch to global memory manager if not provided.
MemoryManager* memmgr = getMemoryManager();
if (memmgr == NULL)
{
memmgr = MemoryManager::getGlobal();
}
void* p = memmgr->alloc(codeSize, getAllocType());
if (p == NULL)
{
*dest = NULL;
return ERROR_NO_VIRTUAL_MEMORY;
}
// Relocate the code.
sysuint_t relocatedSize = assembler->relocCode(p);
// Return unused memory to MemoryManager.
if (relocatedSize < codeSize)
{
memmgr->shrink(p, relocatedSize);
}
// Mark memory if MemoryMarker provided.
if (_memoryMarker)
{
_memoryMarker->mark(p, relocatedSize);
}
// Return the code.
*dest = p;
return ERROR_NONE;
}
} // AsmJit namespace

View File

@ -0,0 +1,140 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_CODEGENERATOR_H
#define _ASMJIT_CODEGENERATOR_H
// [Dependencies]
#include "Build.h"
namespace AsmJit {
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct Assembler;
struct JitCodeGenerator;
struct MemoryManager;
struct MemoryMarker;
// ============================================================================
// [AsmJit::CodeGenerator]
// ============================================================================
//! @brief Code generator is core class for changing behavior of code generated
//! by @c Assembler or @c Compiler.
struct ASMJIT_API CodeGenerator
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @c CodeGenerator instance.
CodeGenerator();
//! @brief Destroy the @c CodeGenerator instance.
virtual ~CodeGenerator();
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
//! @brief Allocate memory for code generated in @a assembler and reloc it
//! to target location.
//!
//! This method is universal allowing any pre-process / post-process work
//! with code generated by @c Assembler or @c Compiler. Because @c Compiler
//! always uses @c Assembler it's allowed to access only the @c Assembler
//! instance.
//!
//! This method is always last step when using code generation. You can use
//! it to allocate memory for JIT code, saving code to remote process or a
//! shared library.
//!
//! @retrurn Error value, see @c ERROR_CODE.
virtual uint32_t generate(void** dest, Assembler* assembler) = 0;
// --------------------------------------------------------------------------
// [Statics]
// --------------------------------------------------------------------------
static JitCodeGenerator* getGlobal();
private:
ASMJIT_DISABLE_COPY(CodeGenerator)
};
// ============================================================================
// [AsmJit::JitCodeGenerator]
// ============================================================================
struct JitCodeGenerator : public CodeGenerator
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @c JitCodeGenerator instance.
JitCodeGenerator();
//! @brief Destroy the @c JitCodeGenerator instance.
virtual ~JitCodeGenerator();
// --------------------------------------------------------------------------
// [Memory Manager and Alloc Type]
// --------------------------------------------------------------------------
// Note: These members can be ignored by all derived classes. They are here
// only to privide default implementation. All other implementations (remote
// code patching or making dynamic loadable libraries/executables) ignore
// members accessed by these accessors.
//! @brief Get the @c MemoryManager instance.
inline MemoryManager* getMemoryManager() const { return _memoryManager; }
//! @brief Set the @c MemoryManager instance.
inline void setMemoryManager(MemoryManager* memoryManager) { _memoryManager = memoryManager; }
//! @brief Get the type of allocation.
inline uint32_t getAllocType() const { return _allocType; }
//! @brief Set the type of allocation.
inline void setAllocType(uint32_t allocType) { _allocType = allocType; }
// --------------------------------------------------------------------------
// [Memory Marker]
// --------------------------------------------------------------------------
//! @brief Get the @c MemoryMarker instance.
inline MemoryMarker* getMemoryMarker() const { return _memoryMarker; }
//! @brief Set the @c MemoryMarker instance.
inline void setMemoryMarker(MemoryMarker* memoryMarker) { _memoryMarker = memoryMarker; }
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
virtual uint32_t generate(void** dest, Assembler* assembler);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief Memory manager.
MemoryManager* _memoryManager;
//! @brief Memory marker.
MemoryMarker* _memoryMarker;
//! @brief Type of allocation.
uint32_t _allocType;
private:
ASMJIT_DISABLE_COPY(JitCodeGenerator)
};
} // AsmJit namespace
// [Guard]
#endif // _ASMJIT_CODEGENERATOR_H

View File

@ -0,0 +1,272 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// We are using sprintf() here.
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif // _MSC_VER
// [Dependencies]
#include "Assembler.h"
#include "Compiler.h"
#include "CpuInfo.h"
#include "Logger.h"
#include "Util.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// ============================================================================
// [AsmJit::Emittable]
// ============================================================================
Emittable::Emittable(Compiler* c, uint32_t type) ASMJIT_NOTHROW :
_compiler(c),
_next(NULL),
_prev(NULL),
_comment(NULL),
_type((uint8_t)type),
_translated(false),
_reserved0(0),
_reserved1(0),
_offset(INVALID_VALUE)
{
}
Emittable::~Emittable() ASMJIT_NOTHROW
{
}
void Emittable::prepare(CompilerContext& cc) ASMJIT_NOTHROW
{
_offset = cc._currentOffset;
}
Emittable* Emittable::translate(CompilerContext& cc) ASMJIT_NOTHROW
{
return translated();
}
void Emittable::emit(Assembler& a) ASMJIT_NOTHROW
{
}
void Emittable::post(Assembler& a) ASMJIT_NOTHROW
{
}
int Emittable::getMaxSize() const ASMJIT_NOTHROW
{
// Default maximum size is -1 which means that it's not known.
return -1;
}
bool Emittable::_tryUnuseVar(VarData* v) ASMJIT_NOTHROW
{
return false;
}
void Emittable::setComment(const char* str) ASMJIT_NOTHROW
{
_comment = _compiler->getZone().zstrdup(str);
}
void Emittable::setCommentF(const char* fmt, ...) ASMJIT_NOTHROW
{
// I'm really not expecting larger inline comments:)
char buf[256];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, 255, fmt, ap);
va_end(ap);
// I don't know if vsnprintf can produce non-null terminated string, in case
// it can, we terminate it here.
buf[255] = '\0';
setComment(buf);
}
// ============================================================================
// [AsmJit::EDummy]
// ============================================================================
EDummy::EDummy(Compiler* c) ASMJIT_NOTHROW :
Emittable(c, EMITTABLE_DUMMY)
{
}
EDummy::~EDummy() ASMJIT_NOTHROW
{
}
int EDummy::getMaxSize() const ASMJIT_NOTHROW
{
return 0;
}
// ============================================================================
// [AsmJit::EFunctionEnd]
// ============================================================================
EFunctionEnd::EFunctionEnd(Compiler* c) ASMJIT_NOTHROW :
EDummy(c)
{
_type = EMITTABLE_FUNCTION_END;
}
EFunctionEnd::~EFunctionEnd() ASMJIT_NOTHROW
{
}
Emittable* EFunctionEnd::translate(CompilerContext& cc) ASMJIT_NOTHROW
{
_translated = true;
return NULL;
}
// ============================================================================
// [AsmJit::EComment]
// ============================================================================
EComment::EComment(Compiler* c, const char* str) ASMJIT_NOTHROW :
Emittable(c, EMITTABLE_COMMENT)
{
setComment(str);
}
EComment::~EComment() ASMJIT_NOTHROW
{
}
void EComment::emit(Assembler& a) ASMJIT_NOTHROW
{
if (a.getLogger())
{
a.getLogger()->logString(getComment());
}
}
int EComment::getMaxSize() const ASMJIT_NOTHROW
{
return 0;
}
// ============================================================================
// [AsmJit::EData]
// ============================================================================
EData::EData(Compiler* c, const void* data, sysuint_t length) ASMJIT_NOTHROW :
Emittable(c, EMITTABLE_EMBEDDED_DATA)
{
_length = length;
memcpy(_data, data, length);
}
EData::~EData() ASMJIT_NOTHROW
{
}
void EData::emit(Assembler& a) ASMJIT_NOTHROW
{
a.embed(_data, _length);
}
int EData::getMaxSize() const ASMJIT_NOTHROW
{
return (int)_length;;
}
// ============================================================================
// [AsmJit::EAlign]
// ============================================================================
EAlign::EAlign(Compiler* c, uint32_t size) ASMJIT_NOTHROW :
Emittable(c, EMITTABLE_ALIGN), _size(size)
{
}
EAlign::~EAlign() ASMJIT_NOTHROW
{
}
void EAlign::emit(Assembler& a) ASMJIT_NOTHROW
{
a.align(_size);
}
int EAlign::getMaxSize() const ASMJIT_NOTHROW
{
return (_size > 0) ? (int)_size - 1 : 0;
}
// ============================================================================
// [AsmJit::ETarget]
// ============================================================================
ETarget::ETarget(Compiler* c, const Label& label) ASMJIT_NOTHROW :
Emittable(c, EMITTABLE_TARGET),
_label(label),
_from(NULL),
_state(NULL),
_jumpsCount(0)
{
}
ETarget::~ETarget() ASMJIT_NOTHROW
{
}
void ETarget::prepare(CompilerContext& cc) ASMJIT_NOTHROW
{
_offset = cc._currentOffset++;
}
Emittable* ETarget::translate(CompilerContext& cc) ASMJIT_NOTHROW
{
// If this ETarget was already translated, it's needed to change the current
// state and return NULL to tell CompilerContext to process next untranslated
// emittable.
if (_translated)
{
cc._restoreState(_state);
return NULL;
}
if (cc._unreachable)
{
cc._unreachable = 0;
// Assign state to the compiler context.
ASMJIT_ASSERT(_state != NULL);
cc._assignState(_state);
}
else
{
_state = cc._saveState();
}
return translated();
}
void ETarget::emit(Assembler& a) ASMJIT_NOTHROW
{
a.bind(_label);
}
int ETarget::getMaxSize() const ASMJIT_NOTHROW
{
return 0;
}
} // AsmJit namespace

View File

@ -0,0 +1,846 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_COMPILER_H
#define _ASMJIT_COMPILER_H
// [Dependencies]
#include "Build.h"
#include "Defs.h"
#include "Operand.h"
#include "Util.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct Assembler;
struct CodeGenerator;
struct Compiler;
struct CompilerContext;
struct CompilerCore;
struct CompilerIntrinsics;
struct MemoryManager;
struct FunctionDefinition;
struct ForwardJumpData;
struct VarData;
struct VarAllocRecord;
struct StateData;
struct Emittable;
struct EAlign;
struct ECall;
struct EComment;
struct EData;
struct EEpilog;
struct EFunction;
struct EFunctionEnd;
struct EInstruction;
struct EJmp;
struct EProlog;
struct ERet;
// ============================================================================
// [AsmJit::TypeToId]
// ============================================================================
#if !defined(ASMJIT_NODOC)
#if defined(ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION)
template<typename T>
struct TypeToId
{
#if defined(ASMJIT_NODOC)
enum { Id = INVALID_VALUE };
#endif // ASMJIT_NODOC
};
template<typename T>
struct TypeToId<T*> { enum { Id = VARIABLE_TYPE_INTPTR }; };
#else
// Same trict is used in Qt, Boost, Fog and all other libraries that need
// something similar.
//
// It's easy. It's needed to use sizeof() to determine the size
// of return value of this function. If size will be sizeof(char)
// (this is our type) then type is pointer, otherwise it's not.
template<typename T>
char TypeToId_NoPtiHelper(T*(*)());
// And specialization.
void* TypeToId_NoPtiHelper(...);
template<typename T>
struct TypeToId
{
// TypeInfo constants
enum
{
// This is the hackery result.
Id = (sizeof(char) == sizeof( TypeToId_NoPtiHelper((T(*)())0) )
? VARIABLE_TYPE_INTPTR
: INVALID_VALUE)
};
};
#endif // ASMJIT_HAS_PARTIAL_TEMPLATE_SPECIALIZATION
#define ASMJIT_DECLARE_TYPE_AS_ID(__T__, __Id__) \
template<> \
struct TypeToId<__T__> { enum { Id = __Id__ }; }
// Declare void type and alternative.
struct Void {};
ASMJIT_DECLARE_TYPE_AS_ID(void, INVALID_VALUE);
ASMJIT_DECLARE_TYPE_AS_ID(Void, INVALID_VALUE);
#endif // ASMJIT_NODOC
// ============================================================================
// [AsmJit::Function Builder]
// ============================================================================
struct FunctionDefinition
{
//! @brief Get function arguments IDs.
inline const uint32_t* getArguments() const
{
return _arguments;
}
//! @brief Get function arguments count.
inline uint32_t getArgumentsCount() const
{
return _argumentsCount;
}
inline uint32_t getArgument(uint32_t id) const
{
ASMJIT_ASSERT(id < _argumentsCount);
return _arguments[id];
}
//! @brief Get function return value.
inline uint32_t getReturnValue() const
{
return _returnValue;
}
protected:
inline void _setDefinition(const uint32_t* arguments, uint32_t argumentsCount, uint32_t returnValue)
{
_arguments = arguments;
_argumentsCount = argumentsCount;
_returnValue = returnValue;
}
const uint32_t* _arguments;
uint32_t _argumentsCount;
uint32_t _returnValue;
};
//! @brief Custom function builder for up to 32 function arguments.
struct FunctionBuilderX : public FunctionDefinition
{
inline FunctionBuilderX()
{
_setDefinition(_argumentsData, 0, INVALID_VALUE);
}
template<typename T>
inline void addArgument()
{
addArgumentRaw(TypeToId<ASMJIT_TYPE_TO_TYPE(T)>::Id);
}
template<typename T>
inline void setArgument(uint32_t id)
{
setArgumentRaw(id, TypeToId<ASMJIT_TYPE_TO_TYPE(T)>::Id);
}
template<typename T>
inline void setReturnValue()
{
setReturnValueRaw(TypeToId<ASMJIT_TYPE_TO_TYPE(T)>::Id);
}
inline void addArgumentRaw(uint32_t type)
{
ASMJIT_ASSERT(_argumentsCount < FUNC_MAX_ARGS);
_argumentsData[_argumentsCount++] = type;
}
inline void setArgumentRaw(uint32_t id, uint32_t type)
{
ASMJIT_ASSERT(id < _argumentsCount);
_argumentsData[id] = type;
}
inline void setReturnValueRaw(uint32_t returnValue)
{
_returnValue = returnValue;
}
protected:
uint32_t _argumentsData[FUNC_MAX_ARGS];
};
//! @brief Class used to build function without arguments.
template<typename RET>
struct FunctionBuilder0 : public FunctionDefinition
{
inline FunctionBuilder0()
{
_setDefinition(NULL, 0, TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 1 argument.
template<typename RET, typename P0>
struct FunctionBuilder1 : public FunctionDefinition
{
inline FunctionBuilder1()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 2 arguments.
template<typename RET, typename P0, typename P1>
struct FunctionBuilder2 : public FunctionDefinition
{
inline FunctionBuilder2()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 3 arguments.
template<typename RET, typename P0, typename P1, typename P2>
struct FunctionBuilder3 : public FunctionDefinition
{
inline FunctionBuilder3()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 4 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3>
struct FunctionBuilder4 : public FunctionDefinition
{
inline FunctionBuilder4()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 5 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4>
struct FunctionBuilder5 : public FunctionDefinition
{
inline FunctionBuilder5()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id,
TypeToId<P4>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 6 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
struct FunctionBuilder6 : public FunctionDefinition
{
inline FunctionBuilder6()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id,
TypeToId<P4>::Id,
TypeToId<P5>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 7 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
struct FunctionBuilder7 : public FunctionDefinition
{
inline FunctionBuilder7()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id,
TypeToId<P4>::Id,
TypeToId<P5>::Id,
TypeToId<P6>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 8 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
struct FunctionBuilder8 : public FunctionDefinition
{
inline FunctionBuilder8()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id,
TypeToId<P4>::Id,
TypeToId<P5>::Id,
TypeToId<P6>::Id,
TypeToId<P7>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 9 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
struct FunctionBuilder9 : public FunctionDefinition
{
inline FunctionBuilder9()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id,
TypeToId<P4>::Id,
TypeToId<P5>::Id,
TypeToId<P6>::Id,
TypeToId<P7>::Id,
TypeToId<P8>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
//! @brief Class used to build function with 10 arguments.
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
struct FunctionBuilder10 : public FunctionDefinition
{
inline FunctionBuilder10()
{
static const uint32_t args[] =
{
TypeToId<P0>::Id,
TypeToId<P1>::Id,
TypeToId<P2>::Id,
TypeToId<P3>::Id,
TypeToId<P4>::Id,
TypeToId<P5>::Id,
TypeToId<P6>::Id,
TypeToId<P7>::Id,
TypeToId<P8>::Id,
TypeToId<P9>::Id
};
_setDefinition(args, ASMJIT_ARRAY_SIZE(args), TypeToId<RET>::Id);
}
};
// ============================================================================
// [AsmJit::Emittable]
// ============================================================================
//! @brief Emmitable.
//!
//! Emittable is object that can emit single or more instructions. To
//! create your custom emittable it's needed to override the abstract virtual
//! method @c emit().
//!
//! When you are finished serializing instructions to the @c Compiler and you
//! call @c Compiler::make(), it will first call @c prepare() method for each
//! emittable in list, then @c translate(), @c emit() and @c post() is the last.
//! Prepare can be used to calculate something that can be only calculated when
//! emitting instructions is finished (for example @c Function uses @c prepare()
//! to relocate memory home for all memory/spilled variables). The @c emit() should
//! be used to emit instruction or multiple instructions into @a Assembler stream,
//! and the @c post() is here to allow emitting embedded data (after function
//! declaration), etc.
struct ASMJIT_API Emittable
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create new emittable.
//!
//! Never create @c Emittable by @c new operator or on the stack, use
//! @c Compiler::newObject template to do that.
Emittable(Compiler* c, uint32_t type) ASMJIT_NOTHROW;
//! @brief Destroy emittable.
//!
//! @note Never destroy emittable using @c delete keyword, @c Compiler
//! manages all emittables in internal memory pool and it will destroy
//! all emittables after you destroy it.
virtual ~Emittable() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit and Helpers]
// --------------------------------------------------------------------------
//! @brief Step 1. Extract emittable variables, update statistics, ...
virtual void prepare(CompilerContext& cc) ASMJIT_NOTHROW;
//! @brief Step 2. Translate instruction, alloc variables, ...
virtual Emittable* translate(CompilerContext& cc) ASMJIT_NOTHROW;
//! @brief Step 3. Emit to @c Assembler.
virtual void emit(Assembler& a) ASMJIT_NOTHROW;
//! @brief Step 4. Last post step (verify, add data, etc).
virtual void post(Assembler& a) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
//! @brief Get maximum size in bytes of this emittable (in binary).
virtual int getMaxSize() const ASMJIT_NOTHROW;
//! @brief Try to unuse the variable @a.
//!
//! Returns @c true only if the variable will be unused by the instruction,
//! otherwise @c false is returned.
virtual bool _tryUnuseVar(VarData* v) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Compiler]
// --------------------------------------------------------------------------
//! @brief Get associated compiler instance.
inline Compiler* getCompiler() const ASMJIT_NOTHROW { return _compiler; }
// --------------------------------------------------------------------------
// [Type / Offset]
// --------------------------------------------------------------------------
//! @brief Get emittable type, see @c EMITTABLE_TYPE.
inline uint32_t getType() const ASMJIT_NOTHROW { return _type; }
//! @brief Get whether the emittable was translated.
inline uint8_t isTranslated() const ASMJIT_NOTHROW { return _translated; }
//! @brief Get emittable offset in the stream
//!
//! Emittable offset is not byte offset, each emittable increments offset by 1
//! and this value is then used by register allocator. Emittable offset is
//! set by compiler by the register allocator, don't use it in your code.
inline uint32_t getOffset() const ASMJIT_NOTHROW { return _offset; }
// --------------------------------------------------------------------------
// [Emittables List]
// --------------------------------------------------------------------------
//! @brief Get previous emittable in list.
inline Emittable* getPrev() const ASMJIT_NOTHROW { return _prev; }
//! @brief Get next emittable in list.
inline Emittable* getNext() const ASMJIT_NOTHROW { return _next; }
// --------------------------------------------------------------------------
// [Comment]
// --------------------------------------------------------------------------
//! @brief Get comment string.
inline const char* getComment() const ASMJIT_NOTHROW { return _comment; }
//! @brief Set comment string to @a str.
void setComment(const char* str) ASMJIT_NOTHROW;
//! @brief Format comment string using @a fmt string and variable argument list.
void setCommentF(const char* fmt, ...) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Protected]
// --------------------------------------------------------------------------
protected:
//! @brief Mark emittable as translated and return next.
inline Emittable* translated() ASMJIT_NOTHROW
{
ASMJIT_ASSERT(_translated == false);
_translated = true;
return _next;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Compiler where this emittable is connected to.
Compiler* _compiler;
//! @brief Type of emittable, see @c EMITTABLE_TYPE.
uint8_t _type;
//! @brief Whether the emittable was translated, see @c translate().
uint8_t _translated;
//! @brief Reserved flags for future use.
uint8_t _reserved0;
//! @brief Reserved flags for future use.
uint8_t _reserved1;
//! @brief Emittable offset.
uint32_t _offset;
//! @brief Previous emittable.
Emittable* _prev;
//! @brief Next emittable.
Emittable* _next;
//! @brief Embedded comment string (also used by a @c Comment emittable).
const char* _comment;
private:
friend struct CompilerCore;
ASMJIT_DISABLE_COPY(Emittable)
};
// ============================================================================
// [AsmJit::EDummy]
// ============================================================================
//! @brief Dummy emittable, used as a mark.
//!
//! This emittable does nothing and it's only used by @ref Compiler to mark
//! specific location in the code.
struct ASMJIT_API EDummy : public Emittable
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref EDummy instance.
EDummy(Compiler* c) ASMJIT_NOTHROW;
//! @brief Destroy the @ref EDummy instance.
virtual ~EDummy() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
virtual int getMaxSize() const ASMJIT_NOTHROW;
private:
ASMJIT_DISABLE_COPY(EDummy)
};
// ============================================================================
// [AsmJit::EFunctionEnd]
// ============================================================================
//! @brief End of function.
//!
//! This emittable does nothing and it's only used by @ref Compiler to mark
//! specific location in the code. The @c EFunctionEnd is similar to @c EDummy,
//! except that it overrides @c translate() to return @c NULL.
struct ASMJIT_API EFunctionEnd : public EDummy
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref EDummy instance.
EFunctionEnd(Compiler* c) ASMJIT_NOTHROW;
//! @brief Destroy the @ref EDummy instance.
virtual ~EFunctionEnd() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit and Helpers]
// --------------------------------------------------------------------------
virtual Emittable* translate(CompilerContext& cc) ASMJIT_NOTHROW;
private:
ASMJIT_DISABLE_COPY(EFunctionEnd)
};
// ============================================================================
// [AsmJit::EComment]
// ============================================================================
//! @brief Emittable used to emit comment into @c Assembler logger.
//!
//! Comments allows to comment your assembler stream for better debugging
//! and visualization what's happening. Comments are ignored if logger is
//! not set.
//!
//! Comment string can't be modified after comment was created.
struct ASMJIT_API EComment : public Emittable
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref EComment instance.
EComment(Compiler* c, const char* comment) ASMJIT_NOTHROW;
//! @brief Destroy the @ref EComment instance.
virtual ~EComment() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit]
// --------------------------------------------------------------------------
virtual void emit(Assembler& a) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
virtual int getMaxSize() const ASMJIT_NOTHROW;
private:
friend struct CompilerCore;
ASMJIT_DISABLE_COPY(EComment)
};
// ============================================================================
// [AsmJit::EData]
// ============================================================================
//! @brief Emittable used to emit comment into @c Assembler logger.
//!
//! @note This class is always allocated by @c AsmJit::Compiler.
struct ASMJIT_API EData : public Emittable
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref EData instance.
EData(Compiler* c, const void* data, sysuint_t length) ASMJIT_NOTHROW;
//! @brief Destroy the @ref EData instance.
virtual ~EData() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit]
// --------------------------------------------------------------------------
virtual void emit(Assembler& a) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
virtual int getMaxSize() const ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Data]
// --------------------------------------------------------------------------
//! @brief Get pointer to embedded data.
uint8_t* getData() const ASMJIT_NOTHROW { return (uint8_t*)_data; }
//! @brief Get length of embedded data.
sysuint_t getLength() const ASMJIT_NOTHROW { return _length; }
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief Data length.
sysuint_t _length;
//! @brief Data buffer (that will be embedded to the assembler stream).
uint8_t _data[sizeof(void*)];
private:
friend struct CompilerCore;
ASMJIT_DISABLE_COPY(EData)
};
// ============================================================================
// [AsmJit::EAlign]
// ============================================================================
//! @brief Emittable used to align assembler code.
struct ASMJIT_API EAlign : public Emittable
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref EAlign instance.
EAlign(Compiler* c, uint32_t size = 0) ASMJIT_NOTHROW;
//! @brief Destroy the @ref EAlign instance.
virtual ~EAlign() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit]
// --------------------------------------------------------------------------
virtual void emit(Assembler& a) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
virtual int getMaxSize() const ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Align Size]
// --------------------------------------------------------------------------
//! @brief Get align size in bytes.
inline uint32_t getSize() const ASMJIT_NOTHROW { return _size; }
//! @brief Set align size in bytes to @a size.
inline void setSize(uint32_t size) ASMJIT_NOTHROW { _size = size; }
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief Align size.
uint32_t _size;
private:
friend struct CompilerCore;
ASMJIT_DISABLE_COPY(EAlign)
};
// ============================================================================
// [AsmJit::ETarget]
// ============================================================================
//! @brief Target - the bound label.
struct ASMJIT_API ETarget : public Emittable
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref ETarget instance.
ETarget(Compiler* c, const Label& target) ASMJIT_NOTHROW;
//! @brief Destroy the @ref ETarget instance.
virtual ~ETarget() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit]
// --------------------------------------------------------------------------
virtual void prepare(CompilerContext& cc) ASMJIT_NOTHROW;
virtual Emittable* translate(CompilerContext& cc) ASMJIT_NOTHROW;
virtual void emit(Assembler& a) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Utilities]
// --------------------------------------------------------------------------
virtual int getMaxSize() const ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Methods]
// --------------------------------------------------------------------------
//! @brief Return label bound to this target.
inline const Label& getLabel() const ASMJIT_NOTHROW { return _label; }
//! @brief Get first jmp instruction.
inline EJmp* getFrom() const ASMJIT_NOTHROW { return _from; }
//! @brief Get register allocator state for this target.
inline StateData* getState() const ASMJIT_NOTHROW { return _state; }
//! @brief Get number of jumps to this target.
inline uint32_t getJumpsCount() const ASMJIT_NOTHROW { return _jumpsCount; }
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief Label.
Label _label;
//! @brief First jump instruction that points to this target (label).
EJmp* _from;
//! @brief State at this location.
StateData* _state;
//! @brief Count of jumps to this target (label).
uint32_t _jumpsCount;
private:
friend struct CompilerContext;
friend struct CompilerCore;
friend struct EInstruction;
friend struct EJmp;
ASMJIT_DISABLE_COPY(ETarget)
};
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"
// ============================================================================
// [Platform Specific]
// ============================================================================
// [X86 / X64]
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
#include "CompilerX86X64.h"
#endif // ASMJIT_X86 || ASMJIT_X64
// [Guard]
#endif // _ASMJIT_COMPILER_H

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,74 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// This file is designed to be modifyable. Platform specific changes should
// be applied to this file so it's guaranteed that never versions of AsmJit
// library will never overwrite generated config files.
//
// So modify this file by your build system or by hand.
// [Guard]
#ifndef _ASMJIT_CONFIG_H
#define _ASMJIT_CONFIG_H
// ============================================================================
// [AsmJit - OS]
// ============================================================================
// Provides definitions about your operating system. It's detected by default,
// so override it if you have problems with automatic detection.
//
// #define ASMJIT_WINDOWS 1
// #define ASMJIT_POSIX 2
// ============================================================================
// [AsmJit - Architecture]
// ============================================================================
// Provides definitions about your cpu architecture. It's detected by default,
// so override it if you have problems with automatic detection.
// #define ASMJIT_X86
// #define ASMJIT_X64
// ============================================================================
// [AsmJit - API]
// ============================================================================
// If you are embedding AsmJit library into your project (statically), undef
// ASMJIT_API macro. ASMJIT_HIDDEN macro can contain visibility (used by GCC)
// to hide some AsmJit symbols that shouldn't be never exported.
//
// If you have problems with throw() in compilation time, undef ASMJIT_NOTHROW
// to disable this feature. ASMJIT_NOTHROW marks functions that never throws
// an exception.
#define ASMJIT_HIDDEN
#define ASMJIT_API
// #define ASMJIT_NOTHROW
// ============================================================================
// [AsmJit - Memory Management]
// ============================================================================
// #define ASMJIT_MALLOC ::malloc
// #define ASMJIT_REALLOC ::realloc
// #define ASMJIT_FREE ::free
// ============================================================================
// [AsmJit - Debug]
// ============================================================================
// Turn debug on/off (to bypass autodetection)
// #define ASMJIT_DEBUG
// #define ASMJIT_NO_DEBUG
// Setup custom assertion code.
// #define ASMJIT_ASSERT(exp) do { if (!(exp)) ::AsmJit::assertionFailure(__FILE__, __LINE__, #exp); } while(0)
// [Guard]
#endif // _ASMJIT_CONFIG_H

View File

@ -0,0 +1,337 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include "CpuInfo.h"
#if defined(ASMJIT_WINDOWS)
# include <windows.h>
#endif // ASMJIT_WINDOWS
// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler. This
// shouldn't affect x64 compilation, because x64 compiler starts with
// VS2005 (VC8.0).
#if defined(_MSC_VER)
# if _MSC_VER >= 1400
# include <intrin.h>
# endif // _MSC_VER >= 1400 (>= VS2005)
#endif // _MSC_VER
#if defined(ASMJIT_POSIX)
#include <errno.h>
#include <string.h>
#include <sys/statvfs.h>
#include <sys/utsname.h>
#include <unistd.h>
#endif // ASMJIT_POSIX
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// helpers
static uint32_t detectNumberOfProcessors(void)
{
#if defined(ASMJIT_WINDOWS)
SYSTEM_INFO info;
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
#elif defined(ASMJIT_POSIX) && defined(_SC_NPROCESSORS_ONLN)
// It seems that sysconf returns the number of "logical" processors on both
// mac and linux. So we get the number of "online logical" processors.
long res = sysconf(_SC_NPROCESSORS_ONLN);
if (res == -1) return 1;
return static_cast<uint32_t>(res);
#else
return 1;
#endif
}
// This is messy, I know. cpuid is implemented as intrinsic in VS2005, but
// we should support other compilers as well. Main problem is that MS compilers
// in 64-bit mode not allows to use inline assembler, so we need intrinsic and
// we need also asm version.
// cpuid() and detectCpuInfo() for x86 and x64 platforms begins here.
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
void cpuid(uint32_t in, CpuId* out) ASMJIT_NOTHROW
{
#if defined(_MSC_VER)
// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler.
// ASMJIT_X64 is here only for readibility, only VS2005 can compile 64-bit code.
# if _MSC_VER >= 1400 || defined(ASMJIT_X64)
// done by intrinsics
__cpuid(reinterpret_cast<int*>(out->i), in);
# else // _MSC_VER < 1400
uint32_t cpuid_in = in;
uint32_t* cpuid_out = out->i;
__asm
{
mov eax, cpuid_in
mov edi, cpuid_out
cpuid
mov dword ptr[edi + 0], eax
mov dword ptr[edi + 4], ebx
mov dword ptr[edi + 8], ecx
mov dword ptr[edi + 12], edx
}
# endif // _MSC_VER < 1400
#elif defined(__GNUC__)
// Note, need to preserve ebx/rbx register!
# if defined(ASMJIT_X86)
# define __mycpuid(a, b, c, d, inp) \
asm ("mov %%ebx, %%edi\n" \
"cpuid\n" \
"xchg %%edi, %%ebx\n" \
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
# else
# define __mycpuid(a, b, c, d, inp) \
asm ("mov %%rbx, %%rdi\n" \
"cpuid\n" \
"xchg %%rdi, %%rbx\n" \
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
# endif
__mycpuid(out->eax, out->ebx, out->ecx, out->edx, in);
#endif // compiler
}
struct CpuVendorInfo
{
uint32_t id;
char text[12];
};
static const CpuVendorInfo cpuVendorInfo[] =
{
{ CPU_VENDOR_INTEL , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } },
{ CPU_VENDOR_AMD , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
{ CPU_VENDOR_AMD , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
{ CPU_VENDOR_NSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } },
{ CPU_VENDOR_NSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } },
{ CPU_VENDOR_TRANSMETA, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } },
{ CPU_VENDOR_TRANSMETA, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } },
{ CPU_VENDOR_VIA , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } },
{ CPU_VENDOR_VIA , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } }
};
static inline bool cpuVencorEq(const CpuVendorInfo& info, const char* vendorString)
{
const uint32_t* a = reinterpret_cast<const uint32_t*>(info.text);
const uint32_t* b = reinterpret_cast<const uint32_t*>(vendorString);
return (a[0] == b[0]) &
(a[1] == b[1]) &
(a[2] == b[2]) ;
}
static inline void simplifyBrandString(char* s)
{
// Always clear the current character in the buffer. This ensures that there
// is no garbage after the string NULL terminator.
char* d = s;
char prev = 0;
char curr = s[0];
s[0] = '\0';
for (;;)
{
if (curr == 0) break;
if (curr == ' ')
{
if (prev == '@') goto _Skip;
if (s[1] == ' ' || s[1] == '@') goto _Skip;
}
d[0] = curr;
d++;
prev = curr;
_Skip:
curr = *++s;
s[0] = '\0';
}
d[0] = '\0';
}
void detectCpuInfo(CpuInfo* i) ASMJIT_NOTHROW
{
uint32_t a;
// First clear our struct
memset(i, 0, sizeof(CpuInfo));
memcpy(i->vendor, "Unknown", 8);
i->numberOfProcessors = detectNumberOfProcessors();
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
CpuId out;
// Get vendor string
cpuid(0, &out);
memcpy(i->vendor, &out.ebx, 4);
memcpy(i->vendor + 4, &out.edx, 4);
memcpy(i->vendor + 8, &out.ecx, 4);
for (a = 0; a < 3; a++)
{
if (cpuVencorEq(cpuVendorInfo[a], i->vendor))
{
i->vendorId = cpuVendorInfo[a].id;
break;
}
}
// get feature flags in ecx/edx, and family/model in eax
cpuid(1, &out);
// family and model fields
i->family = (out.eax >> 8) & 0x0F;
i->model = (out.eax >> 4) & 0x0F;
i->stepping = (out.eax ) & 0x0F;
// use extended family and model fields
if (i->family == 0x0F)
{
i->family += ((out.eax >> 20) & 0xFF);
i->model += ((out.eax >> 16) & 0x0F) << 4;
}
i->x86ExtendedInfo.processorType = ((out.eax >> 12) & 0x03);
i->x86ExtendedInfo.brandIndex = ((out.ebx ) & 0xFF);
i->x86ExtendedInfo.flushCacheLineSize = ((out.ebx >> 8) & 0xFF) * 8;
i->x86ExtendedInfo.maxLogicalProcessors = ((out.ebx >> 16) & 0xFF);
i->x86ExtendedInfo.apicPhysicalId = ((out.ebx >> 24) & 0xFF);
if (out.ecx & 0x00000001U) i->features |= CPU_FEATURE_SSE3;
if (out.ecx & 0x00000002U) i->features |= CPU_FEATURE_PCLMULDQ;
if (out.ecx & 0x00000008U) i->features |= CPU_FEATURE_MONITOR_MWAIT;
if (out.ecx & 0x00000200U) i->features |= CPU_FEATURE_SSSE3;
if (out.ecx & 0x00002000U) i->features |= CPU_FEATURE_CMPXCHG16B;
if (out.ecx & 0x00080000U) i->features |= CPU_FEATURE_SSE4_1;
if (out.ecx & 0x00100000U) i->features |= CPU_FEATURE_SSE4_2;
if (out.ecx & 0x00400000U) i->features |= CPU_FEATURE_MOVBE;
if (out.ecx & 0x00800000U) i->features |= CPU_FEATURE_POPCNT;
if (out.ecx & 0x10000000U) i->features |= CPU_FEATURE_AVX;
if (out.edx & 0x00000010U) i->features |= CPU_FEATURE_RDTSC;
if (out.edx & 0x00000100U) i->features |= CPU_FEATURE_CMPXCHG8B;
if (out.edx & 0x00008000U) i->features |= CPU_FEATURE_CMOV;
if (out.edx & 0x00800000U) i->features |= CPU_FEATURE_MMX;
if (out.edx & 0x01000000U) i->features |= CPU_FEATURE_FXSR;
if (out.edx & 0x02000000U) i->features |= CPU_FEATURE_SSE | CPU_FEATURE_MMX_EXT;
if (out.edx & 0x04000000U) i->features |= CPU_FEATURE_SSE | CPU_FEATURE_SSE2;
if (out.edx & 0x10000000U) i->features |= CPU_FEATURE_MULTI_THREADING;
if (i->vendorId == CPU_VENDOR_AMD && (out.edx & 0x10000000U))
{
// AMD sets Multithreading to ON if it has more cores.
if (i->numberOfProcessors == 1) i->numberOfProcessors = 2;
}
// This comment comes from V8 and I think that its important:
//
// Opteron Rev E has a bug in which on very rare occasions a locked
// instruction doesn't act as a read-acquire barrier if followed by a
// non-locked read-modify-write instruction. Rev F has this bug in
// pre-release versions, but not in versions released to customers,
// so we test only for Rev E, which is family 15, model 32..63 inclusive.
if (i->vendorId == CPU_VENDOR_AMD && i->family == 15 && i->model >= 32 && i->model <= 63)
{
i->bugs |= CPU_BUG_AMD_LOCK_MB;
}
// Calling cpuid with 0x80000000 as the in argument
// gets the number of valid extended IDs.
cpuid(0x80000000, &out);
uint32_t exIds = out.eax;
if (exIds > 0x80000004) exIds = 0x80000004;
uint32_t* brand = reinterpret_cast<uint32_t*>(i->brand);
for (a = 0x80000001; a <= exIds; a++)
{
cpuid(a, &out);
switch (a)
{
case 0x80000001:
if (out.ecx & 0x00000001U) i->features |= CPU_FEATURE_LAHF_SAHF;
if (out.ecx & 0x00000020U) i->features |= CPU_FEATURE_LZCNT;
if (out.ecx & 0x00000040U) i->features |= CPU_FEATURE_SSE4_A;
if (out.ecx & 0x00000080U) i->features |= CPU_FEATURE_MSSE;
if (out.ecx & 0x00000100U) i->features |= CPU_FEATURE_PREFETCH;
if (out.edx & 0x00100000U) i->features |= CPU_FEATURE_EXECUTE_DISABLE_BIT;
if (out.edx & 0x00200000U) i->features |= CPU_FEATURE_FFXSR;
if (out.edx & 0x00400000U) i->features |= CPU_FEATURE_MMX_EXT;
if (out.edx & 0x08000000U) i->features |= CPU_FEATURE_RDTSCP;
if (out.edx & 0x20000000U) i->features |= CPU_FEATURE_64_BIT;
if (out.edx & 0x40000000U) i->features |= CPU_FEATURE_3DNOW_EXT | CPU_FEATURE_MMX_EXT;
if (out.edx & 0x80000000U) i->features |= CPU_FEATURE_3DNOW;
break;
case 0x80000002:
case 0x80000003:
case 0x80000004:
*brand++ = out.eax;
*brand++ = out.ebx;
*brand++ = out.ecx;
*brand++ = out.edx;
break;
default:
// Additional features can be detected in the future.
break;
}
}
// Simplify the brand string (remove unnecessary spaces to make it printable).
simplifyBrandString(i->brand);
#endif // ASMJIT_X86 || ASMJIT_X64
}
#else
void detectCpuInfo(CpuInfo* i) ASMJIT_NOTHROW
{
memset(i, 0, sizeof(CpuInfo));
}
#endif
struct ASMJIT_HIDDEN CpuInfoStatic
{
CpuInfoStatic() ASMJIT_NOTHROW { detectCpuInfo(&i); }
CpuInfo i;
};
CpuInfo* getCpuInfo() ASMJIT_NOTHROW
{
static CpuInfoStatic i;
return &i.i;
}
} // AsmJit
// [Api-End]
#include "ApiEnd.h"

View File

@ -0,0 +1,226 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_CPUINFO_H
#define _ASMJIT_CPUINFO_H
// [Dependencies]
#include "Build.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
//! @addtogroup AsmJit_CpuInfo
//! @{
// ============================================================================
// [AsmJit::CpuId]
// ============================================================================
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
//! @brief Structure (union) used by cpuid() function.
union CpuId
{
//! @brief cpuid results array(eax, ebx, ecx and edx registers).
uint32_t i[4];
struct
{
//! @brief cpuid result in eax register.
uint32_t eax;
//! @brief cpuid result in ebx register.
uint32_t ebx;
//! @brief cpuid result in ecx register.
uint32_t ecx;
//! @brief cpuid result in edx register.
uint32_t edx;
};
};
//! @brief Calls CPUID instruction with eax == @a in and returns result to @a out.
//!
//! @c cpuid() function has one input parameter that is passed to cpuid through
//! eax register and results in four output values representing result of cpuid
//! instruction (eax, ebx, ecx and edx registers).
ASMJIT_API void cpuid(uint32_t in, CpuId* out) ASMJIT_NOTHROW;
#endif // ASMJIT_X86 || ASMJIT_X64
// ============================================================================
// [AsmJit::CPU_VENDOR]
// ============================================================================
//! @brief Cpu vendor IDs.
//!
//! Cpu vendor IDs are specific for AsmJit library. Vendor ID is not directly
//! read from cpuid result, instead it's based on CPU vendor string.
enum CPU_VENDOR
{
//! @brief Unknown CPU vendor.
CPU_VENDOR_UNKNOWN = 0,
//! @brief Intel CPU vendor.
CPU_VENDOR_INTEL = 1,
//! @brief AMD CPU vendor.
CPU_VENDOR_AMD = 2,
//! @brief National Semiconductor CPU vendor (applies also to Cyrix processors).
CPU_VENDOR_NSM = 3,
//! @brief Transmeta CPU vendor.
CPU_VENDOR_TRANSMETA = 4,
//! @brief VIA CPU vendor.
CPU_VENDOR_VIA = 5
};
// ============================================================================
// [AsmJit::CPU_FEATURE]
// ============================================================================
//! @brief X86/X64 CPU features.
enum CPU_FEATURE
{
//! @brief Cpu has RDTSC instruction.
CPU_FEATURE_RDTSC = 1U << 0,
//! @brief Cpu has RDTSCP instruction.
CPU_FEATURE_RDTSCP = 1U << 1,
//! @brief Cpu has CMOV instruction (conditional move)
CPU_FEATURE_CMOV = 1U << 2,
//! @brief Cpu has CMPXCHG8B instruction
CPU_FEATURE_CMPXCHG8B = 1U << 3,
//! @brief Cpu has CMPXCHG16B instruction (64-bit processors)
CPU_FEATURE_CMPXCHG16B = 1U << 4,
//! @brief Cpu has CLFUSH instruction
CPU_FEATURE_CLFLUSH = 1U << 5,
//! @brief Cpu has PREFETCH instruction
CPU_FEATURE_PREFETCH = 1U << 6,
//! @brief Cpu supports LAHF and SAHF instrictions.
CPU_FEATURE_LAHF_SAHF = 1U << 7,
//! @brief Cpu supports FXSAVE and FXRSTOR instructions.
CPU_FEATURE_FXSR = 1U << 8,
//! @brief Cpu supports FXSAVE and FXRSTOR instruction optimizations (FFXSR).
CPU_FEATURE_FFXSR = 1U << 9,
//! @brief Cpu has MMX.
CPU_FEATURE_MMX = 1U << 10,
//! @brief Cpu has extended MMX.
CPU_FEATURE_MMX_EXT = 1U << 11,
//! @brief Cpu has 3dNow!
CPU_FEATURE_3DNOW = 1U << 12,
//! @brief Cpu has enchanced 3dNow!
CPU_FEATURE_3DNOW_EXT = 1U << 13,
//! @brief Cpu has SSE.
CPU_FEATURE_SSE = 1U << 14,
//! @brief Cpu has SSE2.
CPU_FEATURE_SSE2 = 1U << 15,
//! @brief Cpu has SSE3.
CPU_FEATURE_SSE3 = 1U << 16,
//! @brief Cpu has Supplemental SSE3 (SSSE3).
CPU_FEATURE_SSSE3 = 1U << 17,
//! @brief Cpu has SSE4.A.
CPU_FEATURE_SSE4_A = 1U << 18,
//! @brief Cpu has SSE4.1.
CPU_FEATURE_SSE4_1 = 1U << 19,
//! @brief Cpu has SSE4.2.
CPU_FEATURE_SSE4_2 = 1U << 20,
//! @brief Cpu has AVX.
CPU_FEATURE_AVX = 1U << 22,
//! @brief Cpu has Misaligned SSE (MSSE).
CPU_FEATURE_MSSE = 1U << 23,
//! @brief Cpu supports MONITOR and MWAIT instructions.
CPU_FEATURE_MONITOR_MWAIT = 1U << 24,
//! @brief Cpu supports MOVBE instruction.
CPU_FEATURE_MOVBE = 1U << 25,
//! @brief Cpu supports POPCNT instruction.
CPU_FEATURE_POPCNT = 1U << 26,
//! @brief Cpu supports LZCNT instruction.
CPU_FEATURE_LZCNT = 1U << 27,
//! @brief Cpu supports PCLMULDQ set of instructions.
CPU_FEATURE_PCLMULDQ = 1U << 28,
//! @brief Cpu supports multithreading.
CPU_FEATURE_MULTI_THREADING = 1U << 29,
//! @brief Cpu supports execute disable bit (execute protection).
CPU_FEATURE_EXECUTE_DISABLE_BIT = 1U << 30,
//! @brief 64-bit CPU.
CPU_FEATURE_64_BIT = 1U << 31
};
// ============================================================================
// [AsmJit::CPU_BUG]
// ============================================================================
//! @brief X86/X64 CPU bugs.
enum CPU_BUG
{
//! @brief Whether the processor contains bug seen in some
//! AMD-Opteron processors.
CPU_BUG_AMD_LOCK_MB = 1U << 0
};
// ============================================================================
// [AsmJit::CpuInfo]
// ============================================================================
//! @brief Informations about host cpu.
struct ASMJIT_HIDDEN CpuInfo
{
//! @brief Cpu short vendor string.
char vendor[16];
//! @brief Cpu long vendor string (brand).
char brand[64];
//! @brief Cpu vendor id (see @c AsmJit::CpuInfo::VendorId enum).
uint32_t vendorId;
//! @brief Cpu family ID.
uint32_t family;
//! @brief Cpu model ID.
uint32_t model;
//! @brief Cpu stepping.
uint32_t stepping;
//! @brief Number of processors or cores.
uint32_t numberOfProcessors;
//! @brief Cpu features bitfield, see @c AsmJit::CpuInfo::Feature enum).
uint32_t features;
//! @brief Cpu bugs bitfield, see @c AsmJit::CpuInfo::Bug enum).
uint32_t bugs;
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
//! @brief Extended information for x86/x64 compatible processors.
struct X86ExtendedInfo
{
//! @brief Processor type.
uint32_t processorType;
//! @brief Brand index.
uint32_t brandIndex;
//! @brief Flush cache line size in bytes.
uint32_t flushCacheLineSize;
//! @brief Maximum number of addressable IDs for logical processors.
uint32_t maxLogicalProcessors;
//! @brief Initial APIC ID.
uint32_t apicPhysicalId;
};
//! @brief Extended information for x86/x64 compatible processors.
X86ExtendedInfo x86ExtendedInfo;
#endif // ASMJIT_X86 || ASMJIT_X64
};
//! @brief Detect CPU features to CpuInfo structure @a i.
//!
//! @sa @c CpuInfo.
ASMJIT_API void detectCpuInfo(CpuInfo* i) ASMJIT_NOTHROW;
//! @brief Return CpuInfo (detection is done only once).
//!
//! @sa @c CpuInfo.
ASMJIT_API CpuInfo* getCpuInfo() ASMJIT_NOTHROW;
//! @}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"
// [Guard]
#endif // _ASMJIT_CPUINFO_H

View File

@ -0,0 +1,49 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include "Defs.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
const char* getErrorString(uint32_t error) ASMJIT_NOTHROW
{
static const char* errorMessage[] = {
"No error",
"No heap memory",
"No virtual memory",
"Unknown instruction",
"Illegal instruction",
"Illegal addressing",
"Illegal short jump",
"No function defined",
"Incomplete function",
"Not enough registers",
"Registers overlap",
"Incompatible argument",
"Incompatible return value",
"Unknown error"
};
// Saturate error code to be able to use errorMessage[].
if (error > _ERROR_COUNT) error = _ERROR_COUNT;
return errorMessage[error];
}
} // AsmJit
// [Api-End]
#include "ApiEnd.h"

View File

@ -0,0 +1,416 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_DEFS_H
#define _ASMJIT_DEFS_H
// [Dependencies]
#include "Build.h"
namespace AsmJit {
//! @addtogroup AsmJit_Core
//! @{
// ============================================================================
// [AsmJit::ENUM]
// ============================================================================
//! @brief Uncategorized constants.
enum
{
//! @brief Invalid operand identifier.
INVALID_VALUE = 0xFFFFFFFF,
//! @brief Maximum allowed arguments per function declaration / call.
FUNC_MAX_ARGS = 32
};
// ============================================================================
// [AsmJit::MEMORY_ALLOC_TYPE]
// ============================================================================
//! @brief Types of allocation used by @c AsmJit::MemoryManager::alloc() method.
enum MEMORY_ALLOC_TYPE
{
//! @brief Allocate memory that can be freed by @c AsmJit::MemoryManager::free()
//! method.
MEMORY_ALLOC_FREEABLE = 0,
//! @brief Allocate permanent memory that will be never freed.
MEMORY_ALLOC_PERMANENT = 1
};
// ============================================================================
// [AsmJit::ERROR_CODE]
// ============================================================================
//! @brief AsmJit error codes.
enum ERROR_CODE
{
//! @brief No error (success).
//!
//! This is default state and state you want.
ERROR_NONE = 0,
//! @brief Memory allocation error (@c ASMJIT_MALLOC returned @c NULL).
ERROR_NO_HEAP_MEMORY = 1,
//! @brief Virtual memory allocation error (@c VirtualMemory returned @c NULL).
ERROR_NO_VIRTUAL_MEMORY = 2,
//! @brief Unknown instruction. This happens only if instruction code is
//! out of bounds. Shouldn't happen.
ERROR_UNKNOWN_INSTRUCTION = 3,
//! @brief Illegal instruction, usually generated by AsmJit::AssemblerCore
//! class when emitting instruction opcode. If this error is generated the
//! target buffer is not affected by this invalid instruction.
//!
//! You can also get this error code if you are under x64 (64-bit x86) and
//! you tried to decode instruction using AH, BH, CH or DH register with REX
//! prefix. These registers can't be accessed if REX prefix is used and AsmJit
//! didn't check for this situation in intrinsics (@c Compiler takes care of
//! this and rearrange registers if needed).
//!
//! Examples that will raise @c ERROR_ILLEGAL_INSTRUCTION error (a is
//! @c Assembler instance):
//!
//! @code
//! a.mov(dword_ptr(eax), al); // Invalid address size.
//! a.mov(byte_ptr(r10), ah); // Undecodable instruction (AH used with r10
//! // which can be encoded only using REX prefix)
//! @endcode
//!
//! @note In debug mode you get assertion failure instead of setting error
//! code.
ERROR_ILLEGAL_INSTRUCTION = 4,
//! @brief Illegal addressing used (unencodable).
ERROR_ILLEGAL_ADDRESING = 5,
//! @brief Short jump instruction used, but displacement is out of bounds.
ERROR_ILLEGAL_SHORT_JUMP = 6,
//! @brief No function defined.
ERROR_NO_FUNCTION = 7,
//! @brief Function generation is not finished by using @c Compiler::endFunction()
//! or something bad happened during generation related to function. This can
//! be missing emittable, etc...
ERROR_INCOMPLETE_FUNCTION = 8,
//! @brief Compiler can't allocate registers, because all of them are used.
//!
//! @note AsmJit is able to spill registers so this error really shouldn't
//! happen unless all registers have priority 0 (which means never spill).
ERROR_NOT_ENOUGH_REGISTERS = 9,
//! @brief Compiler can't allocate one register to multiple destinations.
//!
//! This error can only happen using special instructions like cmpxchg8b and
//! others where there are more destination operands (implicit).
ERROR_REGISTERS_OVERLAP = 10,
//! @brief Tried to call function using incompatible argument.
ERROR_INCOMPATIBLE_ARGUMENT = 11,
//! @brief Incompatible return value.
ERROR_INCOMPATIBLE_RETURN_VALUE = 12,
//! @brief Count of error codes by AsmJit. Can grow in future.
_ERROR_COUNT
};
// ============================================================================
// [AsmJit::OPERAND_TYPE]
// ============================================================================
//! @brief Operand types that can be encoded in @c Op operand.
enum OPERAND_TYPE
{
//! @brief Operand is none, used only internally (not initialized Operand).
//!
//! This operand is not valid.
OPERAND_NONE = 0x00,
//! @brief Operand is register.
OPERAND_REG = 0x01,
//! @brief Operand is memory.
OPERAND_MEM = 0x02,
//! @brief Operand is immediate.
OPERAND_IMM = 0x04,
//! @brief Operand is label.
OPERAND_LABEL = 0x08,
//! @brief Operand is variable.
OPERAND_VAR = 0x10
};
// ============================================================================
// [AsmJit::OPERAND_MEM_TYPE]
// ============================================================================
//! @brief Type of memory operand.
enum OPERAND_MEM_TYPE
{
//! @brief Operand is combination of register(s) and displacement (native).
OPERAND_MEM_NATIVE = 0,
//! @brief Operand is label.
OPERAND_MEM_LABEL = 1,
//! @brief Operand is absolute memory location (supported mainly in 32-bit
//! mode)
OPERAND_MEM_ABSOLUTE = 2,
};
// ============================================================================
// [AsmJit::OPERAND_ID]
// ============================================================================
//! @brief Operand ID masks used to determine the operand type.
enum OPERAND_ID
{
//! @brief Operand id value mask (part used for IDs).
OPERAND_ID_VALUE_MASK = 0x3FFFFFFF,
//! @brief Operand id type mask (part used for operand type).
OPERAND_ID_TYPE_MASK = 0xC0000000,
//! @brief Label operand mark id.
OPERAND_ID_TYPE_LABEL = 0x40000000,
//! @brief Variable operand mark id.
OPERAND_ID_TYPE_VAR = 0x80000000
};
// ============================================================================
// [AsmJit::PROPERTY]
// ============================================================================
//! @brief @c Assembler/Compiler properties.
enum PROPERTY
{
//! @brief Optimize align for current processor.
//!
//! Default: @c true.
PROPERTY_OPTIMIZE_ALIGN = 0,
//! @brief Emit hints added to jcc() instructions.
//!
//! Default: @c true.
//!
//! @note This is X86/X64 property only.
PROPERTY_JUMP_HINTS = 1
};
// ============================================================================
// [AsmJit::SIZE]
// ============================================================================
//! @brief Size of registers and pointers.
enum SIZE
{
//! @brief 1 byte size.
SIZE_BYTE = 1,
//! @brief 2 bytes size.
SIZE_WORD = 2,
//! @brief 4 bytes size.
SIZE_DWORD = 4,
//! @brief 8 bytes size.
SIZE_QWORD = 8,
//! @brief 10 bytes size.
SIZE_TWORD = 10,
//! @brief 16 bytes size.
SIZE_DQWORD = 16
};
// ============================================================================
// [EMITTABLE_TYPE]
// ============================================================================
//! @brief Emmitable type.
//!
//! For each emittable that is used by @c Compiler must be defined it's type.
//! Compiler can optimize instruction stream by analyzing emittables and each
//! type is hint for it. The most used emittables are instructions
//! (@c EMITTABLE_INSTRUCTION).
enum EMITTABLE_TYPE
{
//! @brief Emittable is invalid (can't be used).
EMITTABLE_NONE = 0,
//! @brief Emittable is dummy (used as a mark) (@ref EDummy).
EMITTABLE_DUMMY,
//! @brief Emittable is comment (no code) (@ref EComment).
EMITTABLE_COMMENT,
//! @brief Emittable is embedded data (@ref EData).
EMITTABLE_EMBEDDED_DATA,
//! @brief Emittable is .align directive (@ref EAlign).
EMITTABLE_ALIGN,
//! @brief Emittable is variable hint (alloc, spill, use, unuse, ...) (@ref EVariableHint).
EMITTABLE_VARIABLE_HINT,
//! @brief Emittable is single instruction (@ref EInstruction).
EMITTABLE_INSTRUCTION,
//! @brief Emittable is block of instructions.
EMITTABLE_BLOCK,
//! @brief Emittable is function declaration (@ref EFunction).
EMITTABLE_FUNCTION,
//! @brief Emittable is function prolog (@ref EProlog).
EMITTABLE_PROLOG,
//! @brief Emittable is function epilog (@ref EEpilog).
EMITTABLE_EPILOG,
//! @brief Emittable is end of function (@ref EFunctionEnd).
EMITTABLE_FUNCTION_END,
//! @brief Emittable is target (bound label).
EMITTABLE_TARGET,
//! @brief Emittable is jump table (@ref EJmp).
EMITTABLE_JUMP_TABLE,
//! @brief Emittable is function call (@ref ECall).
EMITTABLE_CALL,
//! @brief Emittable is return (@ref ERet).
EMITTABLE_RET
};
// ============================================================================
// [AsmJit::VARIABLE_STATE]
// ============================================================================
//! @brief State of variable.
//!
//! @note State of variable is used only during make process and it's not
//! visible to the developer.
enum VARIABLE_STATE
{
//! @brief Variable is currently not used.
VARIABLE_STATE_UNUSED = 0,
//! @brief Variable is in register.
//!
//! Variable is currently allocated in register.
VARIABLE_STATE_REGISTER = 1,
//! @brief Variable is in memory location or spilled.
//!
//! Variable was spilled from register to memory or variable is used for
//! memory only storage.
VARIABLE_STATE_MEMORY = 2
};
// ============================================================================
// [AsmJit::VARIABLE_ALLOC_FLAGS]
// ============================================================================
//! @brief Variable alloc mode.
enum VARIABLE_ALLOC
{
//! @brief Allocating variable to read only.
//!
//! Read only variables are used to optimize variable spilling. If variable
//! is some time ago deallocated and it's not marked as changed (so it was
//! all the life time read only) then spill is simply NOP (no mov instruction
//! is generated to move it to it's home memory location).
VARIABLE_ALLOC_READ = 0x01,
//! @brief Allocating variable to write only (overwrite).
//!
//! Overwriting means that if variable is in memory, there is no generated
//! instruction to move variable from memory to register, because that
//! register will be overwritten by next instruction. This is used as a
//! simple optimization to improve generated code by @c Compiler.
VARIABLE_ALLOC_WRITE = 0x02,
//! @brief Allocating variable to read / write.
//!
//! Variable allocated for read / write is marked as changed. This means that
//! if variable must be later spilled into memory, mov (or similar)
//! instruction will be generated.
VARIABLE_ALLOC_READWRITE = 0x03,
//! @brief Variable can be allocated in register.
VARIABLE_ALLOC_REGISTER = 0x04,
//! @brief Variable can be allocated in memory.
VARIABLE_ALLOC_MEMORY = 0x08,
//! @brief Unuse the variable after use.
VARIABLE_ALLOC_UNUSE_AFTER_USE = 0x10,
//! @brief Variable can be allocated only to one register (special allocation).
VARIABLE_ALLOC_SPECIAL = 0x20
};
// ============================================================================
// [AsmJit::VARIABLE_ALLOC_POLICY]
// ============================================================================
//! @brief Variable allocation method.
//!
//! Variable allocation method is used by compiler and it means if compiler
//! should first allocate preserved registers or not. Preserved registers are
//! registers that must be saved / restored by generated function.
//!
//! This option is for people who are calling C/C++ functions from JIT code so
//! Compiler can recude generating push/pop sequences before and after call,
//! respectively.
enum VARIABLE_ALLOC_POLICY
{
//! @brief Allocate preserved registers first.
VARIABLE_ALLOC_PRESERVED_FIRST = 0,
//! @brief Allocate preserved registers last (default).
VARIABLE_ALLOC_PRESERVED_LAST = 1
};
// ============================================================================
// [AsmJit::FUNCTION_HINT]
// ============================================================================
//! @brief Function hints.
enum FUNCTION_HINT
{
//! @brief Use push/pop sequences instead of mov sequences in function prolog
//! and epilog.
FUNCTION_HINT_PUSH_POP_SEQUENCE = 0,
//! @brief Make naked function (without using ebp/erp in prolog / epilog).
FUNCTION_HINT_NAKED = 1,
//! @brief Add emms instruction to the function epilog.
FUNCTION_HINT_EMMS = 2,
//! @brief Add sfence instruction to the function epilog.
FUNCTION_HINT_SFENCE = 3,
//! @brief Add lfence instruction to the function epilog.
FUNCTION_HINT_LFENCE = 4
};
// ============================================================================
// [AsmJit::ARGUMENT_DIR]
// ============================================================================
//! @brief Arguments direction used by @c Function.
enum ARGUMENT_DIR
{
//! @brief Arguments are passed left to right.
//!
//! This arguments direction is unusual to C programming, it's used by pascal
//! compilers and in some calling conventions by Borland compiler).
ARGUMENT_DIR_LEFT_TO_RIGHT = 0,
//! @brief Arguments are passer right ro left
//!
//! This is default argument direction in C programming.
ARGUMENT_DIR_RIGHT_TO_LEFT = 1
};
// ============================================================================
// [AsmJit::API]
// ============================================================================
//! @brief Translates error code (see @c ERROR_CODE) into text representation.
ASMJIT_API const char* getErrorString(uint32_t error) ASMJIT_NOTHROW;
//! @}
} // AsmJit namespace
// ============================================================================
// [Platform Specific]
//
// Following enums must be declared by platform specific header:
// - CALL_CONV - Calling convention.
// - VARIABLE_TYPE - Variable type.
// ============================================================================
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
#include "DefsX86X64.h"
#endif // ASMJIT_X86 || ASMJIT_X64
// [Guard]
#endif // _ASMJIT_DEFS_H

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,92 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// We are using sprintf() here.
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif // _MSC_VER
// [Dependencies]
#include "Logger.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// ============================================================================
// [AsmJit::Logger]
// ============================================================================
Logger::Logger() ASMJIT_NOTHROW :
_enabled(true),
_used(true),
_logBinary(false)
{
}
Logger::~Logger() ASMJIT_NOTHROW
{
}
void Logger::logFormat(const char* fmt, ...) ASMJIT_NOTHROW
{
char buf[1024];
sysuint_t len;
va_list ap;
va_start(ap, fmt);
len = vsnprintf(buf, 1023, fmt, ap);
va_end(ap);
logString(buf, len);
}
void Logger::setEnabled(bool enabled) ASMJIT_NOTHROW
{
_enabled = enabled;
_used = enabled;
}
// ============================================================================
// [AsmJit::FileLogger]
// ============================================================================
FileLogger::FileLogger(FILE* stream) ASMJIT_NOTHROW
: _stream(NULL)
{
setStream(stream);
}
void FileLogger::logString(const char* buf, sysuint_t len) ASMJIT_NOTHROW
{
if (!_used) return;
if (len == (sysuint_t)-1) len = strlen(buf);
fwrite(buf, 1, len, _stream);
}
void FileLogger::setEnabled(bool enabled) ASMJIT_NOTHROW
{
_enabled = enabled;
_used = (_enabled == true) & (_stream != NULL);
}
//! @brief Set file stream.
void FileLogger::setStream(FILE* stream) ASMJIT_NOTHROW
{
_stream = stream;
_used = (_enabled == true) & (_stream != NULL);
}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"

View File

@ -0,0 +1,175 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_LOGGER_H
#define _ASMJIT_LOGGER_H
// [Dependencies]
#include "Defs.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
//! @addtogroup AsmJit_Logging
//! @{
//! @brief Abstract logging class.
//!
//! This class can be inherited and reimplemented to fit into your logging
//! subsystem. When reimplementing use @c AsmJit::Logger::log() method to
//! log into your stream.
//!
//! This class also contain @c _enabled member that can be used to enable
//! or disable logging.
struct ASMJIT_API Logger
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create logger.
Logger() ASMJIT_NOTHROW;
//! @brief Destroy logger.
virtual ~Logger() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Logging]
// --------------------------------------------------------------------------
//! @brief Abstract method to log output.
//!
//! Default implementation that is in @c AsmJit::Logger is to do nothing.
//! It's virtual to fit to your logging system.
virtual void logString(const char* buf, sysuint_t len = (sysuint_t)-1) ASMJIT_NOTHROW = 0;
//! @brief Log formatter message (like sprintf) sending output to @c logString() method.
virtual void logFormat(const char* fmt, ...) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Enabled]
// --------------------------------------------------------------------------
//! @brief Return @c true if logging is enabled.
inline bool isEnabled() const ASMJIT_NOTHROW { return _enabled; }
//! @brief Set logging to enabled or disabled.
virtual void setEnabled(bool enabled) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Used]
// --------------------------------------------------------------------------
//! @brief Get whether the logger should be used.
inline bool isUsed() const ASMJIT_NOTHROW { return _used; }
// --------------------------------------------------------------------------
// [LogBinary]
// --------------------------------------------------------------------------
//! @brief Get whether logging binary output.
inline bool getLogBinary() const { return _logBinary; }
//! @brief Get whether to log binary output.
inline void setLogBinary(bool val) { _logBinary = val; }
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief Whether logger is enabled or disabled.
//!
//! Default @c true.
bool _enabled;
//! @brief Whether logger is enabled and can be used.
//!
//! This value can be set by inherited classes to inform @c Logger that
//! assigned stream (or something that can log output) is invalid. If
//! @c _used is false it means that there is no logging output and AsmJit
//! shouldn't use this logger (because all messages will be lost).
//!
//! This is designed only to optimize cases that logger exists, but its
//! configured not to output messages. The API inside Logging and AsmJit
//! should only check this value when needed. The API outside AsmJit should
//! check only whether logging is @c _enabled.
//!
//! Default @c true.
bool _used;
//! @brief Whether to log instruction in binary form.
bool _logBinary;
private:
ASMJIT_DISABLE_COPY(Logger)
};
//! @brief Logger that can log to standard C @c FILE* stream.
struct ASMJIT_API FileLogger : public Logger
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create new @c FileLogger.
//! @param stream FILE stream where logging will be sent (can be @c NULL
//! to disable logging).
FileLogger(FILE* stream = NULL) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Logging]
// --------------------------------------------------------------------------
virtual void logString(const char* buf, sysuint_t len = (sysuint_t)-1) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Enabled]
// --------------------------------------------------------------------------
virtual void setEnabled(bool enabled) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Stream]
// --------------------------------------------------------------------------
//! @brief Get @c FILE* stream.
//!
//! @note Return value can be @c NULL.
inline FILE* getStream() const ASMJIT_NOTHROW { return _stream; }
//! @brief Set @c FILE* stream.
//!
//! @param stream @c FILE stream where to log output (can be @c NULL to
//! disable logging).
void setStream(FILE* stream) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief C file stream.
FILE* _stream;
ASMJIT_DISABLE_COPY(FileLogger)
};
//! @}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"
// [Guard]
#endif // _ASMJIT_LOGGER_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_MEMORYMANAGER_H
#define _ASMJIT_MEMORYMANAGER_H
// [Dependencies]
#include "Build.h"
#include "Defs.h"
// [Api-Begin]
#include "ApiBegin.h"
// [Debug]
// #define ASMJIT_MEMORY_MANAGER_DUMP
namespace AsmJit {
//! @addtogroup AsmJit_MemoryManagement
//! @{
// ============================================================================
// [AsmJit::MemoryManager]
// ============================================================================
//! @brief Virtual memory manager interface.
//!
//! This class is pure virtual. You can get default virtual memory manager using
//! @c getGlobal() method. If you want to create more memory managers with same
//! functionality as global memory manager use @c VirtualMemoryManager class.
struct ASMJIT_API MemoryManager
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create memory manager instance.
MemoryManager() ASMJIT_NOTHROW;
//! @brief Destroy memory manager instance, this means also to free all memory
//! blocks.
virtual ~MemoryManager() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
//! @brief Allocate a @a size bytes of virtual memory.
//!
//! Note that if you are implementing your own virtual memory manager then you
//! can quitly ignore type of allocation. This is mainly for AsmJit to memory
//! manager that allocated memory will be never freed.
virtual void* alloc(sysuint_t size, uint32_t type = MEMORY_ALLOC_FREEABLE) ASMJIT_NOTHROW = 0;
//! @brief Free previously allocated memory at a given @a address.
virtual bool free(void* address) ASMJIT_NOTHROW = 0;
//! @brief Free some tail memory.
virtual bool shrink(void* address, sysuint_t used) ASMJIT_NOTHROW = 0;
//! @brief Free all allocated memory.
virtual void freeAll() ASMJIT_NOTHROW = 0;
//! @brief Get how many bytes are currently used.
virtual sysuint_t getUsedBytes() ASMJIT_NOTHROW = 0;
//! @brief Get how many bytes are currently allocated.
virtual sysuint_t getAllocatedBytes() ASMJIT_NOTHROW = 0;
//! @brief Get global memory manager instance.
//!
//! Global instance is instance of @c VirtualMemoryManager class. Global memory
//! manager is used by default by @ref Assembler::make() and @ref Compiler::make()
//! methods.
static MemoryManager* getGlobal() ASMJIT_NOTHROW;
};
//! @brief Reference implementation of memory manager that uses
//! @ref AsmJit::VirtualMemory class to allocate chunks of virtual memory
//! and bit arrays to manage it.
struct ASMJIT_API VirtualMemoryManager : public MemoryManager
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @c VirtualMemoryManager instance.
VirtualMemoryManager() ASMJIT_NOTHROW;
#if defined(ASMJIT_WINDOWS)
//! @brief Create a @c VirtualMemoryManager instance for process @a hProcess.
//!
//! This is specialized version of constructor available only for windows and
//! usable to alloc/free memory of different process.
VirtualMemoryManager(HANDLE hProcess) ASMJIT_NOTHROW;
#endif // ASMJIT_WINDOWS
//! @brief Destroy the @c VirtualMemoryManager instance, this means also to
//! free all blocks.
virtual ~VirtualMemoryManager() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
virtual void* alloc(sysuint_t size, uint32_t type = MEMORY_ALLOC_FREEABLE) ASMJIT_NOTHROW;
virtual bool free(void* address) ASMJIT_NOTHROW;
virtual bool shrink(void* address, sysuint_t used) ASMJIT_NOTHROW;
virtual void freeAll() ASMJIT_NOTHROW;
virtual sysuint_t getUsedBytes() ASMJIT_NOTHROW;
virtual sysuint_t getAllocatedBytes() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Virtual Memory Manager Specific]
// --------------------------------------------------------------------------
//! @brief Get whether to keep allocated memory after memory manager is
//! destroyed.
//!
//! @sa @c setKeepVirtualMemory().
bool getKeepVirtualMemory() const ASMJIT_NOTHROW;
//! @brief Set whether to keep allocated memory after memory manager is
//! destroyed.
//!
//! This method is usable when patching code of remote process. You need to
//! allocate process memory, store generated assembler into it and patch the
//! method you want to redirect (into your code). This method affects only
//! VirtualMemoryManager destructor. After destruction all internal
//! structures are freed, only the process virtual memory remains.
//!
//! @note Memory allocated with MEMORY_ALLOC_PERMANENT is always kept.
//!
//! @sa @c getKeepVirtualMemory().
void setKeepVirtualMemory(bool keepVirtualMemory) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Debug]
// --------------------------------------------------------------------------
#if defined(ASMJIT_MEMORY_MANAGER_DUMP)
//! @brief Dump memory manager tree into file.
//!
//! Generated output is using DOT language (from graphviz package).
void dump(const char* fileName);
#endif // ASMJIT_MEMORY_MANAGER_DUMP
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
protected:
//! @brief Pointer to private data hidden from the public API.
void* _d;
};
//! @}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"
// [Guard]
#endif // _ASMJIT_MEMORYMANAGER_H

View File

@ -0,0 +1,26 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include "Build.h"
#include "MemoryMarker.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// ============================================================================
// [AsmJit::MemoryMarker]
// ============================================================================
MemoryMarker::MemoryMarker() ASMJIT_NOTHROW {}
MemoryMarker::~MemoryMarker() ASMJIT_NOTHROW {}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"

View File

@ -0,0 +1,55 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_MEMORYMARKER_H
#define _ASMJIT_MEMORYMARKER_H
// [Dependencies]
#include "Build.h"
#include "Defs.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
//! @addtogroup AsmJit_MemoryManagement
//! @{
// ============================================================================
// [AsmJit::MemoryMarker]
// ============================================================================
//! @brief Virtual memory marker interface.
struct ASMJIT_API MemoryMarker
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
MemoryMarker() ASMJIT_NOTHROW;
virtual ~MemoryMarker() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
virtual void mark(const void* ptr, sysuint_t size) ASMJIT_NOTHROW = 0;
private:
ASMJIT_DISABLE_COPY(MemoryMarker)
};
//! @}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"
// [Guard]
#endif // _ASMJIT_MEMORYMARKER_H

View File

@ -0,0 +1,34 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_OPERAND_H
#define _ASMJIT_OPERAND_H
// [Dependencies]
#include "Build.h"
namespace AsmJit {
//! @addtogroup AsmJit_Core
//! @{
// There is currently no platform independent code.
//! @}
} // AsmJit namespace
// ============================================================================
// [Platform Specific]
// ============================================================================
#if defined(ASMJIT_X86) || defined(ASMJIT_X64)
#include "OperandX86X64.h"
#endif // ASMJIT_X86 || ASMJIT_X64
// [Guard]
#endif // _ASMJIT_OPERAND_H

View File

@ -0,0 +1,425 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include "Defs.h"
#include "Operand.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// ============================================================================
// [AsmJit::Registers - no_reg]
// ============================================================================
const GPReg no_reg(_Initialize(), INVALID_VALUE);
// ============================================================================
// [AsmJit::Registers - 8-bit]
// ============================================================================
const GPReg al(_Initialize(), REG_AL);
const GPReg cl(_Initialize(), REG_CL);
const GPReg dl(_Initialize(), REG_DL);
const GPReg bl(_Initialize(), REG_BL);
#if defined(ASMJIT_X64)
const GPReg spl(_Initialize(), REG_SPL);
const GPReg bpl(_Initialize(), REG_BPL);
const GPReg sil(_Initialize(), REG_SIL);
const GPReg dil(_Initialize(), REG_DIL);
const GPReg r8b(_Initialize(), REG_R8B);
const GPReg r9b(_Initialize(), REG_R9B);
const GPReg r10b(_Initialize(), REG_R10B);
const GPReg r11b(_Initialize(), REG_R11B);
const GPReg r12b(_Initialize(), REG_R12B);
const GPReg r13b(_Initialize(), REG_R13B);
const GPReg r14b(_Initialize(), REG_R14B);
const GPReg r15b(_Initialize(), REG_R15B);
#endif // ASMJIT_X64
const GPReg ah(_Initialize(), REG_AH);
const GPReg ch(_Initialize(), REG_CH);
const GPReg dh(_Initialize(), REG_DH);
const GPReg bh(_Initialize(), REG_BH);
// ============================================================================
// [AsmJit::Registers - 16-bit]
// ============================================================================
const GPReg ax(_Initialize(), REG_AX);
const GPReg cx(_Initialize(), REG_CX);
const GPReg dx(_Initialize(), REG_DX);
const GPReg bx(_Initialize(), REG_BX);
const GPReg sp(_Initialize(), REG_SP);
const GPReg bp(_Initialize(), REG_BP);
const GPReg si(_Initialize(), REG_SI);
const GPReg di(_Initialize(), REG_DI);
#if defined(ASMJIT_X64)
const GPReg r8w(_Initialize(), REG_R8W);
const GPReg r9w(_Initialize(), REG_R9W);
const GPReg r10w(_Initialize(), REG_R10W);
const GPReg r11w(_Initialize(), REG_R11W);
const GPReg r12w(_Initialize(), REG_R12W);
const GPReg r13w(_Initialize(), REG_R13W);
const GPReg r14w(_Initialize(), REG_R14W);
const GPReg r15w(_Initialize(), REG_R15W);
#endif // ASMJIT_X64
// ============================================================================
// [AsmJit::Registers - 32-bit]
// ============================================================================
const GPReg eax(_Initialize(), REG_EAX);
const GPReg ecx(_Initialize(), REG_ECX);
const GPReg edx(_Initialize(), REG_EDX);
const GPReg ebx(_Initialize(), REG_EBX);
const GPReg esp(_Initialize(), REG_ESP);
const GPReg ebp(_Initialize(), REG_EBP);
const GPReg esi(_Initialize(), REG_ESI);
const GPReg edi(_Initialize(), REG_EDI);
#if defined(ASMJIT_X64)
const GPReg r8d(_Initialize(), REG_R8D);
const GPReg r9d(_Initialize(), REG_R9D);
const GPReg r10d(_Initialize(), REG_R10D);
const GPReg r11d(_Initialize(), REG_R11D);
const GPReg r12d(_Initialize(), REG_R12D);
const GPReg r13d(_Initialize(), REG_R13D);
const GPReg r14d(_Initialize(), REG_R14D);
const GPReg r15d(_Initialize(), REG_R15D);
#endif // ASMJIT_X64
// ============================================================================
// [AsmJit::Registers - 64-bit]
// ============================================================================
#if defined(ASMJIT_X64)
const GPReg rax(_Initialize(), REG_RAX);
const GPReg rcx(_Initialize(), REG_RCX);
const GPReg rdx(_Initialize(), REG_RDX);
const GPReg rbx(_Initialize(), REG_RBX);
const GPReg rsp(_Initialize(), REG_RSP);
const GPReg rbp(_Initialize(), REG_RBP);
const GPReg rsi(_Initialize(), REG_RSI);
const GPReg rdi(_Initialize(), REG_RDI);
const GPReg r8(_Initialize(), REG_R8);
const GPReg r9(_Initialize(), REG_R9);
const GPReg r10(_Initialize(), REG_R10);
const GPReg r11(_Initialize(), REG_R11);
const GPReg r12(_Initialize(), REG_R12);
const GPReg r13(_Initialize(), REG_R13);
const GPReg r14(_Initialize(), REG_R14);
const GPReg r15(_Initialize(), REG_R15);
#endif // ASMJIT_X64
// ============================================================================
// [AsmJit::Registers - Native (AsmJit extension)]
// ============================================================================
const GPReg nax(_Initialize(), REG_NAX);
const GPReg ncx(_Initialize(), REG_NCX);
const GPReg ndx(_Initialize(), REG_NDX);
const GPReg nbx(_Initialize(), REG_NBX);
const GPReg nsp(_Initialize(), REG_NSP);
const GPReg nbp(_Initialize(), REG_NBP);
const GPReg nsi(_Initialize(), REG_NSI);
const GPReg ndi(_Initialize(), REG_NDI);
// ============================================================================
// [AsmJit::Registers - MM]
// ============================================================================
const MMReg mm0(_Initialize(), REG_MM0);
const MMReg mm1(_Initialize(), REG_MM1);
const MMReg mm2(_Initialize(), REG_MM2);
const MMReg mm3(_Initialize(), REG_MM3);
const MMReg mm4(_Initialize(), REG_MM4);
const MMReg mm5(_Initialize(), REG_MM5);
const MMReg mm6(_Initialize(), REG_MM6);
const MMReg mm7(_Initialize(), REG_MM7);
// ============================================================================
// [AsmJit::Registers - XMM]
// ============================================================================
const XMMReg xmm0(_Initialize(), REG_XMM0);
const XMMReg xmm1(_Initialize(), REG_XMM1);
const XMMReg xmm2(_Initialize(), REG_XMM2);
const XMMReg xmm3(_Initialize(), REG_XMM3);
const XMMReg xmm4(_Initialize(), REG_XMM4);
const XMMReg xmm5(_Initialize(), REG_XMM5);
const XMMReg xmm6(_Initialize(), REG_XMM6);
const XMMReg xmm7(_Initialize(), REG_XMM7);
#if defined(ASMJIT_X64)
const XMMReg xmm8(_Initialize(), REG_XMM8);
const XMMReg xmm9(_Initialize(), REG_XMM9);
const XMMReg xmm10(_Initialize(), REG_XMM10);
const XMMReg xmm11(_Initialize(), REG_XMM11);
const XMMReg xmm12(_Initialize(), REG_XMM12);
const XMMReg xmm13(_Initialize(), REG_XMM13);
const XMMReg xmm14(_Initialize(), REG_XMM14);
const XMMReg xmm15(_Initialize(), REG_XMM15);
#endif // ASMJIT_X64
// ============================================================================
// [AsmJit::Registers - Segment]
// ============================================================================
const SegmentReg cs(_Initialize(), REG_CS);
const SegmentReg ss(_Initialize(), REG_SS);
const SegmentReg ds(_Initialize(), REG_DS);
const SegmentReg es(_Initialize(), REG_ES);
const SegmentReg fs(_Initialize(), REG_FS);
const SegmentReg gs(_Initialize(), REG_GS);
// ============================================================================
// [AsmJit::Immediate]
// ============================================================================
//! @brief Create signed immediate value operand.
Imm imm(sysint_t i) ASMJIT_NOTHROW
{
return Imm(i, false);
}
//! @brief Create unsigned immediate value operand.
Imm uimm(sysuint_t i) ASMJIT_NOTHROW
{
return Imm((sysint_t)i, true);
}
// ============================================================================
// [AsmJit::BaseVar]
// ============================================================================
Mem _BaseVarMem(const BaseVar& var, uint32_t ptrSize) ASMJIT_NOTHROW
{
Mem m; //(_DontInitialize());
m._mem.op = OPERAND_MEM;
m._mem.size = (ptrSize == INVALID_VALUE) ? var.getSize() : (uint8_t)ptrSize;
m._mem.type = OPERAND_MEM_NATIVE;
m._mem.segmentPrefix = SEGMENT_NONE;
m._mem.sizePrefix = 0;
m._mem.shift = 0;
m._mem.id = var.getId();
m._mem.base = INVALID_VALUE;
m._mem.index = INVALID_VALUE;
m._mem.target = NULL;
m._mem.displacement = 0;
return m;
}
Mem _BaseVarMem(const BaseVar& var, uint32_t ptrSize, sysint_t disp) ASMJIT_NOTHROW
{
Mem m; //(_DontInitialize());
m._mem.op = OPERAND_MEM;
m._mem.size = (ptrSize == INVALID_VALUE) ? var.getSize() : (uint8_t)ptrSize;
m._mem.type = OPERAND_MEM_NATIVE;
m._mem.segmentPrefix = SEGMENT_NONE;
m._mem.sizePrefix = 0;
m._mem.shift = 0;
m._mem.id = var.getId();
m._mem.base = INVALID_VALUE;
m._mem.index = INVALID_VALUE;
m._mem.target = NULL;
m._mem.displacement = disp;
return m;
}
Mem _BaseVarMem(const BaseVar& var, uint32_t ptrSize, const GPVar& index, uint32_t shift, sysint_t disp) ASMJIT_NOTHROW
{
Mem m; //(_DontInitialize());
m._mem.op = OPERAND_MEM;
m._mem.size = (ptrSize == INVALID_VALUE) ? var.getSize() : (uint8_t)ptrSize;
m._mem.type = OPERAND_MEM_NATIVE;
m._mem.segmentPrefix = SEGMENT_NONE;
m._mem.sizePrefix = 0;
m._mem.shift = shift;
m._mem.id = var.getId();
m._mem.base = INVALID_VALUE;
m._mem.index = index.getId();
m._mem.target = NULL;
m._mem.displacement = disp;
return m;
}
// ============================================================================
// [AsmJit::Mem - ptr[]]
// ============================================================================
Mem _MemPtrBuild(
const Label& label, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
return Mem(label, disp, ptrSize);
}
Mem _MemPtrBuild(
const Label& label,
const GPReg& index, uint32_t shift, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
Mem m(label, disp, ptrSize);
m._mem.index = index.getRegIndex();
m._mem.shift = shift;
return m;
}
Mem _MemPtrBuild(
const Label& label,
const GPVar& index, uint32_t shift, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
Mem m(label, disp, ptrSize);
m._mem.index = index.getId();
m._mem.shift = shift;
return m;
}
// ============================================================================
// [AsmJit::Mem - ptr[] - Absolute Addressing]
// ============================================================================
ASMJIT_API Mem _MemPtrAbs(
void* target, sysint_t disp,
uint32_t segmentPrefix, uint32_t ptrSize)
ASMJIT_NOTHROW
{
Mem m;
m._mem.size = ptrSize;
m._mem.type = OPERAND_MEM_ABSOLUTE;
m._mem.segmentPrefix = segmentPrefix;
m._mem.target = target;
m._mem.displacement = disp;
return m;
}
ASMJIT_API Mem _MemPtrAbs(
void* target,
const GPReg& index, uint32_t shift, sysint_t disp,
uint32_t segmentPrefix, uint32_t ptrSize)
ASMJIT_NOTHROW
{
Mem m;// (_DontInitialize());
m._mem.op = OPERAND_MEM;
m._mem.size = ptrSize;
m._mem.type = OPERAND_MEM_ABSOLUTE;
m._mem.segmentPrefix = (uint8_t)segmentPrefix;
#if defined(ASMJIT_X86)
m._mem.sizePrefix = index.getSize() != 4;
#else
m._mem.sizePrefix = index.getSize() != 8;
#endif
m._mem.shift = shift;
m._mem.id = INVALID_VALUE;
m._mem.base = INVALID_VALUE;
m._mem.index = index.getRegIndex();
m._mem.target = target;
m._mem.displacement = disp;
return m;
}
ASMJIT_API Mem _MemPtrAbs(
void* target,
const GPVar& index, uint32_t shift, sysint_t disp,
uint32_t segmentPrefix, uint32_t ptrSize)
ASMJIT_NOTHROW
{
Mem m;// (_DontInitialize());
m._mem.op = OPERAND_MEM;
m._mem.size = ptrSize;
m._mem.type = OPERAND_MEM_ABSOLUTE;
m._mem.segmentPrefix = (uint8_t)segmentPrefix;
#if defined(ASMJIT_X86)
m._mem.sizePrefix = index.getSize() != 4;
#else
m._mem.sizePrefix = index.getSize() != 8;
#endif
m._mem.shift = shift;
m._mem.id = INVALID_VALUE;
m._mem.base = INVALID_VALUE;
m._mem.index = index.getId();
m._mem.target = target;
m._mem.displacement = disp;
return m;
}
// ============================================================================
// [AsmJit::Mem - ptr[base + displacement]]
// ============================================================================
Mem _MemPtrBuild(
const GPReg& base, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
return Mem(base, disp, ptrSize);
}
Mem _MemPtrBuild(
const GPReg& base,
const GPReg& index, uint32_t shift, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
return Mem(base, index, shift, disp, ptrSize);
}
Mem _MemPtrBuild(
const GPVar& base, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
return Mem(base, disp, ptrSize);
}
Mem _MemPtrBuild(
const GPVar& base,
const GPVar& index, uint32_t shift, sysint_t disp, uint32_t ptrSize)
ASMJIT_NOTHROW
{
return Mem(base, index, shift, disp, ptrSize);
}
} // AsmJit namespace

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include <stdio.h>
#include "Platform.h"
// [Api-Begin]
#include "ApiBegin.h"
// helpers
namespace AsmJit {
// ============================================================================
// [AsmJit::Assert]
// ============================================================================
void assertionFailure(const char* file, int line, const char* exp)
{
fprintf(stderr,
"*** ASSERTION FAILURE at %s (line %d)\n"
"*** %s\n", file, line, exp);
exit(1);
}
// ============================================================================
// [AsmJit::Helpers]
// ============================================================================
static bool isAligned(sysuint_t base, sysuint_t alignment)
{
return base % alignment == 0;
}
static sysuint_t roundUp(sysuint_t base, sysuint_t pageSize)
{
sysuint_t over = base % pageSize;
return base + (over > 0 ? pageSize - over : 0);
}
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
// figure 3-3, page 48, where the function is called clp2.
static sysuint_t roundUpToPowerOf2(sysuint_t base)
{
base -= 1;
base = base | (base >> 1);
base = base | (base >> 2);
base = base | (base >> 4);
base = base | (base >> 8);
base = base | (base >> 16);
// I'm trying to make this portable and MSVC strikes me the warning C4293:
// "Shift count negative or too big, undefined behavior"
// Fixing...
#if _MSC_VER
# pragma warning(disable: 4293)
#endif // _MSC_VER
if (sizeof(sysuint_t) >= 8)
base = base | (base >> 32);
return base + 1;
}
} // AsmJit namespace
// ============================================================================
// [AsmJit::VirtualMemory::Windows]
// ============================================================================
#if defined(ASMJIT_WINDOWS)
#include <windows.h>
namespace AsmJit {
struct ASMJIT_HIDDEN VirtualMemoryLocal
{
VirtualMemoryLocal() ASMJIT_NOTHROW
{
SYSTEM_INFO info;
GetSystemInfo(&info);
alignment = info.dwAllocationGranularity;
pageSize = roundUpToPowerOf2(info.dwPageSize);
}
sysuint_t alignment;
sysuint_t pageSize;
};
static VirtualMemoryLocal& vm() ASMJIT_NOTHROW
{
static VirtualMemoryLocal vm;
return vm;
};
void* VirtualMemory::alloc(sysuint_t length, sysuint_t* allocated, bool canExecute)
ASMJIT_NOTHROW
{
return allocProcessMemory(GetCurrentProcess(), length, allocated, canExecute);
}
void VirtualMemory::free(void* addr, sysuint_t length)
ASMJIT_NOTHROW
{
return freeProcessMemory(GetCurrentProcess(), addr, length);
}
void* VirtualMemory::allocProcessMemory(HANDLE hProcess, sysuint_t length, sysuint_t* allocated, bool canExecute) ASMJIT_NOTHROW
{
// VirtualAlloc rounds allocated size to page size automatically.
sysuint_t msize = roundUp(length, vm().pageSize);
// Windows XP SP2 / Vista allow Data Excution Prevention (DEP).
WORD protect = canExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
LPVOID mbase = VirtualAllocEx(hProcess, NULL, msize, MEM_COMMIT | MEM_RESERVE, protect);
if (mbase == NULL) return NULL;
ASMJIT_ASSERT(isAligned(reinterpret_cast<sysuint_t>(mbase), vm().alignment));
if (allocated) *allocated = msize;
return mbase;
}
void VirtualMemory::freeProcessMemory(HANDLE hProcess, void* addr, sysuint_t /* length */) ASMJIT_NOTHROW
{
VirtualFreeEx(hProcess, addr, 0, MEM_RELEASE);
}
sysuint_t VirtualMemory::getAlignment()
ASMJIT_NOTHROW
{
return vm().alignment;
}
sysuint_t VirtualMemory::getPageSize()
ASMJIT_NOTHROW
{
return vm().pageSize;
}
} // AsmJit
#endif // ASMJIT_WINDOWS
// ============================================================================
// [AsmJit::VirtualMemory::Posix]
// ============================================================================
#if defined(ASMJIT_POSIX)
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
// MacOS uses MAP_ANON instead of MAP_ANONYMOUS
#ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS MAP_ANON
#endif
namespace AsmJit {
struct ASMJIT_HIDDEN VirtualMemoryLocal
{
VirtualMemoryLocal() ASMJIT_NOTHROW
{
alignment = pageSize = getpagesize();
}
sysuint_t alignment;
sysuint_t pageSize;
};
static VirtualMemoryLocal& vm()
ASMJIT_NOTHROW
{
static VirtualMemoryLocal vm;
return vm;
}
void* VirtualMemory::alloc(sysuint_t length, sysuint_t* allocated, bool canExecute)
ASMJIT_NOTHROW
{
sysuint_t msize = roundUp(length, vm().pageSize);
int protection = PROT_READ | PROT_WRITE | (canExecute ? PROT_EXEC : 0);
void* mbase = mmap(NULL, msize, protection, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (mbase == MAP_FAILED) return NULL;
if (allocated) *allocated = msize;
return mbase;
}
void VirtualMemory::free(void* addr, sysuint_t length)
ASMJIT_NOTHROW
{
munmap(addr, length);
}
sysuint_t VirtualMemory::getAlignment()
ASMJIT_NOTHROW
{
return vm().alignment;
}
sysuint_t VirtualMemory::getPageSize()
ASMJIT_NOTHROW
{
return vm().pageSize;
}
} // AsmJit
#endif // ASMJIT_POSIX
// [Api-End]
#include "ApiEnd.h"

View File

@ -0,0 +1,208 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_PLATFORM_H
#define _ASMJIT_PLATFORM_H
// [Dependencies]
#include "Build.h"
#if defined(ASMJIT_WINDOWS)
#include <windows.h>
#endif // ASMJIT_WINDOWS
#if defined(ASMJIT_POSIX)
#include <pthread.h>
#endif // ASMJIT_POSIX
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
//! @addtogroup AsmJit_Util
//! @{
// ============================================================================
// [AsmJit::Assert]
// ============================================================================
//! @brief Called in debug build on assertion failure.
//! @param file Source file name where it happened.
//! @param line Line in the source file.
//! @param exp Expression what failed.
//!
//! If you have problems with assertions simply put a breakpoint into
//! AsmJit::assertionFailure() method (see AsmJit/Platform.cpp file) and see
//! call stack.
ASMJIT_API void assertionFailure(const char* file, int line, const char* exp);
// ============================================================================
// [AsmJit::Lock]
// ============================================================================
//! @brief Lock - used in thread-safe code for locking.
struct ASMJIT_HIDDEN Lock
{
#if defined(ASMJIT_WINDOWS)
typedef CRITICAL_SECTION Handle;
#endif // ASMJIT_WINDOWS
#if defined(ASMJIT_POSIX)
typedef pthread_mutex_t Handle;
#endif // ASMJIT_POSIX
//! @brief Create a new @ref Lock instance.
inline Lock() ASMJIT_NOTHROW
{
#if defined(ASMJIT_WINDOWS)
InitializeCriticalSection(&_handle);
// InitializeLockAndSpinCount(&_handle, 2000);
#endif // ASMJIT_WINDOWS
#if defined(ASMJIT_POSIX)
pthread_mutex_init(&_handle, NULL);
#endif // ASMJIT_POSIX
}
//! @brief Destroy the @ref Lock instance.
inline ~Lock() ASMJIT_NOTHROW
{
#if defined(ASMJIT_WINDOWS)
DeleteCriticalSection(&_handle);
#endif // ASMJIT_WINDOWS
#if defined(ASMJIT_POSIX)
pthread_mutex_destroy(&_handle);
#endif // ASMJIT_POSIX
}
//! @brief Get handle.
inline Handle& getHandle() ASMJIT_NOTHROW
{
return _handle;
}
//! @overload
inline const Handle& getHandle() const ASMJIT_NOTHROW
{
return _handle;
}
//! @brief Lock.
inline void lock() ASMJIT_NOTHROW
{
#if defined(ASMJIT_WINDOWS)
EnterCriticalSection(&_handle);
#endif // ASMJIT_WINDOWS
#if defined(ASMJIT_POSIX)
pthread_mutex_lock(&_handle);
#endif // ASMJIT_POSIX
}
//! @brief Unlock.
inline void unlock() ASMJIT_NOTHROW
{
#if defined(ASMJIT_WINDOWS)
LeaveCriticalSection(&_handle);
#endif // ASMJIT_WINDOWS
#if defined(ASMJIT_POSIX)
pthread_mutex_unlock(&_handle);
#endif // ASMJIT_POSIX
}
private:
//! @brief Handle.
Handle _handle;
// Disable copy.
ASMJIT_DISABLE_COPY(Lock)
};
// ============================================================================
// [AsmJit::AutoLock]
// ============================================================================
//! @brief Scope auto locker.
struct ASMJIT_HIDDEN AutoLock
{
//! @brief Locks @a target.
inline AutoLock(Lock& target) ASMJIT_NOTHROW : _target(target)
{
_target.lock();
}
//! @brief Unlocks target.
inline ~AutoLock() ASMJIT_NOTHROW
{
_target.unlock();
}
private:
//! @brief Pointer to target (lock).
Lock& _target;
// Disable copy.
ASMJIT_DISABLE_COPY(AutoLock)
};
// ============================================================================
// [AsmJit::VirtualMemory]
// ============================================================================
//! @brief Class that helps with allocating memory for executing code
//! generated by JIT compiler.
//!
//! There are defined functions that provides facility to allocate and free
//! memory where can be executed code. If processor and operating system
//! supports execution protection then you can't run code from normally
//! malloc()'ed memory.
//!
//! Functions are internally implemented by operating system dependent way.
//! VirtualAlloc() function is used for Windows operating system and mmap()
//! for posix ones. If you want to study or create your own functions, look
//! at VirtualAlloc() or mmap() documentation (depends on you target OS).
//!
//! Under posix operating systems is also useable mprotect() function, that
//! can enable execution protection to malloc()'ed memory block.
struct ASMJIT_API VirtualMemory
{
//! @brief Allocate virtual memory.
//!
//! Pages are readable/writeable, but they are not guaranteed to be
//! executable unless 'canExecute' is true. Returns the address of
//! allocated memory, or NULL if failed.
static void* alloc(sysuint_t length, sysuint_t* allocated, bool canExecute) ASMJIT_NOTHROW;
//! @brief Free memory allocated by @c alloc()
static void free(void* addr, sysuint_t length) ASMJIT_NOTHROW;
#if defined(ASMJIT_WINDOWS)
//! @brief Allocate virtual memory of @a hProcess.
//!
//! @note This function is windows specific and unportable.
static void* allocProcessMemory(HANDLE hProcess, sysuint_t length, sysuint_t* allocated, bool canExecute) ASMJIT_NOTHROW;
//! @brief Free virtual memory of @a hProcess.
//!
//! @note This function is windows specific and unportable.
static void freeProcessMemory(HANDLE hProcess, void* addr, sysuint_t length) ASMJIT_NOTHROW;
#endif // ASMJIT_WINDOWS
//! @brief Get the alignment guaranteed by alloc().
static sysuint_t getAlignment() ASMJIT_NOTHROW;
//! @brief Get size of single page.
static sysuint_t getPageSize() ASMJIT_NOTHROW;
};
//! @}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"
// [Guard]
#endif // _ASMJIT_PLATFORM_H

View File

@ -0,0 +1,115 @@
AsmJit - Complete x86/x64 JIT Assembler for C++ Language - Version 1.0
======================================================================
http://code.google.com/p/asmjit/
Introduction
============
AsmJit is complete x86/x64 JIT Assembler for C++ language. It supports FPU,
MMX, 3dNow, SSE, SSE2, SSE3 and SSE4 intrinsics, powerful compiler that helps
to write portable functions for 32-bit (x86) and 64-bit (x64) architectures.
AsmJit can be used to create functions at runtime that can be called from
existing (but also generated) C/C++ code.
AsmJit is crossplatform library that supports various compilers and operating
systems. Currently only limitation is x86 (32-bit) or x64 (64-bit) processor.
Currently tested operating systems are Windows (32 bit and 64 bit), Linux (32
bit and 64 bit) and MacOSX (32 bit).
Assembler / Compiler
====================
AsmJit library contains two main classes for code generation with different
goals. First main code generation class is called Assembler and contains low
level API that can be used to generate JIT binary code. It directly emits
binary stream that represents encoded x86/x64 assembler opcodes. Together
with operands and labels it can be used to generate complete code.
There is also class named Compiler that allows to develop crossplatform
assembler code without worring about function calling conventions and
registers allocation. It can be also used to write 32 bit and 64 bit portable
code. Compiler is recommended class to use for high level code generation.
Building & Configuring
======================
You have two choices when using AsmJit library:
1. Embed files into your project - This is simplest way how to use AsmJit
library. If you want to do this, edit AsmJit/Config.h file and undefine
"// #define ASMJIT_API" macro or define ASMJIT_API using your IDE or
makefiles (for example gcc can accept -DASMJIT_API to define it).
You will bypass shared library (dll) support by defining ASMJIT_API .
2. Build shared library and link your project to it. This is now default way
for using AsmJit library, but can be easily changed. To build dynamically
linked library use cmake (http://www.cmake.org/) that can generate
makefiles and project files for your IDE (included is Visual Studio,
Code::Blocks, Eclipse, KDevelop and more...).
To build shared library use this cmake command (or use provided scripts):
cmake {Replace this with AsmJit directory} DASMJIT_BUILD_LIBRARY=1
Directory structure
===================
AsmJit - Directory where are sources needed to compile AsmJit. This directory
is designed to be embeddable to your application as easy as possible. There is
also AsmJit/Config.h header where you can configure platform (if autodetection
not works for you) and application specific features. Look at platform macros
to change some backends to your preferences.
Test - Directory with cmake project to test AsmJit library. It generates simple
command line applications for testing AsmJit functionality. It's only here as a
demonstration how easy this can be done. These applications are also examples
how to use AsmJit API. For example look at testjit for simple code generation,
testcpu for cpuid() and cpuInfo() demonstration, testcompiler for compiler
example, etc...
Supported compilers
===================
AsmJit is successfully tested by following compilers:
- MSVC (VC6.0, VC7.1, VC8.0)
- GCC (3.4.X+ including MinGW and 4.1.X+, 4.3.X+, 4.4.X+)
If you are using different compiler and you have troubles, please use AsmJit
mailing list or create an Issue (see project home page).
Supported platforms
===================
Fully supported platforms at this time are X86 (32-bit) and X86_64/X64 (64-bit).
Other platforms need volunteers. Also note that AsmJit is designed to generate
assembler binary only for host CPU, don't try to generate 64-bit assembler in
32 bit mode and vica versa - this is not designed to work and will not work.
Examples
========
Examples and tests can be found in these places:
- AsmJit home page <http://code.google.com/p/asmjit/>
- AsmJit wiki <http://code.google.com/p/asmjit/w/list>
- AsmJit Test directory (in this package)
License
=======
AsmJit can be distributed under zlib license:
<http://www.opensource.org/licenses/zlib-license.php>
Google Groups and Mailing Lists
===============================
AsmJit google group:
* http://groups.google.com/group/asmjit-dev
AsmJit mailing list:
* asmjit-dev@googlegroups.com
Contact Author/Maintainer
=========================
Petr Kobalicek <kobalicek.petr@gmail.com>

View File

@ -0,0 +1,97 @@
#!/usr/bin/env python
# =============================================================================
# [Regenerate.py - Description]
#
# This Python script will regenerate instruction names in Assembler{$ARCH}.cpp
# files. Idea is that there can be big instruction table and this script tries
# to minimize runtime relocation data of AsmJit library.
# =============================================================================
# =============================================================================
# [Configuration]
# =============================================================================
# Files to process.
FILES = [
"DefsX86X64.cpp"
]
# =============================================================================
# [Imports]
# =============================================================================
import os, re, string
# =============================================================================
# [Helpers]
# =============================================================================
def readFile(fileName):
handle = open(fileName, "rb")
data = handle.read()
handle.close()
return data
def writeFile(fileName, data):
handle = open(fileName, "wb")
handle.truncate()
handle.write(data)
handle.close()
# =============================================================================
# [Main]
# =============================================================================
def processFile(fileName):
data = readFile(fileName);
din = data
r = re.compile(r"instructionDescription\[\][\s]*=[\s]*{(?P<BLOCK>[^}])*}")
m = r.search(din)
if not m:
print "Cannot match instruction data in " + fileName
exit(0)
din = din[m.start():m.end()]
dout = ""
dinst = []
daddr = []
hinst = {}
r = re.compile(r'\"(?P<INST>[A-Za-z0-9_ ]+)\"')
dpos = 0
for m in r.finditer(din):
inst = m.group("INST")
if not inst in hinst:
dinst.append(inst)
hinst[inst] = dpos
daddr.append(dpos)
dpos += len(inst) + 1
dout += "const char instructionName[] =\n"
for i in xrange(len(dinst)):
dout += " \"" + dinst[i] + "\\0\"\n"
dout += " ;\n"
dout += "\n"
for i in xrange(len(dinst)):
dout += "#define INST_" + dinst[i].upper().replace(" ", "_") + "_INDEX" + " " + str(daddr[i]) + "\n"
mb_string = "// ${INSTRUCTION_DATA_BEGIN}\n"
me_string = "// ${INSTRUCTION_DATA_END}\n"
mb = data.index(mb_string)
me = data.index(me_string)
data = data[:mb + len(mb_string)] + dout + data[me:]
writeFile(fileName, data)
for fileName in FILES:
processFile(fileName)

View File

@ -0,0 +1,266 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Dependencies]
#include "Build.h"
#include "Util_p.h"
// [Api-Begin]
#include "ApiBegin.h"
namespace AsmJit {
// ============================================================================
// [AsmJit::Util]
// ============================================================================
static const char letters[] = "0123456789ABCDEF";
char* Util::mycpy(char* dst, const char* src, sysuint_t len) ASMJIT_NOTHROW
{
if (src == NULL) return dst;
if (len == (sysuint_t)-1)
{
while (*src) *dst++ = *src++;
}
else
{
memcpy(dst, src, len);
dst += len;
}
return dst;
}
char* Util::myfill(char* dst, const int c, sysuint_t len) ASMJIT_NOTHROW
{
memset(dst, c, len);
return dst + len;
}
char* Util::myhex(char* dst, const uint8_t* src, sysuint_t len) ASMJIT_NOTHROW
{
for (sysuint_t i = len; i; i--, dst += 2, src += 1)
{
dst[0] = letters[(src[0] >> 4) & 0xF];
dst[1] = letters[(src[0] ) & 0xF];
}
return dst;
}
// Not too efficient, but this is mainly for debugging:)
char* Util::myutoa(char* dst, sysuint_t i, sysuint_t base) ASMJIT_NOTHROW
{
ASMJIT_ASSERT(base <= 16);
char buf[128];
char* p = buf + 128;
do {
sysint_t b = i % base;
*--p = letters[b];
i /= base;
} while (i);
return Util::mycpy(dst, p, (sysuint_t)(buf + 128 - p));
}
char* Util::myitoa(char* dst, sysint_t i, sysuint_t base) ASMJIT_NOTHROW
{
if (i < 0)
{
*dst++ = '-';
i = -i;
}
return Util::myutoa(dst, (sysuint_t)i, base);
}
// ============================================================================
// [AsmJit::Buffer]
// ============================================================================
void Buffer::emitData(const void* dataPtr, sysuint_t dataLen) ASMJIT_NOTHROW
{
sysint_t max = getCapacity() - getOffset();
if ((sysuint_t)max < dataLen)
{
if (!realloc(getOffset() + dataLen)) return;
}
memcpy(_cur, dataPtr, dataLen);
_cur += dataLen;
}
bool Buffer::realloc(sysint_t to) ASMJIT_NOTHROW
{
if (getCapacity() < to)
{
sysint_t len = getOffset();
uint8_t *newdata;
if (_data)
newdata = (uint8_t*)ASMJIT_REALLOC(_data, to);
else
newdata = (uint8_t*)ASMJIT_MALLOC(to);
if (!newdata) return false;
_data = newdata;
_cur = newdata + len;
_max = newdata + to;
_max -= (to >= _growThreshold) ? _growThreshold : to;
_capacity = to;
}
return true;
}
bool Buffer::grow() ASMJIT_NOTHROW
{
sysint_t to = _capacity;
if (to < 512)
to = 1024;
else if (to > 65536)
to += 65536;
else
to <<= 1;
return realloc(to);
}
void Buffer::clear() ASMJIT_NOTHROW
{
_cur = _data;
}
void Buffer::free() ASMJIT_NOTHROW
{
if (!_data) return;
ASMJIT_FREE(_data);
_data = NULL;
_cur = NULL;
_max = NULL;
_capacity = 0;
}
uint8_t* Buffer::take() ASMJIT_NOTHROW
{
uint8_t* data = _data;
_data = NULL;
_cur = NULL;
_max = NULL;
_capacity = 0;
return data;
}
// ============================================================================
// [AsmJit::Zone]
// ============================================================================
Zone::Zone(sysuint_t chunkSize) ASMJIT_NOTHROW
{
_chunks = NULL;
_total = 0;
_chunkSize = chunkSize;
}
Zone::~Zone() ASMJIT_NOTHROW
{
freeAll();
}
void* Zone::zalloc(sysuint_t size) ASMJIT_NOTHROW
{
// Align to 4 or 8 bytes.
size = (size + sizeof(sysint_t)-1) & ~(sizeof(sysint_t)-1);
Chunk* cur = _chunks;
if (!cur || cur->getRemainingBytes() < size)
{
sysuint_t chSize = _chunkSize;
if (chSize < size) chSize = size;
cur = (Chunk*)ASMJIT_MALLOC(sizeof(Chunk) - sizeof(void*) + chSize);
if (!cur) return NULL;
cur->prev = _chunks;
cur->pos = 0;
cur->size = _chunkSize;
_chunks = cur;
}
uint8_t* p = cur->data + cur->pos;
cur->pos += size;
_total += size;
return (void*)p;
}
char* Zone::zstrdup(const char* str) ASMJIT_NOTHROW
{
if (str == NULL) return NULL;
sysuint_t len = strlen(str);
if (len == 0) return NULL;
// Include NULL terminator.
len++;
// Limit string length.
if (len > 256) len = 256;
char* m = reinterpret_cast<char*>(zalloc((len + 15) & ~15));
if (!m) return NULL;
memcpy(m, str, len);
m[len-1] = '\0';
return m;
}
void Zone::clear() ASMJIT_NOTHROW
{
Chunk* cur = _chunks;
if (!cur) return;
_chunks->pos = 0;
_chunks->prev = NULL;
_total = 0;
cur = cur->prev;
while (cur)
{
Chunk* prev = cur->prev;
ASMJIT_FREE(cur);
cur = prev;
}
}
void Zone::freeAll() ASMJIT_NOTHROW
{
Chunk* cur = _chunks;
_chunks = NULL;
_total = 0;
while (cur)
{
Chunk* prev = cur->prev;
ASMJIT_FREE(cur);
cur = prev;
}
}
} // AsmJit namespace
// [Api-End]
#include "ApiEnd.h"

View File

@ -0,0 +1,914 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_UTIL_H
#define _ASMJIT_UTIL_H
// [Dependencies]
#include "Build.h"
#include <stdlib.h>
#include <string.h>
namespace AsmJit {
//! @addtogroup AsmJit_Util
//! @{
// ============================================================================
// [AsmJit::Macros]
// ============================================================================
// Skip documenting this.
#if !defined(ASMJIT_NODOC)
struct ASMJIT_HIDDEN _DontInitialize {};
struct ASMJIT_HIDDEN _Initialize {};
#endif // !ASMJIT_NODOC
// ============================================================================
// [AsmJit::Util]
// ============================================================================
namespace Util {
// ============================================================================
// [AsmJit::Util::isInt?]
// ============================================================================
//! @brief Returns @c true if a given integer @a x is signed 8-bit integer
static inline bool isInt8(sysint_t x) ASMJIT_NOTHROW { return x >= -128 && x <= 127; }
//! @brief Returns @c true if a given integer @a x is unsigned 8-bit integer
static inline bool isUInt8(sysint_t x) ASMJIT_NOTHROW { return x >= 0 && x <= 255; }
//! @brief Returns @c true if a given integer @a x is signed 16-bit integer
static inline bool isInt16(sysint_t x) ASMJIT_NOTHROW { return x >= -32768 && x <= 32767; }
//! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer
static inline bool isUInt16(sysint_t x) ASMJIT_NOTHROW { return x >= 0 && x <= 65535; }
//! @brief Returns @c true if a given integer @a x is signed 16-bit integer
static inline bool isInt32(sysint_t x) ASMJIT_NOTHROW
{
#if defined(ASMJIT_X86)
return true;
#else
return x >= ASMJIT_INT64_C(-2147483648) && x <= ASMJIT_INT64_C(2147483647);
#endif
}
//! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer
static inline bool isUInt32(sysint_t x) ASMJIT_NOTHROW
{
#if defined(ASMJIT_X86)
return x >= 0;
#else
return x >= 0 && x <= ASMJIT_INT64_C(4294967295);
#endif
}
// ============================================================================
// [Bit Utils]
// ============================================================================
static inline uint32_t maskFromIndex(uint32_t x)
{
return (1U << x);
}
static inline uint32_t maskUpToIndex(uint32_t x)
{
if (x >= 32)
return 0xFFFFFFFF;
else
return (1U << x) - 1;
}
// From http://graphics.stanford.edu/~seander/bithacks.html .
static inline uint32_t bitCount(uint32_t x)
{
x = x - ((x >> 1) & 0x55555555U);
x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U);
return (((x + (x >> 4)) & 0xF0F0F0FU) * 0x1010101U) >> 24;
}
static inline uint32_t findFirstBit(uint32_t mask) ASMJIT_NOTHROW
{
for (uint32_t i = 0, bit = 1; i < sizeof(uint32_t) * 8; i++, bit <<= 1)
{
if (mask & bit) return i;
}
// INVALID_VALUE.
return 0xFFFFFFFF;
}
// ============================================================================
// [Alignment]
// ============================================================================
// Align variable @a x to 16-bytes.
template<typename T>
static inline T alignTo16(const T& x)
{
return (x + (T)15) & (T)~15;
}
// Return the size needed to align variable @a x to 16-bytes.
template<typename T>
static inline T deltaTo16(const T& x)
{
T aligned = alignTo16(x);
return aligned - x;
}
} // Util namespace
// ============================================================================
// [AsmJit::function_cast<>]
// ============================================================================
//! @brief Cast used to cast pointer to function. It's like reinterpret_cast<>,
//! but uses internally C style cast to work with MinGW.
//!
//! If you are using single compiler and @c reinterpret_cast<> works for you,
//! there is no reason to use @c AsmJit::function_cast<>. If you are writing
//! cross-platform software with various compiler support, consider using
//! @c AsmJit::function_cast<> instead of @c reinterpret_cast<>.
template<typename T, typename Z>
static inline T function_cast(Z* p) ASMJIT_NOTHROW { return (T)p; }
// ============================================================================
// [AsmJit::(X)MMData]
// ============================================================================
//! @brief Structure used for MMX specific data (64-bit).
//!
//! This structure can be used to load / store data from / to MMX register.
union ASMJIT_HIDDEN MMData
{
// --------------------------------------------------------------------------
// [Methods]
// --------------------------------------------------------------------------
//! @brief Set all eight signed 8-bit integers.
inline void setSB(
int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) ASMJIT_NOTHROW
{
sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7;
}
//! @brief Set all eight unsigned 8-bit integers.
inline void setUB(
uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) ASMJIT_NOTHROW
{
ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7;
}
//! @brief Set all four signed 16-bit integers.
inline void setSW(
int16_t x0, int16_t x1, int16_t x2, int16_t x3) ASMJIT_NOTHROW
{
sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3;
}
//! @brief Set all four unsigned 16-bit integers.
inline void setUW(
uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) ASMJIT_NOTHROW
{
uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3;
}
//! @brief Set all two signed 32-bit integers.
inline void setSD(
int32_t x0, int32_t x1) ASMJIT_NOTHROW
{
sd[0] = x0; sd[1] = x1;
}
//! @brief Set all two unsigned 32-bit integers.
inline void setUD(
uint32_t x0, uint32_t x1) ASMJIT_NOTHROW
{
ud[0] = x0; ud[1] = x1;
}
//! @brief Set signed 64-bit integer.
inline void setSQ(
int64_t x0) ASMJIT_NOTHROW
{
sq[0] = x0;
}
//! @brief Set unsigned 64-bit integer.
inline void setUQ(
uint64_t x0) ASMJIT_NOTHROW
{
uq[0] = x0;
}
//! @brief Set all two SP-FP values.
inline void setSF(
float x0, float x1) ASMJIT_NOTHROW
{
sf[0] = x0; sf[1] = x1;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Array of eight signed 8-bit integers.
int8_t sb[8];
//! @brief Array of eight unsigned 8-bit integers.
uint8_t ub[8];
//! @brief Array of four signed 16-bit integers.
int16_t sw[4];
//! @brief Array of four unsigned 16-bit integers.
uint16_t uw[4];
//! @brief Array of two signed 32-bit integers.
int32_t sd[2];
//! @brief Array of two unsigned 32-bit integers.
uint32_t ud[2];
//! @brief Array of one signed 64-bit integer.
int64_t sq[1];
//! @brief Array of one unsigned 64-bit integer.
uint64_t uq[1];
//! @brief Array of two SP-FP values.
float sf[2];
};
//! @brief Structure used for SSE specific data (128-bit).
//!
//! This structure can be used to load / store data from / to SSE register.
//!
//! @note Always align SSE data to 16-bytes.
union ASMJIT_HIDDEN XMMData
{
// --------------------------------------------------------------------------
// [Methods]
// --------------------------------------------------------------------------
//! @brief Set all sixteen signed 8-bit integers.
inline void setSB(
int8_t x0, int8_t x1, int8_t x2 , int8_t x3 , int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 ,
int8_t x8, int8_t x9, int8_t x10, int8_t x11, int8_t x12, int8_t x13, int8_t x14, int8_t x15) ASMJIT_NOTHROW
{
sb[0] = x0; sb[1] = x1; sb[ 2] = x2 ; sb[3 ] = x3 ; sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ;
sb[8] = x8; sb[9] = x9; sb[10] = x10; sb[11] = x11; sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15;
}
//! @brief Set all sixteen unsigned 8-bit integers.
inline void setUB(
uint8_t x0, uint8_t x1, uint8_t x2 , uint8_t x3 , uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 ,
uint8_t x8, uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) ASMJIT_NOTHROW
{
ub[0] = x0; ub[1] = x1; ub[ 2] = x2 ; ub[3 ] = x3 ; ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ;
ub[8] = x8; ub[9] = x9; ub[10] = x10; ub[11] = x11; ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15;
}
//! @brief Set all eight signed 16-bit integers.
inline void setSW(
int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) ASMJIT_NOTHROW
{
sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7;
}
//! @brief Set all eight unsigned 16-bit integers.
inline void setUW(
uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) ASMJIT_NOTHROW
{
uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7;
}
//! @brief Set all four signed 32-bit integers.
inline void setSD(
int32_t x0, int32_t x1, int32_t x2, int32_t x3) ASMJIT_NOTHROW
{
sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3;
}
//! @brief Set all four unsigned 32-bit integers.
inline void setUD(
uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) ASMJIT_NOTHROW
{
ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3;
}
//! @brief Set all two signed 64-bit integers.
inline void setSQ(
int64_t x0, int64_t x1) ASMJIT_NOTHROW
{
sq[0] = x0; sq[1] = x1;
}
//! @brief Set all two unsigned 64-bit integers.
inline void setUQ(
uint64_t x0, uint64_t x1) ASMJIT_NOTHROW
{
uq[0] = x0; uq[1] = x1;
}
//! @brief Set all four SP-FP floats.
inline void setSF(
float x0, float x1, float x2, float x3) ASMJIT_NOTHROW
{
sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3;
}
//! @brief Set all two DP-FP floats.
inline void setDF(
double x0, double x1) ASMJIT_NOTHROW
{
df[0] = x0; df[1] = x1;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Array of sixteen signed 8-bit integers.
int8_t sb[16];
//! @brief Array of sixteen unsigned 8-bit integers.
uint8_t ub[16];
//! @brief Array of eight signed 16-bit integers.
int16_t sw[8];
//! @brief Array of eight unsigned 16-bit integers.
uint16_t uw[8];
//! @brief Array of four signed 32-bit integers.
int32_t sd[4];
//! @brief Array of four unsigned 32-bit integers.
uint32_t ud[4];
//! @brief Array of two signed 64-bit integers.
int64_t sq[2];
//! @brief Array of two unsigned 64-bit integers.
uint64_t uq[2];
//! @brief Array of four 32-bit single precision floating points.
float sf[4];
//! @brief Array of two 64-bit double precision floating points.
double df[2];
};
// ============================================================================
// [AsmJit::Buffer]
// ============================================================================
//! @brief Buffer used to store instruction stream in AsmJit.
//!
//! This class can be dangerous, if you don't know how it works. Assembler
//! instruction stream is usually constructed by multiple calls of emit
//! functions that emits bytes, words, dwords or qwords. But to decrease
//! AsmJit library size and improve performance, we are not checking for
//! buffer overflow for each emit operation, but only once in highler level
//! emit instruction.
//!
//! So, if you want to use this class, you need to do buffer checking yourself
//! by using @c ensureSpace() method. It's designed to grow buffer if needed.
//! Threshold for growing is named @c growThreshold() and it means count of
//! bytes for emitting single operation. Default size is set to 16 bytes,
//! because x86 and x64 instruction can't be larger (so it's space to hold 1
//! instruction).
//!
//! Example using Buffer:
//!
//! @code
//! // Buffer instance, growThreshold == 16
//! // (no memory allocated in constructor).
//! AsmJit::Buffer buf(16);
//!
//! // Begin of emit stream, ensure space can fail on out of memory error.
//! if (buf.ensureSpace())
//! {
//! // here, you can emit up to 16 (growThreshold) bytes
//! buf.emitByte(0x00);
//! buf.emitByte(0x01);
//! buf.emitByte(0x02);
//! buf.emitByte(0x03);
//! ...
//! }
//! @endcode
struct ASMJIT_API Buffer
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
inline Buffer(sysint_t growThreshold = 16) ASMJIT_NOTHROW :
_data(NULL),
_cur(NULL),
_max(NULL),
_capacity(0),
_growThreshold(growThreshold)
{
}
inline ~Buffer() ASMJIT_NOTHROW
{
if (_data) ASMJIT_FREE(_data);
}
//! @brief Get start of buffer.
inline uint8_t* getData() const ASMJIT_NOTHROW { return _data; }
//! @brief Get current pointer in code buffer.
inline uint8_t* getCur() const ASMJIT_NOTHROW { return _cur; }
//! @brief Get maximum pointer in code buffer for growing.
inline uint8_t* getMax() const ASMJIT_NOTHROW { return _max; }
//! @brief Get current offset in buffer.
inline sysint_t getOffset() const ASMJIT_NOTHROW { return (sysint_t)(_cur - _data); }
//! @brief Get capacity of buffer.
inline sysint_t getCapacity() const ASMJIT_NOTHROW { return _capacity; }
//! @brief Get grow threshold.
inline sysint_t getGrowThreshold() const ASMJIT_NOTHROW { return _growThreshold; }
//! @brief Ensure space for next instruction
inline bool ensureSpace() ASMJIT_NOTHROW { return (_cur >= _max) ? grow() : true; }
//! @brief Sets offset to @a o and returns previous offset.
//!
//! This method can be used to truncate buffer or it's used to
//! overwrite specific position in buffer by Assembler.
inline sysint_t toOffset(sysint_t o) ASMJIT_NOTHROW
{
ASMJIT_ASSERT(o < _capacity);
sysint_t prev = (sysint_t)(_cur - _data);
_cur = _data + o;
return prev;
}
//! @brief Reallocate buffer.
//!
//! It's only used for growing, buffer is never reallocated to smaller
//! number than current capacity() is.
bool realloc(sysint_t to) ASMJIT_NOTHROW;
//! @brief Used to grow the buffer.
//!
//! It will typically realloc to twice size of capacity(), but if capacity()
//! is large, it will use smaller steps.
bool grow() ASMJIT_NOTHROW;
//! @brief Clear everything, but not deallocate buffer.
void clear() ASMJIT_NOTHROW;
//! @brief Free buffer and NULL all pointers.
void free() ASMJIT_NOTHROW;
//! @brief Take ownership of the buffer data and purge @c Buffer instance.
uint8_t* take() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Emit]
// --------------------------------------------------------------------------
//! @brief Emit Byte.
inline void emitByte(uint8_t x) ASMJIT_NOTHROW
{
*_cur++ = x;
}
//! @brief Emit Word (2 bytes).
inline void emitWord(uint16_t x) ASMJIT_NOTHROW
{
*(uint16_t *)_cur = x;
_cur += 2;
}
//! @brief Emit DWord (4 bytes).
inline void emitDWord(uint32_t x) ASMJIT_NOTHROW
{
*(uint32_t *)_cur = x;
_cur += 4;
}
//! @brief Emit QWord (8 bytes).
inline void emitQWord(uint64_t x) ASMJIT_NOTHROW
{
*(uint64_t *)_cur = x;
_cur += 8;
}
//! @brief Emit system signed integer (4 or 8 bytes).
inline void emitSysInt(sysint_t x) ASMJIT_NOTHROW
{
*(sysint_t *)_cur = x;
_cur += sizeof(sysint_t);
}
//! @brief Emit system unsigned integer (4 or 8 bytes).
inline void emitSysUInt(sysuint_t x) ASMJIT_NOTHROW
{
*(sysuint_t *)_cur = x;
_cur += sizeof(sysuint_t);
}
//! @brief Emit custom data.
void emitData(const void* ptr, sysuint_t len) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Get / Set]
// --------------------------------------------------------------------------
//! @brief Set byte at position @a pos.
inline uint8_t getByteAt(sysint_t pos) const ASMJIT_NOTHROW
{
return *reinterpret_cast<const uint8_t*>(_data + pos);
}
//! @brief Set word at position @a pos.
inline uint16_t getWordAt(sysint_t pos) const ASMJIT_NOTHROW
{
return *reinterpret_cast<const uint16_t*>(_data + pos);
}
//! @brief Set word at position @a pos.
inline uint32_t getDWordAt(sysint_t pos) const ASMJIT_NOTHROW
{
return *reinterpret_cast<const uint32_t*>(_data + pos);
}
//! @brief Set word at position @a pos.
inline uint64_t getQWordAt(sysint_t pos) const ASMJIT_NOTHROW
{
return *reinterpret_cast<const uint64_t*>(_data + pos);
}
//! @brief Set byte at position @a pos.
inline void setByteAt(sysint_t pos, uint8_t x) ASMJIT_NOTHROW
{
*reinterpret_cast<uint8_t*>(_data + pos) = x;
}
//! @brief Set word at position @a pos.
inline void setWordAt(sysint_t pos, uint16_t x) ASMJIT_NOTHROW
{
*reinterpret_cast<uint16_t*>(_data + pos) = x;
}
//! @brief Set word at position @a pos.
inline void setDWordAt(sysint_t pos, uint32_t x) ASMJIT_NOTHROW
{
*reinterpret_cast<uint32_t*>(_data + pos) = x;
}
//! @brief Set word at position @a pos.
inline void setQWordAt(sysint_t pos, uint64_t x) ASMJIT_NOTHROW
{
*reinterpret_cast<uint64_t*>(_data + pos) = x;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
// All members are public, because they can be accessed and modified by
// Assembler/Compiler directly.
//! @brief Beginning position of buffer.
uint8_t* _data;
//! @brief Current position in buffer.
uint8_t* _cur;
//! @brief Maximum position in buffer for realloc.
uint8_t* _max;
//! @brief Buffer capacity (in bytes).
sysint_t _capacity;
//! @brief Grow threshold
sysint_t _growThreshold;
};
// ============================================================================
// [AsmJit::PodVector<>]
// ============================================================================
//! @brief Template used to store and manage array of POD data.
//!
//! This template has these adventages over other vector<> templates:
//! - Non-copyable (designed to be non-copyable, we want it)
//! - No copy-on-write (some implementations of stl can use it)
//! - Optimized for working only with POD types
//! - Uses ASMJIT_... memory management macros
template <typename T>
struct PodVector
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create new instance of PodVector template. Data will not
//! be allocated (will be NULL).
inline PodVector() ASMJIT_NOTHROW : _data(NULL), _length(0), _capacity(0)
{
}
//! @brief Destroy PodVector and free all data.
inline ~PodVector() ASMJIT_NOTHROW
{
if (_data) ASMJIT_FREE(_data);
}
// --------------------------------------------------------------------------
// [Data]
// --------------------------------------------------------------------------
//! @brief Get vector data.
inline T* getData() ASMJIT_NOTHROW { return _data; }
//! @overload
inline const T* getData() const ASMJIT_NOTHROW { return _data; }
//! @brief Get vector length.
inline sysuint_t getLength() const ASMJIT_NOTHROW { return _length; }
//! @brief get vector capacity (allocation capacity).
inline sysuint_t getCapacity() const ASMJIT_NOTHROW { return _capacity; }
// --------------------------------------------------------------------------
// [Manipulation]
// --------------------------------------------------------------------------
//! @brief Clear vector data, but not free internal buffer.
void clear() ASMJIT_NOTHROW
{
_length = 0;
}
//! @brief Clear vector data and free internal buffer.
void free() ASMJIT_NOTHROW
{
if (_data)
{
ASMJIT_FREE(_data);
_data = 0;
_length = 0;
_capacity = 0;
}
}
//! @brief Prepend @a item to vector.
bool prepend(const T& item) ASMJIT_NOTHROW
{
if (_length == _capacity && !_grow()) return false;
memmove(_data + 1, _data, sizeof(T) * _length);
memcpy(_data, &item, sizeof(T));
_length++;
return true;
}
//! @brief Insert an @a item at the @a index.
bool insert(sysuint_t index, const T& item) ASMJIT_NOTHROW
{
ASMJIT_ASSERT(index <= _length);
if (_length == _capacity && !_grow()) return false;
T* dst = _data + index;
memmove(dst + 1, dst, _length - index);
memcpy(dst, &item, sizeof(T));
_length++;
return true;
}
//! @brief Append @a item to vector.
bool append(const T& item) ASMJIT_NOTHROW
{
if (_length == _capacity && !_grow()) return false;
memcpy(_data + _length, &item, sizeof(T));
_length++;
return true;
}
//! @brief Get index of @a val or (sysuint_t)-1 if not found.
sysuint_t indexOf(const T& val) const ASMJIT_NOTHROW
{
sysuint_t i = 0, len = _length;
for (i = 0; i < len; i++) { if (_data[i] == val) return i; }
return (sysuint_t)-1;
}
//! @brief Remove element at index @a i.
void removeAt(sysuint_t i) ASMJIT_NOTHROW
{
ASMJIT_ASSERT(i < _length);
T* dst = _data + i;
_length--;
memmove(dst, dst + 1, _length - i);
}
//! @brief Swap this pod-vector with @a other.
void swap(PodVector<T>& other) ASMJIT_NOTHROW
{
T* _tmp_data = _data;
sysuint_t _tmp_length = _length;
sysuint_t _tmp_capacity = _capacity;
_data = other._data;
_length = other._length;
_capacity = other._capacity;
other._data = _tmp_data;
other._length = _tmp_length;
other._capacity = _tmp_capacity;
}
//! @brief Get item at position @a i.
inline T& operator[](sysuint_t i) ASMJIT_NOTHROW
{
ASMJIT_ASSERT(i < _length);
return _data[i];
}
//! @brief Get item at position @a i.
inline const T& operator[](sysuint_t i) const ASMJIT_NOTHROW
{
ASMJIT_ASSERT(i < _length);
return _data[i];
}
//! @brief Append the item and return address so it can be initialized.
T* newItem() ASMJIT_NOTHROW
{
if (_length == _capacity && !_grow()) return NULL;
return _data + (_length++);
}
// --------------------------------------------------------------------------
// [Private]
// --------------------------------------------------------------------------
private:
//! @brief Called to grow internal array.
bool _grow() ASMJIT_NOTHROW
{
return _realloc(_capacity < 16 ? 16 : _capacity * 2);
}
//! @brief Realloc internal array to fit @a to items.
bool _realloc(sysuint_t to) ASMJIT_NOTHROW
{
ASMJIT_ASSERT(to >= _length);
T* p = reinterpret_cast<T*>(_data
? ASMJIT_REALLOC(_data, to * sizeof(T))
: ASMJIT_MALLOC(to * sizeof(T)));
if (!p) return false;
_data = p;
_capacity = to;
return true;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Items data.
T* _data;
//! @brief Length of buffer (count of items in array).
sysuint_t _length;
//! @brief Capacity of buffer (maximum items that can fit to current array).
sysuint_t _capacity;
private:
ASMJIT_DISABLE_COPY(PodVector<T>)
};
// ============================================================================
// [AsmJit::Zone]
// ============================================================================
//! @brief Memory allocator designed to fast alloc memory that will be freed
//! in one step.
//!
//! @note This is hackery for performance. Concept is that objects created
//! by @c Zone are freed all at once. This means that lifetime of
//! these objects are same as zone object itselt.
//!
//! All emittables, variables, labels and states allocated by @c Compiler are
//! allocated through @c Zone object.
struct ASMJIT_API Zone
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create new instance of @c Zone.
//! @param chunkSize Default size for one zone chunk.
Zone(sysuint_t chunkSize) ASMJIT_NOTHROW;
//! @brief Destroy zone instance.
~Zone() ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Methods]
// --------------------------------------------------------------------------
//! @brief Allocate @c size bytes of memory and return pointer to it.
//!
//! Pointer allocated by this way will be valid until @c Zone object is
//! destroyed. To create class by this way use placement @c new and
//! @c delete operators:
//!
//! @code
//! // Example of allocating simple class
//!
//! // Your class
//! class Object
//! {
//! // members...
//! };
//!
//! // Your function
//! void f()
//! {
//! // We are using AsmJit namespace
//! using namespace AsmJit
//!
//! // Create zone object with chunk size of 65536 bytes.
//! Zone zone(65536);
//!
//! // Create your objects using zone object allocating, for example:
//! Object* obj = new(zone.alloc(sizeof(YourClass))) Object();
//!
//! // ... lifetime of your objects ...
//!
//! // Destroy your objects:
//! obj->~Object();
//!
//! // Zone destructor will free all memory allocated through it,
//! // alternative is to call @c zone.freeAll().
//! }
//! @endcode
void* zalloc(sysuint_t size) ASMJIT_NOTHROW;
//! @brief Helper to duplicate string.
char* zstrdup(const char* str) ASMJIT_NOTHROW;
//! @brief Free all allocated memory except first block that remains for reuse.
//!
//! Note that this method will invalidate all instances using this memory
//! allocated by this zone instance.
void clear() ASMJIT_NOTHROW;
//! @brief Free all allocated memory at once.
//!
//! Note that this method will invalidate all instances using this memory
//! allocated by this zone instance.
void freeAll() ASMJIT_NOTHROW;
//! @brief Get total size of allocated objects - by @c alloc().
inline sysuint_t getTotal() const ASMJIT_NOTHROW { return _total; }
//! @brief Get (default) chunk size.
inline sysuint_t getChunkSize() const ASMJIT_NOTHROW { return _chunkSize; }
// --------------------------------------------------------------------------
// [Chunk]
// --------------------------------------------------------------------------
//! @internal
//!
//! @brief One allocated chunk of memory.
struct ASMJIT_HIDDEN Chunk
{
//! @brief Link to previous chunk.
Chunk* prev;
//! @brief Position in this chunk.
sysuint_t pos;
//! @brief Size of this chunk (in bytes).
sysuint_t size;
//! @brief Data.
uint8_t data[sizeof(void*)];
//! @brief Get count of remaining (unused) bytes in chunk.
inline sysuint_t getRemainingBytes() const ASMJIT_NOTHROW { return size - pos; }
};
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
private:
//! @brief Last allocated chunk of memory.
Chunk* _chunks;
//! @brief Total size of allocated objects - by @c alloc() method.
sysuint_t _total;
//! @brief One chunk size.
sysuint_t _chunkSize;
};
//! @}
} // AsmJit namespace
#endif // _ASMJIT_UTIL_H

View File

@ -0,0 +1,111 @@
// [AsmJit]
// Complete JIT Assembler for C++ Language.
//
// [License]
// Zlib - See COPYING file in this package.
// [Guard]
#ifndef _ASMJIT_UTIL_P_H
#define _ASMJIT_UTIL_P_H
// [Dependencies]
#include "Util.h"
#include <stdlib.h>
#include <string.h>
namespace AsmJit {
//! @addtogroup AsmJit_Util
//! @{
// ============================================================================
// [AsmJit::Util]
// ============================================================================
namespace Util
{
// --------------------------------------------------------------------------
// [AsmJit::floatAsInt32, int32AsFloat]
// --------------------------------------------------------------------------
//! @internal
//!
//! @brief used to cast from float to 32-bit integer and vica versa.
union I32FPUnion
{
//! @brief 32-bit signed integer value.
int32_t i;
//! @brief 32-bit SP-FP value.
float f;
};
//! @internal
//!
//! @brief used to cast from double to 64-bit integer and vica versa.
union I64FPUnion
{
//! @brief 64-bit signed integer value.
int64_t i;
//! @brief 64-bit DP-FP value.
double f;
};
//! @brief Binary cast from 32-bit integer to SP-FP value (@c float).
static inline float int32AsFloat(int32_t i) ASMJIT_NOTHROW
{
I32FPUnion u;
u.i = i;
return u.f;
}
//! @brief Binary cast SP-FP value (@c float) to 32-bit integer.
static inline int32_t floatAsInt32(float f) ASMJIT_NOTHROW
{
I32FPUnion u;
u.f = f;
return u.i;
}
//! @brief Binary cast from 64-bit integer to DP-FP value (@c double).
static inline double int64AsDouble(int64_t i) ASMJIT_NOTHROW
{
I64FPUnion u;
u.i = i;
return u.f;
}
//! @brief Binary cast from DP-FP value (@c double) to 64-bit integer.
static inline int64_t doubleAsInt64(double f) ASMJIT_NOTHROW
{
I64FPUnion u;
u.f = f;
return u.i;
}
// --------------------------------------------------------------------------
// [Str Utils]
// --------------------------------------------------------------------------
ASMJIT_HIDDEN char* mycpy(char* dst, const char* src, sysuint_t len = (sysuint_t)-1) ASMJIT_NOTHROW;
ASMJIT_HIDDEN char* myfill(char* dst, const int c, sysuint_t len) ASMJIT_NOTHROW;
ASMJIT_HIDDEN char* myhex(char* dst, const uint8_t* src, sysuint_t len) ASMJIT_NOTHROW;
ASMJIT_HIDDEN char* myutoa(char* dst, sysuint_t i, sysuint_t base = 10) ASMJIT_NOTHROW;
ASMJIT_HIDDEN char* myitoa(char* dst, sysint_t i, sysuint_t base = 10) ASMJIT_NOTHROW;
// --------------------------------------------------------------------------
// [Mem Utils]
// --------------------------------------------------------------------------
static inline void memset32(uint32_t* p, uint32_t c, sysuint_t len) ASMJIT_NOTHROW
{
sysuint_t i;
for (i = 0; i < len; i++) p[i] = c;
}
} // Util namespace
//! @}
} // AsmJit namespace
#endif // _ASMJIT_UTIL_P_H

View File

@ -81,8 +81,14 @@
#define DESMUME_COMPILER_DETAIL ""
#endif
#ifdef HAVE_JIT
#define DESMUME_FEATURE_CPU " (JIT)"
#else
#define DESMUME_FEATURE_CPU ""
#endif
#define DESMUME_VERSION_NUMERIC 90900
#define DESMUME_VERSION_STRING " " "0.9.9" DESMUME_SUBVERSION_STRING DESMUME_FEATURE_STRING DESMUME_PLATFORM_STRING DESMUME_CPUEXT_STRING DESMUME_COMPILER
#define DESMUME_VERSION_STRING " " "0.9.9" DESMUME_SUBVERSION_STRING DESMUME_FEATURE_CPU DESMUME_FEATURE_STRING DESMUME_PLATFORM_STRING DESMUME_CPUEXT_STRING DESMUME_COMPILER
#define DESMUME_NAME_AND_VERSION DESMUME_NAME DESMUME_VERSION_STRING
u32 EMU_DESMUME_VERSION_NUMERIC() { return DESMUME_VERSION_NUMERIC; }

View File

@ -1643,6 +1643,146 @@
>
</File>
</Filter>
<Filter
Name="AsmJit"
>
<File
RelativePath="..\utils\AsmJit\ApiBegin.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\ApiEnd.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\AsmJit.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Assembler.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\AssemblerX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\AssemblerX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Build.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\CodeGenerator.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\CodeGenerator.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Compiler.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Compiler.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\CompilerX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\CompilerX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Config.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\CpuInfo.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\CpuInfo.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Defs.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Defs.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\DefsX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\DefsX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Logger.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Logger.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryManager.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryManager.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryMarker.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryMarker.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Operand.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\OperandX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\OperandX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Platform.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Platform.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Util.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Util.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Util_p.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="addons"
@ -1928,6 +2068,14 @@
RelativePath="..\arm_instructions.h"
>
</File>
<File
RelativePath="..\arm_jit.cpp"
>
</File>
<File
RelativePath="..\arm_jit.h"
>
</File>
<File
RelativePath="..\armcpu.cpp"
>
@ -2120,6 +2268,10 @@
RelativePath="..\GPU_osd.h"
>
</File>
<File
RelativePath="..\instruction_attributes.h"
>
</File>
<File
RelativePath="..\instruction_tabdef.inc"
>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="DeSmuME_VS2008"
ProjectGUID="{9F5F72A1-D3A5-4918-B460-E076B16D10A9}"
RootNamespace="DeSmuME"
@ -607,7 +607,11 @@
>
</File>
<File
RelativePath="..\arm_instructions.h"
RelativePath="..\arm_jit.cpp"
>
</File>
<File
RelativePath="..\arm_jit.h"
>
</File>
<File
@ -778,10 +782,18 @@
RelativePath="..\GPU_osd.h"
>
</File>
<File
RelativePath="..\instruction_attributes.h"
>
</File>
<File
RelativePath="..\instruction_tabdef.inc"
>
</File>
<File
RelativePath="..\instructions.h"
>
</File>
<File
RelativePath="..\lua-engine.cpp"
>
@ -942,10 +954,6 @@
RelativePath="..\thumb_instructions.cpp"
>
</File>
<File
RelativePath="..\thumb_instructions.h"
>
</File>
<File
RelativePath="..\thumb_tabdef.inc"
>
@ -1277,6 +1285,154 @@
>
</File>
</Filter>
<Filter
Name="AsmJit"
>
<File
RelativePath="..\utils\AsmJit\ApiBegin.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\ApiEnd.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\AsmJit.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Assembler.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\AssemblerX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\AssemblerX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Build.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\CodeGenerator.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\CodeGenerator.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Compiler.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Compiler.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\CompilerX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\CompilerX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Config.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\COPYING.txt"
>
</File>
<File
RelativePath="..\utils\AsmJit\CpuInfo.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\CpuInfo.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Defs.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Defs.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\DefsX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\DefsX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Logger.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Logger.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryManager.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryManager.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryMarker.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\MemoryMarker.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Operand.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\OperandX86X64.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\OperandX86X64.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Platform.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Platform.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\README.txt"
>
</File>
<File
RelativePath="..\utils\AsmJit\Util.cpp"
>
</File>
<File
RelativePath="..\utils\AsmJit\Util.h"
>
</File>
<File
RelativePath="..\utils\AsmJit\Util_p.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="metaspu"

View File

@ -181,6 +181,7 @@
<CallingConvention>Cdecl</CallingConvention>
<CompileAs>Default</CompileAs>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>directx-win32-ddraw-dinput8-dsound-dxerr8-dxguid.lib;lua51.lib;glib-vc8-Win32.lib;7z-vc8-Win32.lib;zlib-vc8-Win32.lib;agg-2.5.lib;vfw32.lib;winmm.lib;opengl32.lib;glu32.lib;ws2_32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;shlwapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -271,6 +272,7 @@
<FunctionLevelLinking>false</FunctionLevelLinking>
<FloatingPointExceptions>false</FloatingPointExceptions>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>directx-win32-ddraw-dinput8-dsound-dxerr8-dxguid.lib;lua51.lib;glib-vc8-Win32.lib;7z-vc8-Win32.lib;zlib-vc8-Win32.lib;agg-2.5.lib;vfw32.lib;winmm.lib;opengl32.lib;glu32.lib;ws2_32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;shlwapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -315,6 +317,7 @@
<CallingConvention>Cdecl</CallingConvention>
<CompileAs>Default</CompileAs>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>directx-x64-ddraw-dinput8-dsound-dxerr8-dxguid.lib;lua51.lib;glib-vc8-x64.lib;7z-vc8-x64.lib;zlib-vc8-x64.lib;agg-2.5-x64.lib;vfw32.lib;winmm.lib;opengl32.lib;glu32.lib;ws2_32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -360,6 +363,7 @@
<CallingConvention>Cdecl</CallingConvention>
<CompileAs>Default</CompileAs>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>directx-x64-ddraw-dinput8-dsound-dxerr8-dxguid.lib;lua51.lib;glib-vc8-x64.lib;7z-vc8-x64.lib;zlib-vc8-x64.lib;agg-2.5-x64.lib;vfw32.lib;winmm.lib;opengl32.lib;glu32.lib;ws2_32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -406,6 +410,7 @@
<CallingConvention>Cdecl</CallingConvention>
<CompileAs>Default</CompileAs>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>directx-x64-ddraw-dinput8-dsound-dxerr8-dxguid.lib;lua51.lib;glib-vc8-x64.lib;7z-vc8-x64.lib;zlib-vc8-x64.lib;agg-2.5-x64.lib;vfw32.lib;winmm.lib;opengl32.lib;glu32.lib;ws2_32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -438,6 +443,7 @@
<ClCompile Include="..\aggdraw.cpp" />
<ClCompile Include="..\arm_instructions.cpp" />
<ClCompile Include="..\armcpu.cpp" />
<ClCompile Include="..\arm_jit.cpp" />
<ClCompile Include="..\bios.cpp" />
<ClCompile Include="..\cheatSystem.cpp" />
<ClCompile Include="..\commandline.cpp">
@ -482,6 +488,19 @@
<ClCompile Include="..\SPU.cpp" />
<ClCompile Include="..\texcache.cpp" />
<ClCompile Include="..\thumb_instructions.cpp" />
<ClCompile Include="..\utils\AsmJit\AssemblerX86X64.cpp" />
<ClCompile Include="..\utils\AsmJit\CodeGenerator.cpp" />
<ClCompile Include="..\utils\AsmJit\Compiler.cpp" />
<ClCompile Include="..\utils\AsmJit\CompilerX86X64.cpp" />
<ClCompile Include="..\utils\AsmJit\CpuInfo.cpp" />
<ClCompile Include="..\utils\AsmJit\Defs.cpp" />
<ClCompile Include="..\utils\AsmJit\DefsX86X64.cpp" />
<ClCompile Include="..\utils\AsmJit\Logger.cpp" />
<ClCompile Include="..\utils\AsmJit\MemoryManager.cpp" />
<ClCompile Include="..\utils\AsmJit\MemoryMarker.cpp" />
<ClCompile Include="..\utils\AsmJit\OperandX86X64.cpp" />
<ClCompile Include="..\utils\AsmJit\Platform.cpp" />
<ClCompile Include="..\utils\AsmJit\Util.cpp" />
<ClCompile Include="..\utils\datetime.cpp" />
<ClCompile Include="..\utils\dlditool.cpp" />
<ClCompile Include="..\utils\emufat.cpp" />
@ -573,8 +592,8 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\addons.h" />
<ClInclude Include="..\arm_instructions.h" />
<ClInclude Include="..\armcpu.h" />
<ClInclude Include="..\arm_jit.h" />
<ClInclude Include="..\bios.h" />
<ClInclude Include="..\bits.h" />
<ClInclude Include="..\cheatSystem.h" />
@ -598,6 +617,8 @@
<ClInclude Include="..\gfx3d.h" />
<ClInclude Include="..\GPU.h" />
<ClInclude Include="..\GPU_osd.h" />
<ClInclude Include="..\instructions.h" />
<ClInclude Include="..\instruction_attributes.h" />
<ClInclude Include="..\lua-engine.h" />
<ClInclude Include="..\matrix.h" />
<ClInclude Include="..\mc.h" />
@ -620,8 +641,28 @@
<ClInclude Include="..\slot1.h" />
<ClInclude Include="..\SPU.h" />
<ClInclude Include="..\texcache.h" />
<ClInclude Include="..\thumb_instructions.h" />
<ClInclude Include="..\types.h" />
<ClInclude Include="..\utils\AsmJit\ApiBegin.h" />
<ClInclude Include="..\utils\AsmJit\ApiEnd.h" />
<ClInclude Include="..\utils\AsmJit\AsmJit.h" />
<ClInclude Include="..\utils\AsmJit\Assembler.h" />
<ClInclude Include="..\utils\AsmJit\AssemblerX86X64.h" />
<ClInclude Include="..\utils\AsmJit\Build.h" />
<ClInclude Include="..\utils\AsmJit\CodeGenerator.h" />
<ClInclude Include="..\utils\AsmJit\Compiler.h" />
<ClInclude Include="..\utils\AsmJit\CompilerX86X64.h" />
<ClInclude Include="..\utils\AsmJit\Config.h" />
<ClInclude Include="..\utils\AsmJit\CpuInfo.h" />
<ClInclude Include="..\utils\AsmJit\Defs.h" />
<ClInclude Include="..\utils\AsmJit\DefsX86X64.h" />
<ClInclude Include="..\utils\AsmJit\Logger.h" />
<ClInclude Include="..\utils\AsmJit\MemoryManager.h" />
<ClInclude Include="..\utils\AsmJit\MemoryMarker.h" />
<ClInclude Include="..\utils\AsmJit\Operand.h" />
<ClInclude Include="..\utils\AsmJit\OperandX86X64.h" />
<ClInclude Include="..\utils\AsmJit\Platform.h" />
<ClInclude Include="..\utils\AsmJit\Util.h" />
<ClInclude Include="..\utils\AsmJit\Util_p.h" />
<ClInclude Include="..\utils\datetime.h" />
<ClInclude Include="..\utils\emufat.h" />
<ClInclude Include="..\utils\emufat_types.h" />
@ -717,6 +758,8 @@
<None Include="..\filter\hq4x.dat" />
<None Include="..\instruction_tabdef.inc" />
<None Include="..\thumb_tabdef.inc" />
<None Include="..\utils\AsmJit\COPYING.txt" />
<None Include="..\utils\AsmJit\README.txt" />
<None Include="bitmap1.bmp" />
<None Include="DeSmuME.ico" />
<CustomBuild Include="7z\7z.7z">

View File

@ -52,6 +52,9 @@
<Filter Include="Core\filter">
<UniqueIdentifier>{0c7156df-b4ef-4cd2-af76-6a6c1e66145a}</UniqueIdentifier>
</Filter>
<Filter Include="Core\utils\AsmJit">
<UniqueIdentifier>{faa7804e-deb3-482f-b348-921cb7dacca7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\addons.cpp">
@ -471,14 +474,53 @@
<ClCompile Include="importSave.cpp">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\AssemblerX86X64.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\CodeGenerator.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\Compiler.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\CompilerX86X64.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\CpuInfo.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\Defs.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\DefsX86X64.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\Logger.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\MemoryManager.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\MemoryMarker.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\OperandX86X64.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\Platform.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\utils\AsmJit\Util.cpp">
<Filter>Core\utils\AsmJit</Filter>
</ClCompile>
<ClCompile Include="..\arm_jit.cpp">
<Filter>Core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\addons.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\arm_instructions.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\armcpu.h">
<Filter>Core</Filter>
</ClInclude>
@ -599,9 +641,6 @@
<ClInclude Include="..\texcache.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\thumb_instructions.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\types.h">
<Filter>Core</Filter>
</ClInclude>
@ -885,6 +924,78 @@
<ClInclude Include="importSave.h">
<Filter>Windows</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\ApiBegin.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\ApiEnd.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\AsmJit.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Assembler.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\AssemblerX86X64.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Build.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\CodeGenerator.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Compiler.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\CompilerX86X64.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Config.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\CpuInfo.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Defs.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\DefsX86X64.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Logger.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\MemoryManager.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\MemoryMarker.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Operand.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\OperandX86X64.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Platform.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Util.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\utils\AsmJit\Util_p.h">
<Filter>Core\utils\AsmJit</Filter>
</ClInclude>
<ClInclude Include="..\arm_jit.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\instruction_attributes.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\instructions.h">
<Filter>Core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\instruction_tabdef.inc">
@ -902,6 +1013,12 @@
<None Include="..\filter\hq4x.dat">
<Filter>Core\filter</Filter>
</None>
<None Include="..\utils\AsmJit\COPYING.txt">
<Filter>Core\utils\AsmJit</Filter>
</None>
<None Include="..\utils\AsmJit\README.txt">
<Filter>Core\utils\AsmJit</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resources.rc">

View File

@ -93,6 +93,20 @@ void HK_ReloadROM(int, bool justPressed)
void OpenRecentROM(int listNum);
OpenRecentROM(0);
}
void HK_CpuMode(int, bool justPressed)
{
extern void arm_jit_sync();
void arm_jit_reset(bool enable);
arm_jit_sync();
CommonSettings.use_jit = !CommonSettings.use_jit;
arm_jit_reset(CommonSettings.use_jit);
char tmp[256];
sprintf(tmp,"CPU mode: %s", CommonSettings.use_jit?"JIT":"Interpreter");
osd->addLine(tmp);
//WritePrivateProfileInt("Emulation", "CpuMode", CommonSettings.use_jit, IniName)
}
void HK_SearchCheats(int, bool justPressed)
{
if (romloaded)
@ -456,8 +470,6 @@ void HK_Rotate90(int, bool justPressed) { SetRotate(MainWindow->getHWnd(), 90);}
void HK_Rotate180(int, bool justPressed) { SetRotate(MainWindow->getHWnd(), 180);}
void HK_Rotate270(int, bool justPressed) { SetRotate(MainWindow->getHWnd(), 270);}
//======================================================================================
//=====================================DEFINITIONS======================================
//======================================================================================
@ -509,6 +521,12 @@ void InitCustomKeys (SCustomKeys *keys)
keys->Pause.page = HOTKEY_PAGE_MAIN;
keys->Pause.key = VK_PAUSE;
keys->CpuMode.handleKeyDown = HK_CpuMode;
keys->CpuMode.code = "CpuMode";
keys->CpuMode.name = STRW(ID_LABEL_HK3b);
keys->CpuMode.page = HOTKEY_PAGE_MAIN;
keys->CpuMode.key = VK_SCROLL;
keys->FrameAdvance.handleKeyDown = HK_FrameAdvanceKeyDown;
keys->FrameAdvance.handleKeyUp = HK_FrameAdvanceKeyUp;
keys->FrameAdvance.code = "FrameAdvance";
@ -578,7 +596,7 @@ void InitCustomKeys (SCustomKeys *keys)
keys->StylusAutoHold.handleKeyDown = HK_StylusAutoHoldKeyDown;
keys->StylusAutoHold.code = "StylusAutoHold";
keys->StylusAutoHold.name = STRW(ID_LABEL_HK29);
keys->StylusAutoHold.page = HOTKEY_PAGE_MOVIE; // TODO: set more appropriate category?
keys->StylusAutoHold.page = HOTKEY_PAGE_TOOLS; // TODO: set more appropriate category?
keys->StylusAutoHold.key = NULL;
keys->AutoHoldClear.handleKeyDown = HK_AutoHoldClearKeyDown;
@ -596,13 +614,13 @@ void InitCustomKeys (SCustomKeys *keys)
keys->PrintScreen.handleKeyDown = HK_PrintScreen;
keys->PrintScreen.code = "SaveScreenshotas";
keys->PrintScreen.name = STRW(ID_LABEL_HK13);
keys->PrintScreen.page = HOTKEY_PAGE_MAIN;
keys->PrintScreen.page = HOTKEY_PAGE_TOOLS;
keys->PrintScreen.key = VK_F12;
keys->QuickPrintScreen.handleKeyDown = HK_QuickScreenShot;
keys->QuickPrintScreen.code = "QuickScreenshot";
keys->QuickPrintScreen.name = STRW(ID_LABEL_HK13b);
keys->QuickPrintScreen.page = HOTKEY_PAGE_MAIN;
keys->QuickPrintScreen.page = HOTKEY_PAGE_TOOLS;
keys->QuickPrintScreen.key = VK_F12;
keys->QuickPrintScreen.modifiers = CUSTKEY_CTRL_MASK;
@ -633,13 +651,13 @@ void InitCustomKeys (SCustomKeys *keys)
keys->RecordWAV.handleKeyDown = HK_RecordWAV;
keys->RecordWAV.code = "RecordWAV";
keys->RecordWAV.name = STRW(ID_LABEL_HK14);
keys->RecordWAV.page = HOTKEY_PAGE_MAIN;
keys->RecordWAV.page = HOTKEY_PAGE_MOVIE;
keys->RecordWAV.key = NULL;
keys->RecordAVI.handleKeyDown = HK_RecordAVI;
keys->RecordAVI.code = "RecordAVI";
keys->RecordAVI.name = STRW(ID_LABEL_HK15);
keys->RecordAVI.page = HOTKEY_PAGE_MAIN;
keys->RecordAVI.page = HOTKEY_PAGE_MOVIE;
keys->RecordAVI.key = NULL;
//Turbo Page---------------------------------------
@ -756,62 +774,62 @@ void InitCustomKeys (SCustomKeys *keys)
keys->LCDsMode.handleKeyUp = HK_LCDsMode;
keys->LCDsMode.code = "LCDsLayoutMode";
keys->LCDsMode.name = STRW(ID_LABEL_HK30);
keys->LCDsMode.page = HOTKEY_PAGE_MOVIE;
keys->LCDsMode.page = HOTKEY_PAGE_TOOLS;
keys->LCDsMode.key = VK_END;
keys->LCDsSwap.handleKeyUp = HK_LCDsSwap;
keys->LCDsSwap.code = "LCDsSwap";
keys->LCDsSwap.name = STRW(ID_LABEL_HK31);
keys->LCDsSwap.page = HOTKEY_PAGE_MOVIE;
keys->LCDsSwap.page = HOTKEY_PAGE_TOOLS;
keys->LCDsSwap.key = VK_NEXT;
keys->SearchCheats.handleKeyDown = HK_SearchCheats;
keys->SearchCheats.code = "SearchCheats";
keys->SearchCheats.name = STRW(ID_LABEL_HK54);
keys->SearchCheats.page = HOTKEY_PAGE_MOVIE;
keys->SearchCheats.page = HOTKEY_PAGE_TOOLS;
keys->SearchCheats.key = 'S';
keys->SearchCheats.modifiers = CUSTKEY_CTRL_MASK;
keys->IncreaseVolume.handleKeyDown = HK_IncreaseVolume;
keys->IncreaseVolume.code = "IncreaseVolume";
keys->IncreaseVolume.name = STRW(ID_LABEL_HK32);
keys->IncreaseVolume.page = HOTKEY_PAGE_MOVIE;
keys->IncreaseVolume.page = HOTKEY_PAGE_TOOLS;
keys->IncreaseVolume.key = NULL;
keys->DecreaseVolume.handleKeyDown = HK_DecreaseVolume;
keys->DecreaseVolume.code = "DecreaseVolume";
keys->DecreaseVolume.name = STRW(ID_LABEL_HK33);
keys->DecreaseVolume.page = HOTKEY_PAGE_MOVIE;
keys->DecreaseVolume.page = HOTKEY_PAGE_TOOLS;
keys->DecreaseVolume.key = NULL;
keys->ToggleFrameCounter.handleKeyDown = HK_ToggleFrame;
keys->ToggleFrameCounter.code = "ToggleFrameDisplay";
keys->ToggleFrameCounter.name = STRW(ID_LABEL_HK16);
keys->ToggleFrameCounter.page = HOTKEY_PAGE_MOVIE;
keys->ToggleFrameCounter.page = HOTKEY_PAGE_TOOLS;
keys->ToggleFrameCounter.key = VK_OEM_PERIOD;
keys->ToggleFPS.handleKeyDown = HK_ToggleFPS;
keys->ToggleFPS.code = "ToggleFPSDisplay";
keys->ToggleFPS.name = STRW(ID_LABEL_HK17);
keys->ToggleFPS.page = HOTKEY_PAGE_MOVIE;
keys->ToggleFPS.page = HOTKEY_PAGE_TOOLS;
keys->ToggleFPS.key = NULL;
keys->ToggleInput.handleKeyDown = HK_ToggleInput;
keys->ToggleInput.code = "ToggleInputDisplay";
keys->ToggleInput.name = STRW(ID_LABEL_HK18);
keys->ToggleInput.page = HOTKEY_PAGE_MOVIE;
keys->ToggleInput.page = HOTKEY_PAGE_TOOLS;
keys->ToggleInput.key = VK_OEM_COMMA;
keys->ToggleLag.handleKeyDown = HK_ToggleLag;
keys->ToggleLag.code = "ToggleLagDisplay";
keys->ToggleLag.name = STRW(ID_LABEL_HK19);
keys->ToggleLag.page = HOTKEY_PAGE_MOVIE;
keys->ToggleLag.page = HOTKEY_PAGE_TOOLS;
keys->ToggleLag.key = NULL;
keys->ResetLagCounter.handleKeyDown = HK_ResetLagCounter;
keys->ResetLagCounter.code = "ResetLagCounter";
keys->ResetLagCounter.name = STRW(ID_LABEL_HK20);
keys->ResetLagCounter.page = HOTKEY_PAGE_MOVIE;
keys->ResetLagCounter.page = HOTKEY_PAGE_TOOLS;
keys->ResetLagCounter.key = NULL;
//Other Page -------------------------------------------------------

View File

@ -26,6 +26,7 @@
enum HotkeyPage {
HOTKEY_PAGE_MAIN=0,
HOTKEY_PAGE_TOOLS,
HOTKEY_PAGE_MOVIE,
HOTKEY_PAGE_STATE,
HOTKEY_PAGE_STATE_SLOTS,
@ -36,7 +37,8 @@ enum HotkeyPage {
static LPCTSTR hotkeyPageTitle[] = {
_T("Main"),
_T("Movie / Tools"),
_T("Tools"),
_T("Movie"),
_T("Savestates"),
_T("Savestate Slots"),
_T("Turbo"),
@ -66,10 +68,10 @@ struct SCustomKeys
SCustomKey Load[10];
SCustomKey Slot[10];
SCustomKey QuickSave, QuickLoad, NextSaveSlot, PreviousSaveSlot;
SCustomKey Rotate0, Rotate90, Rotate180, Rotate270;
SCustomKey OpenROM, ReloadROM, Reset, Pause, FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, FrameLimitToggle, Microphone, IncreasePressure, DecreasePressure;
SCustomKey OpenROM, ReloadROM, Reset, Pause, CpuMode, FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, FrameLimitToggle, Microphone, IncreasePressure, DecreasePressure;
SCustomKey PlayMovie, RecordMovie, StopMovie, ToggleReadOnly;

View File

@ -2963,6 +2963,8 @@ int _main()
GetPrivateProfileString("Firmware", "FirmwareFile", "firmware.bin", CommonSettings.Firmware, 256, IniName);
CommonSettings.BootFromFirmware = GetPrivateProfileBool("Firmware", "BootFromFirmware", false, IniName);
CommonSettings.use_jit = GetPrivateProfileBool("Emulation", "CPUmode", true, IniName);
video.setfilter(GetPrivateProfileInt("Video", "Filter", video.NONE, IniName));
FilterUpdate(MainWindow->getHWnd(),false);
@ -3730,7 +3732,7 @@ void ScreenshotToClipboard(bool extraInfo)
int exHeight = 0;
if(extraInfo)
{
exHeight = (14 * (twolinever ? 6:5));
exHeight = (14 * (twolinever ? 7:6));
}
HDC hScreenDC = GetDC(NULL);
@ -3782,11 +3784,14 @@ void ScreenshotToClipboard(bool extraInfo)
memcpy(&str[titlelen+1], &MMU.CART_ROM[12], 6); str[titlelen+1+6] = '\0';
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 3:2), str, strlen(str));
sprintf(str, "FPS: %i/%i (%02d%%/%02d%%) | %s", mainLoopData.fps, mainLoopData.fps3d, Hud.cpuload[0], Hud.cpuload[1], paused ? "Paused":"Running");
sprintf(str, "CPU: %s", CommonSettings.use_jit ? "JIT":"Interpreter");
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 4:3), str, strlen(str));
sprintf(str, "3D Render: %s", core3DList[cur3DCore]->name);
sprintf(str, "FPS: %i/%i (%02d%%/%02d%%) | %s", mainLoopData.fps, mainLoopData.fps3d, Hud.cpuload[0], Hud.cpuload[1], paused ? "Paused":"Running");
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 5:4), str, strlen(str));
sprintf(str, "3D Render: %s", core3DList[cur3DCore]->name);
TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 6:5), str, strlen(str));
}
OpenClipboard(NULL);
@ -5795,6 +5800,7 @@ LRESULT CALLBACK EmulationSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
CheckDlgItem(hDlg, IDC_PATCHSWI3, CommonSettings.PatchSWI3);
SetDlgItemText(hDlg, IDC_ARM9BIOS, CommonSettings.ARM9BIOS);
SetDlgItemText(hDlg, IDC_ARM7BIOS, CommonSettings.ARM7BIOS);
CheckDlgItem(hDlg, IDC_CHECKBOX_DYNAREC, CommonSettings.use_jit);
if(CommonSettings.UseExtBIOS == false)
{
@ -5862,6 +5868,8 @@ LRESULT CALLBACK EmulationSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
CommonSettings.EnsataEmulation = IsDlgCheckboxChecked(hDlg, IDC_CHECKBOX_ENSATAEMULATION);
CommonSettings.advanced_timing = IsDlgCheckboxChecked(hDlg, IDC_CHECBOX_ADVANCEDTIMING);
CommonSettings.use_jit = IsDlgCheckboxChecked(hDlg, IDC_CHECKBOX_DYNAREC);
WritePrivateProfileInt("Emulation", "DebugConsole", ((CommonSettings.DebugConsole == true) ? 1 : 0), IniName);
WritePrivateProfileInt("Emulation", "EnsataEmulation", ((CommonSettings.EnsataEmulation == true) ? 1 : 0), IniName);
WritePrivateProfileBool("Emulation", "AdvancedTiming", CommonSettings.advanced_timing, IniName);
@ -5875,6 +5883,8 @@ LRESULT CALLBACK EmulationSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
WritePrivateProfileString("Firmware", "FirmwareFile", CommonSettings.Firmware, IniName);
WritePrivateProfileInt("Firmware", "BootFromFirmware", ((CommonSettings.BootFromFirmware == true) ? 1 : 0), IniName);
WritePrivateProfileInt("Emulation", "CPUmode", ((CommonSettings.use_jit == true) ? 1 : 0), IniName);
if(val == IDYES)
{
NDS_Reset();

View File

@ -419,6 +419,7 @@
#define IDC_RADIO7 1051
#define IDC_PIANO_DS3 1051
#define IDC_PIANO_HIC 1051
#define IDC_CHECKBOX_DYNAREC 1052
#define IDC_RADIO8 1052
#define IDC_IMP_AUTO_CURRENT 1052
#define IDC_IMP_AUTO_FILE 1053
@ -722,6 +723,7 @@
#define ID_LABEL_HK2 4466
#define IDC_GI_USEDROMSIZE 4467
#define ID_LABEL_HK3 4467
#define ID_LABEL_HK3b 44670
#define IDC_3DSETTINGS_FOG2 4467
#define IDC_3DSETTINGS_TEXTURE 4467
#define ID_LABEL_HK4 4468