📄 dynamicarmcode.cpp
字号:
/*****************************************************************************
*
* This program 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 program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#if defined __SYMBIAN32__
#include <e32base.h>
#elif defined _WIN32_WCE
#include <Windows.h>
#endif
//----------------------------
#include "DynamicArmCode.h"
#include "Util.h"
#include "C_buffer.h"
//mode
//1: I2 rd:16,rn:12
//2: I2C rd:16,rn:12,imm[3]:0
//4: I3 rd:0,rnlo:12,rnhi:16
//6: I2 rd:12,rn:16
//7: I3 rd:12,rn:16,rm:0
//8: I3C rd:12,rn:16,rm:0,imm[3]:20
//9: I2C rd:12,rn:16,imm[8]:0|20
//F: I2C,I1P rd:12,rn:16,imm[8]:0 (w or q *4)
//----------------------------
void *CodeAlloc(int size){
#if defined __SYMBIAN32__ || defined __PALMOS__
//Symbian
return new(true) byte[size];
#elif defined _WIN32_WCE
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READ);
#else
#error
#endif
}
//----------------------------
void CodeFree(void *code, int size){
#if defined __SYMBIAN32__ || defined __PALMOS__
//Symbian
delete[] (byte*)code;
#elif defined _WIN32_WCE
VirtualFree(code, size, MEM_DECOMMIT);
VirtualFree(code, 0, MEM_RELEASE);
#else
#error
#endif
}
//----------------------------
void CodeLock(void *code, int size){
#if defined _WIN32_WCE
DWORD protect;
VirtualProtect(code, size, PAGE_READWRITE | PAGE_NOCACHE, &protect);
#endif
}
//----------------------------
void CodeUnlock(void *code, int size){
//flush cache
#ifdef __SYMBIAN32__
User::IMB_Range(code, (byte*)code+size);
#elif defined _WIN32_WCE
DWORD protect;
VirtualProtect(code, size, PAGE_EXECUTE_READ, &protect);
static void (WINAPI *FuncCacheSync)(DWORD);
static HMODULE CoreDLL;
if(!FuncCacheSync && !CoreDLL){
CoreDLL = LoadLibrary(L"coredll.dll");
if(CoreDLL)
*(FARPROC*)&FuncCacheSync = GetProcAddress(CoreDLL, L"CacheSync");
}
if(FuncCacheSync)
FuncCacheSync(2);
#elif defined __PALMOS__
byte *mem = new byte[65536];
if(mem){
MemCpy(mem, mem, 65536);
delete[] mem;
}
#else
#error
#endif
}
//----------------------------
//detect caps
dword C_dyn_code::GetCpuCaps(){
dword caps = 0;
#if defined _WIN32_WCE
HINSTANCE hi = LoadLibrary(L"Coredll.dll");
if(hi){
typedef BOOL (t_IsProcessorFeaturePresent)(DWORD);
t_IsProcessorFeaturePresent *fp = (t_IsProcessorFeaturePresent*)GetProcAddress(hi, L"IsProcessorFeaturePresent");
if(fp){
const dword _PF_ARM_INTEL_WMMX = 0x80010003;
if((*fp)(_PF_ARM_INTEL_WMMX) != 0)
caps |= CPU_WIRELESS_MMX;
}
FreeLibrary(hi);
}
#endif
return caps;
}
//----------------------------
//----------------------------
class C_dyn_code_imp: public C_dyn_code{
struct S_instruction{
S_instruction *next, *prev;
int tag;
int read_flags;
int write_flags;
dword read_regs;
dword write_regs;
S_instruction *realloc;
bool branch; //branch label
bool is_function;
dword code_small;
byte *code_large;
int code_size;
byte *address;
S_instruction():
tag(0),
next(NULL),
prev(NULL),
read_flags(0),
write_flags(0),
read_regs(0),
write_regs(0),
realloc(NULL),
branch(false),
is_function(false),
code_small(0),
code_large(NULL),
address(NULL)
{}
};
E_CONDITION next_cond;
bool next_set,
next_byte,
next_half,
next_sign;
dword max_align;
//----------------------------
struct S_dynamic_code{
byte *alloc_base;
dword alloc_size;
byte *code;
//dword size;
S_dynamic_code():
alloc_base(NULL),
code(NULL),
//size(0),
alloc_size(0)
{}
~S_dynamic_code(){
Free();
}
void Free(){
if(alloc_base)
CodeFree(alloc_base, alloc_size);
alloc_base = NULL;
code = NULL;
//size =
alloc_size = 0;
}
C_buffer<void*> functions;
} dynamic_code;
//----------------------------
S_instruction *inst_begin, *inst_end;
bool move_back;
//bool delay_slot;
dword local_vars_size;
//----------------------------
void InstInit();
//----------------------------
inline void StoreReg(dword ®s, dword reg){
if(reg != NONE){
if(reg<32)
regs |= 1 << reg;
else
regs |= 256 << (reg-32);
}
}
//----------------------------
S_instruction *InstCreate(const void *code, int code_size, byte write_reg, byte read_reg_1, byte read_reg_2, int read_flags, int write_flags);
//----------------------------
static bool InstReadWrite(const S_instruction *a, const S_instruction *b){
return ((a->read_flags&b->write_flags) || (a->read_regs&b->write_regs));
}
static bool InstBothWrite(const S_instruction *a, const S_instruction *b){
return ((a->write_flags&b->write_flags) || (a->write_regs&b->write_regs));
}
//----------------------------
static int InstructionSize(const S_instruction *p, int pos){
if(p->code_size >= 0)
return p->code_size;
pos = pos % -p->code_size;
if(pos)
pos = -p->code_size - pos;
return pos;
}
static byte *InstCode(S_instruction *p){
return p->code_large ? p->code_large : (byte*)&p->code_small;
}
//----------------------------
void InstAdd(S_instruction *ins){
assert(ins);
S_instruction *p = inst_end; //insert after p
/*
if(delay_slot){
assert(p && !p->branch && !InstReadWrite(p, ins) && !InstReadWrite(ins, p) && !InstBothWrite(p, ins));
p->branch = true;
p = p->prev;
delay_slot = false;
}
*/
if(move_back){
while(p && !p->branch && !p->is_function && !InstReadWrite(p, ins) && !InstReadWrite(ins, p) && !InstBothWrite(p, ins))
p = p->prev;
move_back = false;
}
if(p){
if(p->next)
p->next->prev = ins;
else
inst_end = ins;
ins->next = p->next;
ins->prev = p;
p->next = ins;
}else{
if(inst_begin)
inst_begin->prev = ins;
else
inst_end = ins;
ins->next = inst_begin;
ins->prev = NULL;
inst_begin = ins;
}
}
//----------------------------
S_instruction *InstCreate32(int Code32, byte write_reg = NONE, byte read_reg_1 = NONE, byte read_reg_2 = NONE, int read_flags = 0, int write_flags = 0){
return InstCreate(&Code32, 4, write_reg, read_reg_1, read_reg_2, read_flags, write_flags);
}
/*
S_instruction *InstCreate16(int Code16, byte write_reg, byte read_reg_1, byte read_reg_2, int read_flags, int write_flags){
return InstCreate(&Code16, 2, write_reg, read_reg_1, read_reg_2, read_flags, write_flags);
}
*/
//----------------------------
void FreeInstructions();
//----------------------------
bool InstReAlloc(S_instruction *p, const S_instruction *realloc);
//----------------------------
void IPLD(int *code, byte *dest);
//----------------------------
public:
C_dyn_code_imp():
move_back(false),
local_vars_size(0),
inst_begin(NULL),
inst_end(NULL),
max_align(0)
{
InstInit();
}
~C_dyn_code_imp(){
Close();
}
void Close(){
FreeInstructions();
dynamic_code.Free();
}
//----------------------------
virtual void Byte(){
next_byte = true;
next_sign = false;
}
virtual void Half(){
next_half = true;
next_sign = false;
}
virtual void SByte(){
next_byte = true;
next_sign = true;
}
virtual void SHalf(){
next_half = true;
next_sign = true;
}
virtual void Cond(E_CONDITION c){
next_cond = c;
}
virtual void Set(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -