void CompiledExpression::generateSingleArgCall(X86Compiler& c, X86XmmVar& dest, X86XmmVar& arg, double (*function)(double)) { X86GpVar fn(c, kVarTypeIntPtr); c.mov(fn, imm_ptr((void*) function)); X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>()); call->setArg(0, arg); call->setRet(0, dest); }
int main(int argc, char* argv[]) { using namespace asmjit; Performance perf; uint32_t kNumRepeats = 10; uint32_t kNumIterations = 10000; JitRuntime runtime; X86Assembler a(&runtime); X86Compiler c; uint32_t r, i; // -------------------------------------------------------------------------- // [Bench - Opcode] // -------------------------------------------------------------------------- perf.reset(); for (r = 0; r < kNumRepeats; r++) { perf.start(); for (i = 0; i < kNumIterations; i++) { asmgen::opcode(a); void *p = a.make(); runtime.release(p); a.reset(); } perf.end(); } printf("Opcode | Time: %-6u [ms] | Speed: %-9u [inst/s]\n", perf.best, instPerMs(perf.best, kNumIterations, asmgen::kGenOpCodeInstCount)); // -------------------------------------------------------------------------- // [Bench - Blend] // -------------------------------------------------------------------------- perf.reset(); for (r = 0; r < kNumRepeats; r++) { perf.start(); for (i = 0; i < kNumIterations; i++) { c.attach(&a); asmgen::blend(c); c.finalize(); void* p = a.make(); runtime.release(p); } perf.end(); } printf("Blend | Time: %-6u [ms] | Speed: %-9u [inst/s]\n", perf.best, instPerMs(perf.best, kNumIterations, asmgen::kGenBlendInstCount)); return 0; }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder1<int, int>()); c.getFunc()->setHint(kFuncHintNaked, true); // Call a function. GpVar address(c.newGpVar()); GpVar var(c.getGpArg(0)); c.mov(address, imm((sysint_t)(void*)calledFunc)); X86CompilerFuncCall* ctx; ctx = c.call(address); ctx->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder1<int, int>()); ctx->setArgument(0, var); ctx->setReturn(var); ctx = c.call(address); ctx->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder1<int, int>()); ctx->setArgument(0, var); ctx->setReturn(var); c.ret(var); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder3<int, int, int, int>()); GpVar v0(c.getGpArg(0)); GpVar v1(c.getGpArg(1)); GpVar v2(c.getGpArg(2)); // Just do something;) c.shl(v0, imm(1)); c.shl(v1, imm(1)); c.shl(v2, imm(1)); // Call function. GpVar address(c.newGpVar()); c.mov(address, imm((sysint_t)(void*)calledFunc)); X86CompilerFuncCall* fCall = c.call(address); fCall->setPrototype(kX86FuncConvDefault, FuncBuilder3<Void, int, int, int>()); fCall->setArgument(0, v2); fCall->setArgument(1, v1); fCall->setArgument(2, v0); // TODO: FuncCall return value. // fCall->setReturn(v0); // c.ret(v0); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder4<Void, int*, int, int, int>()); GpVar dst0(c.getGpArg(0)); GpVar v0(c.getGpArg(1)); c.shl(v0, c.getGpArg(2)); c.ror(v0, c.getGpArg(3)); c.mov(dword_ptr(dst0), v0); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder4<Void, int*, int*, int, int>()); c.getFunc()->setHint(kFuncHintNaked, true); GpVar dst0_hi(c.getGpArg(0)); GpVar dst0_lo(c.getGpArg(1)); GpVar v0_hi(c.newGpVar(kX86VarTypeGpd)); GpVar v0_lo(c.getGpArg(2)); GpVar src0(c.getGpArg(3)); c.imul(v0_hi, v0_lo, src0); c.mov(dword_ptr(dst0_hi), v0_hi); c.mov(dword_ptr(dst0_lo), v0_lo); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder2<Void, int*, const int*>()); c.getFunc()->setHint(kFuncHintNaked, true); GpVar dst = c.getGpArg(0); GpVar src = c.getGpArg(1); for (uint i = 0; i < 4; i++) { GpVar x = c.newGpVar(kX86VarTypeGpd); GpVar y = c.newGpVar(kX86VarTypeGpd); GpVar hi = c.newGpVar(kX86VarTypeGpd); c.mov(x, dword_ptr(src, 0)); c.mov(y, dword_ptr(src, 4)); c.imul(hi, x, y); c.add(dword_ptr(dst, 0), hi); c.add(dword_ptr(dst, 4), x); } c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder3<Void, int, int, char*>()); c.getFunc()->setHint(kFuncHintNaked, true); GpVar src0(c.getGpArg(0)); GpVar src1(c.getGpArg(1)); GpVar dst0(c.getGpArg(2)); c.cmp(src0, src1); c.setz(byte_ptr(dst0)); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder3<Void, void*, void*, size_t>()); c.getFunc()->setHint(kFuncHintNaked, true); GpVar dst(c.getGpArg(0)); GpVar src(c.getGpArg(1)); GpVar cnt(c.getGpArg(2)); c.rep_movsb(dst, src, cnt); c.endFunc(); }
virtual void compile(X86Compiler& c) { Label skip(c.newLabel()); X86CompilerFuncDecl* func = c.newFunc(kX86FuncConvDefault, FuncBuilder1<int, int>()); func->setHint(kFuncHintNaked, true); GpVar var(c.getGpArg(0)); c.cmp(var, imm(1)); c.jle(skip); GpVar tmp(c.newGpVar(kX86VarTypeInt32)); c.mov(tmp, var); c.dec(tmp); X86CompilerFuncCall* fCall = c.call(func->getEntryLabel()); fCall->setPrototype(kX86FuncConvDefault, FuncBuilder1<int, int>()); fCall->setArgument(0, tmp); fCall->setReturn(tmp); c.mul(c.newGpVar(kX86VarTypeInt32), var, tmp); c.bind(skip); c.ret(var); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder0<Void>()); c.endFunc(); }
virtual void compile(X86Compiler& c) { int i; GpVar var[32]; c.newFunc(kX86FuncConvDefault, FuncBuilder1<Void, int*>()); for (i = 0; i < ASMJIT_ARRAY_SIZE(var); i++) { var[i] = c.newGpVar(kX86VarTypeGpd); c.xor_(var[i], var[i]); } GpVar v0(c.newGpVar(kX86VarTypeGpd)); Label L(c.newLabel()); c.mov(v0, imm(32)); c.bind(L); for (i = 0; i < ASMJIT_ARRAY_SIZE(var); i++) { c.add(var[i], imm(i)); } c.dec(v0); c.jnz(L); GpVar a0(c.getGpArg(0)); for (i = 0; i < ASMJIT_ARRAY_SIZE(var); i++) { c.mov(dword_ptr(a0, i * 4), var[i]); } c.endFunc(); }
void X86TestSuite::run() { size_t i; size_t testCount = testList.getLength(); for (i = 0; i < testCount; i++) { X86Compiler compiler; StringLogger logger; logger.setLogBinary(true); compiler.setLogger(&logger); X86Test* test = testList[i]; test->compile(compiler); void *func = compiler.make(); // In case that compilation fails uncomment this section to log immediately // after "compiler.make()". // // fprintf(stdout, "%s\n", logger.getString()); // fflush(stdout); if (func != NULL) { StringBuilder output; StringBuilder expected; if (test->run(func, output, expected)) { fprintf(stdout, "[Success] %s.\n", test->getName()); } else { fprintf(stdout, "[Failure] %s.\n", test->getName()); fprintf(stdout, "-------------------------------------------------------------------------------\n"); fprintf(stdout, "%s", logger.getString()); fprintf(stdout, "\n"); fprintf(stdout, "Result : %s\n", output.getData()); fprintf(stdout, "Expected: %s\n", expected.getData()); fprintf(stdout, "-------------------------------------------------------------------------------\n"); } MemoryManager::getGlobal()->free(func); } else { fprintf(stdout, "[Failure] %s.\n", test->getName()); fprintf(stdout, "-------------------------------------------------------------------------------\n"); fprintf(stdout, "%s\n", logger.getString()); fprintf(stdout, "-------------------------------------------------------------------------------\n"); } fflush(stdout); } fputs("\n", stdout); fputs(testOutput.getData(), stdout); fflush(stdout); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder8<Void, void*, void*, void*, void*, void*, void*, void*, void*>()); GpVar p1(c.getGpArg(0)); GpVar p2(c.getGpArg(1)); GpVar p3(c.getGpArg(2)); GpVar p4(c.getGpArg(3)); GpVar p5(c.getGpArg(4)); GpVar p6(c.getGpArg(5)); GpVar p7(c.getGpArg(6)); GpVar p8(c.getGpArg(7)); c.add(p1, 1); c.add(p2, 2); c.add(p3, 3); c.add(p4, 4); c.add(p5, 5); c.add(p6, 6); c.add(p7, 7); c.add(p8, 8); // Move some data into buffer provided by arguments so we can verify if it // really works without looking into assembler output. c.add(byte_ptr(p1), imm(1)); c.add(byte_ptr(p2), imm(2)); c.add(byte_ptr(p3), imm(3)); c.add(byte_ptr(p4), imm(4)); c.add(byte_ptr(p5), imm(5)); c.add(byte_ptr(p6), imm(6)); c.add(byte_ptr(p7), imm(7)); c.add(byte_ptr(p8), imm(8)); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder2<Void, int*, int*>()); // Function arguments. GpVar a1(c.getGpArg(0)); GpVar a2(c.getGpArg(1)); // Create some variables. GpVar x1(c.newGpVar(kX86VarTypeGpd)); GpVar x2(c.newGpVar(kX86VarTypeGpd)); GpVar x3(c.newGpVar(kX86VarTypeGpd)); GpVar x4(c.newGpVar(kX86VarTypeGpd)); GpVar x5(c.newGpVar(kX86VarTypeGpd)); GpVar x6(c.newGpVar(kX86VarTypeGpd)); GpVar x7(c.newGpVar(kX86VarTypeGpd)); GpVar x8(c.newGpVar(kX86VarTypeGpd)); GpVar t(c.newGpVar(kX86VarTypeGpd)); // Setup variables (use mov with reg/imm to se if register allocator works). c.mov(x1, 1); c.mov(x2, 2); c.mov(x3, 3); c.mov(x4, 4); c.mov(x5, 5); c.mov(x6, 6); c.mov(x7, 7); c.mov(x8, 8); // Make sum (addition). c.xor_(t, t); c.add(t, x1); c.add(t, x2); c.add(t, x3); c.add(t, x4); c.add(t, x5); c.add(t, x6); c.add(t, x7); c.add(t, x8); // Store result to a given pointer in first argument. c.mov(dword_ptr(a1), t); // Make sum (subtraction). c.xor_(t, t); c.sub(t, x1); c.sub(t, x2); c.sub(t, x3); c.sub(t, x4); c.sub(t, x5); c.sub(t, x6); c.sub(t, x7); c.sub(t, x8); // Store result to a given pointer in second argument. c.mov(dword_ptr(a2), t); // End of function. c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder0<int>()); GpVar v0(c.newGpVar(kX86VarTypeGpd)); GpVar v1(c.newGpVar(kX86VarTypeGpd)); GpVar v2(c.newGpVar(kX86VarTypeGpd)); GpVar v3(c.newGpVar(kX86VarTypeGpd)); GpVar v4(c.newGpVar(kX86VarTypeGpd)); c.xor_(v0, v0); c.mov(v1, 1); c.mov(v2, 2); c.mov(v3, 3); c.mov(v4, 4); c.add(v0, v1); c.add(v0, v2); c.add(v0, v3); c.add(v0, v4); c.ret(v0); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder3<int, int, int, int>()); GpVar x(c.getGpArg(0)); GpVar y(c.getGpArg(1)); GpVar op(c.getGpArg(2)); GpVar result; X86CompilerFuncCall* fCall; Label opAdd(c.newLabel()); Label opMul(c.newLabel()); c.cmp(op, 0); c.jz(opAdd); c.cmp(op, 1); c.jz(opMul); result = c.newGpVar(); c.mov(result, imm(0)); c.ret(result); c.bind(opAdd); result = c.newGpVar(); fCall = c.call((void*)calledFuncAdd); fCall->setPrototype(kX86FuncConvDefault, FuncBuilder2<int, int, int>()); fCall->setArgument(0, x); fCall->setArgument(1, y); fCall->setReturn(result); c.ret(result); c.bind(opMul); result = c.newGpVar(); fCall = c.call((void*)calledFuncMul); fCall->setPrototype(kX86FuncConvDefault, FuncBuilder2<int, int, int>()); fCall->setArgument(0, x); fCall->setArgument(1, y); fCall->setReturn(result); c.ret(result); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder3<Void, uint32_t*, const uint32_t*, size_t>()); c.getFunc()->setHint(kFuncHintNaked, true); // Omit unnecessary prolog/epilog. Label L_Loop = c.newLabel(); // Create base labels we use Label L_Exit = c.newLabel(); // in our function. GpVar dst(c.getGpArg(0)); // Get reference to function GpVar src(c.getGpArg(1)); // arguments. GpVar cnt(c.getGpArg(2)); c.alloc(dst); // Allocate all registers now, c.alloc(src); // because we want to keep them c.alloc(cnt); // in physical registers only. c.test(cnt, cnt); // Exit if length is zero. c.jz(L_Exit); c.bind(L_Loop); // Bind the loop label here. GpVar tmp(c.newGpVar(kX86VarTypeGpd)); // Copy a single dword (4 bytes). c.mov(tmp, dword_ptr(src)); c.mov(dword_ptr(dst), tmp); c.add(src, 4); // Increment dst/src pointers. c.add(dst, 4); c.dec(cnt); // Loop until cnt isn't zero. c.jnz(L_Loop); c.bind(L_Exit); // Bind the exit label here. c.endFunc(); // End of function. }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder0<int>()); c.getFunc()->setHint(kFuncHintNaked, false); GpVar v0(c.newGpVar(kX86VarTypeGpd)); GpVar v1(c.newGpVar(kX86VarTypeGpd)); GpVar cnt(c.newGpVar(kX86VarTypeGpd)); c.xor_(v0, v0); c.xor_(v1, v1); c.spill(v0); c.spill(v1); Label L(c.newLabel()); c.mov(cnt, imm(32)); c.bind(L); c.inc(v1); c.add(v0, v1); c.dec(cnt); c.jnz(L); c.ret(v0); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvCompatFastCall, FuncBuilder1<int, int*>()); c.getFunc()->setHint(kFuncHintNaked, true); GpVar buf(c.getGpArg(0)); GpVar acc0(c.newGpVar(kX86VarTypeGpd)); GpVar acc1(c.newGpVar(kX86VarTypeGpd)); c.mov(acc0, 0); c.mov(acc1, 0); uint i; for (i = 0; i < 4; i++) { { GpVar ret = c.newGpVar(kX86VarTypeGpd); GpVar ptr = c.newGpVar(kX86VarTypeGpz); GpVar idx = c.newGpVar(kX86VarTypeGpd); c.mov(ptr, buf); c.mov(idx, imm(i)); X86CompilerFuncCall* fCall = c.call((void*)calledFunc); fCall->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder2<int, int*, int>()); fCall->setArgument(0, ptr); fCall->setArgument(1, idx); fCall->setReturn(ret); c.add(acc0, ret); } { GpVar ret = c.newGpVar(kX86VarTypeGpd); GpVar ptr = c.newGpVar(kX86VarTypeGpz); GpVar idx = c.newGpVar(kX86VarTypeGpd); c.mov(ptr, buf); c.mov(idx, imm(i)); X86CompilerFuncCall* fCall = c.call((void*)calledFunc); fCall->setPrototype(kX86FuncConvCompatFastCall, FuncBuilder2<int, int*, int>()); fCall->setArgument(0, ptr); fCall->setArgument(1, idx); fCall->setReturn(ret); c.sub(acc1, ret); } } GpVar ret(c.newGpVar()); c.mov(ret, acc0); c.add(ret, acc1); c.ret(ret); c.endFunc(); }
virtual void compile(X86Compiler& c) { switch (_argsCount) { case 0: c.newFunc(kX86FuncConvDefault, FuncBuilder0<int>()); break; case 1: c.newFunc(kX86FuncConvDefault, FuncBuilder1<int, int>()); break; case 2: c.newFunc(kX86FuncConvDefault, FuncBuilder2<int, int, int>()); break; case 3: c.newFunc(kX86FuncConvDefault, FuncBuilder3<int, int, int, int>()); break; } if (_naked ) c.getFunc()->setHint(kFuncHintNaked, true); if (_pushPop) c.getFunc()->setHint(kX86FuncHintPushPop, true); GpVar gvar(c.newGpVar()); XmmVar xvar(c.newXmmVar(kX86VarTypeXmm)); // Alloc, use and spill preserved registers. if (_varsCount) { uint var = 0; uint index = 0; uint mask = 1; uint preserved = c.getFunc()->getDecl()->getGpPreservedMask(); do { if ((preserved & mask) != 0 && (index != kX86RegIndexEsp && index != kX86RegIndexEbp)) { GpVar somevar(c.newGpVar(kX86VarTypeGpd)); c.alloc(somevar, index); c.mov(somevar, imm(0)); c.spill(somevar); var++; } index++; mask <<= 1; } while (var < _varsCount && index < kX86RegNumGp); } c.alloc(gvar, zax); c.lea(gvar, xvar.m()); c.and_(gvar, imm(15)); c.ret(gvar); c.endFunc(); }
virtual void compile(X86Compiler& c) { c.newFunc(kX86FuncConvDefault, FuncBuilder0<Void>()); Label L_A = c.newLabel(); Label L_B = c.newLabel(); Label L_C = c.newLabel(); c.jmp(L_B); c.bind(L_A); c.jmp(L_C); c.bind(L_B); c.jmp(L_A); c.bind(L_C); c.ret(); c.endFunc(); }
static void benchX86(uint32_t arch, uint32_t callConv) { using namespace asmjit; Performance perf; TestRuntime runtime(arch, callConv); X86Assembler a(&runtime, arch); X86Compiler c; uint32_t r, i; const char* archName = arch == kArchX86 ? "X86" : "X64"; // -------------------------------------------------------------------------- // [Bench - Opcode] // -------------------------------------------------------------------------- size_t asmOutputSize = 0; size_t cmpOutputSize = 0; perf.reset(); for (r = 0; r < kNumRepeats; r++) { asmOutputSize = 0; perf.start(); for (i = 0; i < kNumIterations; i++) { asmgen::opcode(a); void *p = a.make(); runtime.release(p); asmOutputSize += a.getCodeSize(); a.reset(); } perf.end(); } printf("%-12s (%s) | Time: %-6u [ms] | Speed: %7.3f [MB/s]\n", "X86Assembler", archName, perf.best, mbps(perf.best, asmOutputSize)); // -------------------------------------------------------------------------- // [Bench - Blend] // -------------------------------------------------------------------------- perf.reset(); for (r = 0; r < kNumRepeats; r++) { cmpOutputSize = 0; perf.start(); for (i = 0; i < kNumIterations; i++) { c.attach(&a); asmgen::blend(c); c.finalize(); void* p = a.make(); runtime.release(p); cmpOutputSize += a.getCodeSize(); a.reset(); } perf.end(); } printf("%-12s (%s) | Time: %-6u [ms] | Speed: %7.3f [MB/s]\n", "X86Compiler", archName, perf.best, mbps(perf.best, cmpOutputSize)); }
int main(int argc, char* argv[]) { using namespace AsmJit; // ========================================================================== // Log compiler output. FileLogger logger(stderr); logger.setLogBinary(true); // Create compiler. /* X86Compiler c; c.setLogger(&logger); c.newFunc(kX86FuncConvDefault, FuncBuilder0<Void>()); c.getFunc()->setHint(kFuncHintNaked, true); X86CompilerFuncCall* ctx = c.call((void*)dummyFunc); ctx->setPrototype(kX86FuncConvDefault, FuncBuilder0<Void>()); c.endFunc(); */ X86Compiler c; c.setLogger(&logger); c.newFunc(kX86FuncConvDefault, FuncBuilder0<void>()); c.getFunc()->setHint(kFuncHintNaked, true); Label l91 = c.newLabel(); Label l92 = c.newLabel(); Label l93 = c.newLabel(); Label l94 = c.newLabel(); Label l95 = c.newLabel(); Label l96 = c.newLabel(); Label l97 = c.newLabel(); c.bind(l92); GpVar _var91(c.newGpVar()); GpVar _var92(c.newGpVar()); c.bind(l93); c.jmp(l91); c.bind(l95); c.mov(_var91, imm(0)); c.bind(l96); c.jmp(l93); c.mov(_var92, imm(1)); c.jmp(l91); c.bind(l94); c.jmp(l92); c.bind(l97); c.add(_var91, _var92); c.bind(l91); c.ret(); c.endFunc(); typedef void (*Func9)(void); Func9 func9 = asmjit_cast<Func9>(c.make()); // ========================================================================== // ========================================================================== // Make the function. // MyFn fn = asmjit_cast<MyFn>(c.make()); // Call it. // printf("Result %llu\n", (unsigned long long)fn()); // Free the generated function if it's not needed anymore. //MemoryManager::getGlobal()->free((void*)fn); // ========================================================================== return 0; }