struct Code : Xbyak::CodeGenerator {
Code()
: Xbyak::CodeGenerator(<デフォルトメモリサイズ>, Xbyak::AutoGrow)
{
...
}
};
Code c;
c.ready(); // この呼び出しを忘れてはいけない
NASM Xbyak mov eax, ebx --> mov(eax, ebx); inc ecx --> inc(ecx); ret --> ret();
(ptr|dword|word|byte) [base + index * (1|2|4|8) + displacement]
[rip + 32bit disp] ; x64 only
という形で指定します.
サイズを指定する必要がない限りptrを使えばよいです.
セレクタはサポートしていません.
NASM Xbyak mov eax, [ebx+ecx] --> mov (eax, ptr[ebx+ecx]); test byte [esp], 4 --> test (byte [esp], 4);
vaddps(xmm1, xmm2, xmm3); // xmm1 <- xmm2 + xmm3 vaddps(xmm2, xmm3); // xmm2 <- xmm2 + xmm3 vfmadd231pd(xmm1, xmm2, xmm3); // xmm1 <- (xmm2 * xmm3) + xmm1
L("L1");
jmp ("L1");
jmp ("L2");
...
少しの命令の場合.
...
L("L2");
jmp ("L3", T_NEAR);
...
沢山の命令がある場合
...
L("L3");
L("@@"); // <A>
jmp("@b"); // jmp to <A>
jmp("@f"); // jmp to <B>
L("@@"); // <B>
jmp("@b"); // jmp to <B>
void func1()
{
inLocalLabel();
L(".lp"); // <A> ; ローカルラベル
...
jmp(".lp"); // jmpt to <A>
L("aaa"); // グローバルラベル
outLocalLabel();
}
void func2()
{
L(".lp"); // <B> ; ローカルラベル
func1();
jmp(".lp"); // jmp to <B>
}
上記サンプルではinLocalLabel(), outLocalLabel()が無いと, ".lp"ラベルの二重定義エラーになります.
@param maxSize [in] コード生成最大サイズ(デフォルト2048byte) @param userPtr [in] ユーザ指定メモリ CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0);
#include <stdio.h>
#include "xbyak/xbyak.h"
struct AddFunc : public Xbyak::CodeGenerator {
AddFunc(int y)
{
mov(eax, ptr[esp+4]);
add(eax, y);
ret();
}
};
int main()
{
AddFunc a(3);
int (*add3)(int) = (int (*)(int))a.getCode();
printf("3 + 2 = %d\n", add3(2));
}
mov eax, dword ptr [esp+4]
add eax, 3
ret
となります.
/*!
1からnまでの和を求める
*/
class Sample : public Xbyak::CodeGenerator {
public:
Sample(int n)
{
mov(ecx, n); // -- (A)
xor(eax, eax); // sum
test(ecx, ecx);
jbe("exit");
xor(edx, edx); // i
L("lp");
add(eax, edx);
inc(edx);
cmp(edx, ecx);
jbe("lp");
L("exit");
ret();
}
};
int main(int argc, char *argv[])
{
int n = argc < 2 ? 100 : atoi(argv[1]);
try {
Sample s(n);
printf("1 + ... + %d = %d\n", n, ((int (*)())s.getCode())());
} catch (Xbyak::Error err) {
printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
} catch (...) {
printf("unkwon error\n");
}
return 0;
}
func(int n)
{
__asm {
mov eax, n
}
}
push ebp
mov ebp, esp
mov eax, [ebp+8]
void quantize(uint32 dest[64],
const uint32 src[64], const uint32 qTbl[64])
{
for (int i = 0; i < N; i++) {
dest[i] = src[i] / qTbl[i];
}
}
// C
uint32 func(uint32 n)
{
return n / 10;
}
// asm
mov eax, cccccccdH
mul DWORD PTR _n$[esp-4]
mov eax, edx
shr eax, 3
ret
| 種別 | q = 1(低画質) | q = 10 | q = 50 | q = 100(高画質) |
|---|---|---|---|---|
| VC2005 | 8.0 | 8.0 | 8.0 | 8.0 |
| Xbyak | 1.6 | 0.8 | 0.5 | 0.5 |
; q = 1のときに実行時生成されたコード
push esi
push edi
mov edi,dword ptr [esp+0Ch]
mov esi,dword ptr [esp+10h]
mov eax,dword ptr [esi]
shr eax,4
mov dword ptr [edi],eax ; 16で割る
mov eax,dword ptr [esi+4]
mov edx,0BA2E8BA3h
mul eax,edx
shr edx,3 ; 11で割る
...
; q = 100のときに実行時生成されたコード
push esi
push edi
mov edi,dword ptr [esp+0Ch]
mov esi,dword ptr [esp+10h]
mov eax,dword ptr [esi]
mov dword ptr [edi],eax
mov eax,dword ptr [esi+4] ; 1で割る
mov dword ptr [edi+4],eax
mov eax,dword ptr [esi+8]
mov dword ptr [edi+8],eax ; 1で割る
mov eax,dword ptr [esi+0Ch]
mov dword ptr [edi+0Ch],eax
...
void genPush(double n)
{
if (constTblPos_ == MAX_CONST_NUM) throw;
constTbl_[constTblPos_] = static_cast<float>(n);
if (regIdx_ == 7) throw;
movss(Xbyak::Xmm(++regIdx_), ptr[edx+constTblPos_*sizeof(float)]);
constTblPos_++;
}
void genSub(const char*, const char*)
{
subss(Xbyak::Xmm(regIdx_ - 1), Xbyak::Xmm(regIdx_)); regIdx_--;
}
struct Grammar : public boost::spirit::grammar<Grammar> {
FuncGen& f_;
Grammar(FuncGen& f) : f_(f) { }
template<typename ScannerT>
struct definition {
boost::spirit::rule<ScannerT> exp0, exp1, exp2, val;
definition(const Grammar& self)
{
using namespace boost;
using namespace boost::spirit;
exp0 = exp1 >> *(('+' >> exp1)[bind(&FuncGen::genAdd, ref(self.f_), _1, _2)]
| ('-' >> exp1)[bind(&FuncGen::genSub, ref(self.f_), _1, _2)]);
exp1 = exp2 >> *(('*' >> exp2)[bind(&FuncGen::genMul, ref(self.f_), _1, _2)]
| ('/' >> exp2)[bind(&FuncGen::genDiv, ref(self.f_), _1, _2)]);
val = ch_p('x')[bind(&FuncGen::genX, ref(self.f_))];
exp2 = real_p[bind(&FuncGen::genPush, ref(self.f_), _1)]
| val
| '(' >> exp0 >> ')';
}
const boost::spirit::rule<ScannerT>& start() const { return exp0; }
};
};
void (*func)(float *ret, const float *x) = (void (*)(float *, const float*))funcGen.getCode();
for (float x = 0; x < 10; x += 0.7f) {
float y;
func(&y, &x);
printf("f(%f)=%f\n", x, y);
}
; @param y [out] f(x)
; @param x [in] x
; void func(float *y, const float *x);
mov eax,dword ptr [esp+8]
mov edx,12FEA8h
movss xmm0,dword ptr [eax]
movss xmm1,dword ptr [edx]
movss xmm2,dword ptr [eax]
movss xmm3,dword ptr [eax]
mulss xmm2,xmm3
movss xmm3,dword ptr [edx+4]
movss xmm4,dword ptr [eax]
divss xmm3,xmm4
addss xmm2,xmm3
mulss xmm1,xmm2
addss xmm0,xmm1
mov eax,dword ptr [esp+4]
movss dword ptr [eax],xmm0
ret
実行結果 >calc "x*x+3*x+5" f(0.000000)=5.000000 f(0.700000)=7.590000 f(1.400000)=11.160000 f(2.100000)=15.709999 f(2.800000)=21.240000 f(3.500000)=27.750000 f(4.200000)=35.239998 f(4.900000)=43.709995 f(5.599999)=53.159992 f(6.299999)=63.589989 f(6.999999)=74.999985 f(7.699999)=87.389977 f(8.399999)=100.759972 f(9.099998)=115.109970 f(9.799998)=130.439957