parent
d9f13c57c0
commit
64073a2558
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] = {
|
||||
|
|
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(®ionWriteMask_USR[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionWriteMask_SYS[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionReadMask_USR[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionReadMask_SYS[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionExecuteMask_USR[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionExecuteMask_SYS[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionWriteSet_USR[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionWriteSet_SYS[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionReadSet_USR[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionReadSet_SYS[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionExecuteSet_USR[i],is)) return false;
|
||||
for(int i=0;i<8;i++) if(!read32le(®ionExecuteSet_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
|
||||
}
|
||||
|
||||
|
|
|
@ -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(®ionWriteMask_USR[0], 0, sizeof(regionWriteMask_USR));
|
||||
memset(®ionWriteMask_SYS[0], 0, sizeof(regionWriteMask_SYS));
|
||||
memset(®ionReadMask_USR[0], 0, sizeof(regionReadMask_USR));
|
||||
memset(®ionReadMask_SYS[0], 0, sizeof(regionReadMask_SYS));
|
||||
memset(®ionExecuteMask_USR[0], 0, sizeof(regionExecuteMask_USR));
|
||||
memset(®ionExecuteMask_SYS[0], 0, sizeof(regionExecuteMask_SYS));
|
||||
memset(®ionWriteSet_USR[0], 0, sizeof(regionWriteSet_USR));
|
||||
memset(®ionWriteSet_SYS[0], 0, sizeof(regionWriteSet_SYS));
|
||||
memset(®ionReadSet_USR[0], 0, sizeof(regionReadSet_USR));
|
||||
memset(®ionReadSet_SYS[0], 0, sizeof(regionReadSet_SYS));
|
||||
memset(®ionExecuteSet_USR[0], 0, sizeof(regionExecuteSet_USR));
|
||||
memset(®ionExecuteSet_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__*/
|
||||
|
|
|
@ -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
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
@ -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"
|
|
@ -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
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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"
|
|
@ -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
|
|
@ -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>
|
|
@ -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)
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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; }
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 -------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue