asmjit 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +5 -3
- data/asmjit.gemspec +1 -3
- data/ext/asmjit/asmjit/.editorconfig +10 -0
- data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
- data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
- data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
- data/ext/asmjit/asmjit/.gitignore +6 -0
- data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
- data/ext/asmjit/asmjit/LICENSE.md +17 -0
- data/ext/asmjit/asmjit/README.md +69 -0
- data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
- data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
- data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
- data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
- data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
- data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
- data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
- data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
- data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
- data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
- data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
- data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
- data/ext/asmjit/asmjit/test/broken.cpp +312 -0
- data/ext/asmjit/asmjit/test/broken.h +148 -0
- data/ext/asmjit/asmjit/test/cmdline.h +61 -0
- data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
- data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
- data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
- data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
- data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
- data/ext/asmjit/asmjit.cc +167 -30
- data/ext/asmjit/extconf.rb +9 -9
- data/lib/asmjit/version.rb +1 -1
- data/lib/asmjit.rb +14 -4
- metadata +198 -17
@@ -0,0 +1,4317 @@
|
|
1
|
+
// This file is part of AsmJit project <https://asmjit.com>
|
2
|
+
//
|
3
|
+
// See asmjit.h or LICENSE.md for license and copyright information
|
4
|
+
// SPDX-License-Identifier: Zlib
|
5
|
+
|
6
|
+
#include <asmjit/core.h>
|
7
|
+
#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86
|
8
|
+
|
9
|
+
#include <asmjit/x86.h>
|
10
|
+
#include <setjmp.h>
|
11
|
+
#include <stdio.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <string.h>
|
14
|
+
|
15
|
+
// Required for function tests that pass / return XMM registers.
|
16
|
+
#include <emmintrin.h>
|
17
|
+
|
18
|
+
#include "asmjit_test_misc.h"
|
19
|
+
#include "asmjit_test_compiler.h"
|
20
|
+
|
21
|
+
#ifdef _MSC_VER
|
22
|
+
// Interaction between '_setjmp' and C++ object destruction is non-portable.
|
23
|
+
#pragma warning(disable: 4611)
|
24
|
+
#endif
|
25
|
+
|
26
|
+
using namespace asmjit;
|
27
|
+
|
28
|
+
// x86::Compiler - X86TestCase
|
29
|
+
// ===========================
|
30
|
+
|
31
|
+
class X86TestCase : public TestCase {
|
32
|
+
public:
|
33
|
+
X86TestCase(const char* name = nullptr)
|
34
|
+
: TestCase(name) {}
|
35
|
+
|
36
|
+
virtual void compile(BaseCompiler& cc) override {
|
37
|
+
compile(static_cast<x86::Compiler&>(cc));
|
38
|
+
}
|
39
|
+
|
40
|
+
virtual void compile(x86::Compiler& cc) = 0;
|
41
|
+
};
|
42
|
+
|
43
|
+
// x86::Compiler - X86Test_AlignBase
|
44
|
+
// =================================
|
45
|
+
|
46
|
+
class X86Test_AlignBase : public X86TestCase {
|
47
|
+
public:
|
48
|
+
X86Test_AlignBase(uint32_t argCount, uint32_t alignment, bool preserveFP)
|
49
|
+
: _argCount(argCount),
|
50
|
+
_alignment(alignment),
|
51
|
+
_preserveFP(preserveFP) {
|
52
|
+
_name.assignFormat("AlignBase {NumArgs=%u Alignment=%u PreserveFP=%c}", argCount, alignment, preserveFP ? 'Y' : 'N');
|
53
|
+
}
|
54
|
+
|
55
|
+
static void add(TestApp& app) {
|
56
|
+
for (uint32_t i = 0; i <= 16; i++) {
|
57
|
+
for (uint32_t a = 16; a <= 32; a += 16) {
|
58
|
+
app.add(new X86Test_AlignBase(i, a, true));
|
59
|
+
app.add(new X86Test_AlignBase(i, a, false));
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
virtual void compile(x86::Compiler& cc) {
|
65
|
+
uint32_t i;
|
66
|
+
uint32_t argCount = _argCount;
|
67
|
+
|
68
|
+
FuncSignatureBuilder signature(CallConvId::kHost);
|
69
|
+
signature.setRetT<int>();
|
70
|
+
for (i = 0; i < argCount; i++)
|
71
|
+
signature.addArgT<int>();
|
72
|
+
|
73
|
+
FuncNode* funcNode = cc.addFunc(signature);
|
74
|
+
if (_preserveFP)
|
75
|
+
funcNode->frame().setPreservedFP();
|
76
|
+
|
77
|
+
x86::Gp gpVar = cc.newIntPtr("gpVar");
|
78
|
+
x86::Gp gpSum;
|
79
|
+
x86::Mem stack = cc.newStack(_alignment, _alignment);
|
80
|
+
|
81
|
+
// Do a sum of arguments to verify a possible relocation when misaligned.
|
82
|
+
if (argCount) {
|
83
|
+
for (i = 0; i < argCount; i++) {
|
84
|
+
x86::Gp gpArg = cc.newInt32("gpArg%u", i);
|
85
|
+
funcNode->setArg(i, gpArg);
|
86
|
+
|
87
|
+
if (i == 0)
|
88
|
+
gpSum = gpArg;
|
89
|
+
else
|
90
|
+
cc.add(gpSum, gpArg);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
// Check alignment of xmmVar (has to be 16).
|
95
|
+
cc.lea(gpVar, stack);
|
96
|
+
cc.and_(gpVar, _alignment - 1);
|
97
|
+
|
98
|
+
// Add a sum of all arguments to check if they are correct.
|
99
|
+
if (argCount)
|
100
|
+
cc.or_(gpVar.r32(), gpSum);
|
101
|
+
|
102
|
+
cc.ret(gpVar);
|
103
|
+
cc.endFunc();
|
104
|
+
}
|
105
|
+
|
106
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
107
|
+
typedef unsigned int U;
|
108
|
+
|
109
|
+
typedef U (*Func0)();
|
110
|
+
typedef U (*Func1)(U);
|
111
|
+
typedef U (*Func2)(U, U);
|
112
|
+
typedef U (*Func3)(U, U, U);
|
113
|
+
typedef U (*Func4)(U, U, U, U);
|
114
|
+
typedef U (*Func5)(U, U, U, U, U);
|
115
|
+
typedef U (*Func6)(U, U, U, U, U, U);
|
116
|
+
typedef U (*Func7)(U, U, U, U, U, U, U);
|
117
|
+
typedef U (*Func8)(U, U, U, U, U, U, U, U);
|
118
|
+
typedef U (*Func9)(U, U, U, U, U, U, U, U, U);
|
119
|
+
typedef U (*Func10)(U, U, U, U, U, U, U, U, U, U);
|
120
|
+
typedef U (*Func11)(U, U, U, U, U, U, U, U, U, U, U);
|
121
|
+
typedef U (*Func12)(U, U, U, U, U, U, U, U, U, U, U, U);
|
122
|
+
typedef U (*Func13)(U, U, U, U, U, U, U, U, U, U, U, U, U);
|
123
|
+
typedef U (*Func14)(U, U, U, U, U, U, U, U, U, U, U, U, U, U);
|
124
|
+
typedef U (*Func15)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
|
125
|
+
typedef U (*Func16)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
|
126
|
+
|
127
|
+
unsigned int resultRet = 0;
|
128
|
+
unsigned int expectRet = 0;
|
129
|
+
|
130
|
+
switch (_argCount) {
|
131
|
+
case 0:
|
132
|
+
resultRet = ptr_as_func<Func0>(_func)();
|
133
|
+
expectRet = 0;
|
134
|
+
break;
|
135
|
+
case 1:
|
136
|
+
resultRet = ptr_as_func<Func1>(_func)(1);
|
137
|
+
expectRet = 1;
|
138
|
+
break;
|
139
|
+
case 2:
|
140
|
+
resultRet = ptr_as_func<Func2>(_func)(1, 2);
|
141
|
+
expectRet = 1 + 2;
|
142
|
+
break;
|
143
|
+
case 3:
|
144
|
+
resultRet = ptr_as_func<Func3>(_func)(1, 2, 3);
|
145
|
+
expectRet = 1 + 2 + 3;
|
146
|
+
break;
|
147
|
+
case 4:
|
148
|
+
resultRet = ptr_as_func<Func4>(_func)(1, 2, 3, 4);
|
149
|
+
expectRet = 1 + 2 + 3 + 4;
|
150
|
+
break;
|
151
|
+
case 5:
|
152
|
+
resultRet = ptr_as_func<Func5>(_func)(1, 2, 3, 4, 5);
|
153
|
+
expectRet = 1 + 2 + 3 + 4 + 5;
|
154
|
+
break;
|
155
|
+
case 6:
|
156
|
+
resultRet = ptr_as_func<Func6>(_func)(1, 2, 3, 4, 5, 6);
|
157
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6;
|
158
|
+
break;
|
159
|
+
case 7:
|
160
|
+
resultRet = ptr_as_func<Func7>(_func)(1, 2, 3, 4, 5, 6, 7);
|
161
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7;
|
162
|
+
break;
|
163
|
+
case 8:
|
164
|
+
resultRet = ptr_as_func<Func8>(_func)(1, 2, 3, 4, 5, 6, 7, 8);
|
165
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8;
|
166
|
+
break;
|
167
|
+
case 9:
|
168
|
+
resultRet = ptr_as_func<Func9>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
169
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9;
|
170
|
+
break;
|
171
|
+
case 10:
|
172
|
+
resultRet = ptr_as_func<Func10>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
173
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
|
174
|
+
break;
|
175
|
+
case 11:
|
176
|
+
resultRet = ptr_as_func<Func11>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
|
177
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11;
|
178
|
+
break;
|
179
|
+
case 12:
|
180
|
+
resultRet = ptr_as_func<Func12>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
|
181
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
|
182
|
+
break;
|
183
|
+
case 13:
|
184
|
+
resultRet = ptr_as_func<Func13>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
|
185
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13;
|
186
|
+
break;
|
187
|
+
case 14:
|
188
|
+
resultRet = ptr_as_func<Func14>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
|
189
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14;
|
190
|
+
break;
|
191
|
+
case 15:
|
192
|
+
resultRet = ptr_as_func<Func15>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
193
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15;
|
194
|
+
break;
|
195
|
+
case 16:
|
196
|
+
resultRet = ptr_as_func<Func16>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
|
197
|
+
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16;
|
198
|
+
break;
|
199
|
+
}
|
200
|
+
|
201
|
+
result.assignFormat("ret={%u, %u}", resultRet >> 28, resultRet & 0x0FFFFFFFu);
|
202
|
+
expect.assignFormat("ret={%u, %u}", expectRet >> 28, expectRet & 0x0FFFFFFFu);
|
203
|
+
|
204
|
+
return resultRet == expectRet;
|
205
|
+
}
|
206
|
+
|
207
|
+
uint32_t _argCount;
|
208
|
+
uint32_t _alignment;
|
209
|
+
bool _preserveFP;
|
210
|
+
};
|
211
|
+
|
212
|
+
// x86::Compiler - X86Test_NoCode
|
213
|
+
// ==============================
|
214
|
+
|
215
|
+
class X86Test_NoCode : public X86TestCase {
|
216
|
+
public:
|
217
|
+
X86Test_NoCode() : X86TestCase("NoCode") {}
|
218
|
+
|
219
|
+
static void add(TestApp& app) {
|
220
|
+
app.add(new X86Test_NoCode());
|
221
|
+
}
|
222
|
+
|
223
|
+
virtual void compile(x86::Compiler& cc) {
|
224
|
+
cc.addFunc(FuncSignatureT<void>(CallConvId::kHost));
|
225
|
+
cc.endFunc();
|
226
|
+
}
|
227
|
+
|
228
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
229
|
+
DebugUtils::unused(result, expect);
|
230
|
+
|
231
|
+
typedef void(*Func)(void);
|
232
|
+
Func func = ptr_as_func<Func>(_func);
|
233
|
+
|
234
|
+
func();
|
235
|
+
return true;
|
236
|
+
}
|
237
|
+
};
|
238
|
+
|
239
|
+
// x86::Compiler - X86Test_AlignNone
|
240
|
+
// =================================
|
241
|
+
|
242
|
+
class X86Test_NoAlign : public X86TestCase {
|
243
|
+
public:
|
244
|
+
X86Test_NoAlign() : X86TestCase("NoAlign") {}
|
245
|
+
|
246
|
+
static void add(TestApp& app) {
|
247
|
+
app.add(new X86Test_NoAlign());
|
248
|
+
}
|
249
|
+
|
250
|
+
virtual void compile(x86::Compiler& cc) {
|
251
|
+
cc.addFunc(FuncSignatureT<void>(CallConvId::kHost));
|
252
|
+
cc.align(AlignMode::kCode, 0);
|
253
|
+
cc.align(AlignMode::kCode, 1);
|
254
|
+
cc.endFunc();
|
255
|
+
}
|
256
|
+
|
257
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
258
|
+
DebugUtils::unused(result, expect);
|
259
|
+
|
260
|
+
typedef void (*Func)(void);
|
261
|
+
Func func = ptr_as_func<Func>(_func);
|
262
|
+
|
263
|
+
func();
|
264
|
+
return true;
|
265
|
+
}
|
266
|
+
};
|
267
|
+
|
268
|
+
// x86::Compiler - X86Test_JumpMerge
|
269
|
+
// =================================
|
270
|
+
|
271
|
+
class X86Test_JumpMerge : public X86TestCase {
|
272
|
+
public:
|
273
|
+
X86Test_JumpMerge() : X86TestCase("JumpMerge") {}
|
274
|
+
|
275
|
+
static void add(TestApp& app) {
|
276
|
+
app.add(new X86Test_JumpMerge());
|
277
|
+
}
|
278
|
+
|
279
|
+
virtual void compile(x86::Compiler& cc) {
|
280
|
+
Label L0 = cc.newLabel();
|
281
|
+
Label L1 = cc.newLabel();
|
282
|
+
Label L2 = cc.newLabel();
|
283
|
+
Label LEnd = cc.newLabel();
|
284
|
+
|
285
|
+
x86::Gp dst = cc.newIntPtr("dst");
|
286
|
+
x86::Gp val = cc.newInt32("val");
|
287
|
+
|
288
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int>(CallConvId::kHost));
|
289
|
+
funcNode->setArg(0, dst);
|
290
|
+
funcNode->setArg(1, val);
|
291
|
+
|
292
|
+
cc.cmp(val, 0);
|
293
|
+
cc.je(L2);
|
294
|
+
|
295
|
+
cc.cmp(val, 1);
|
296
|
+
cc.je(L1);
|
297
|
+
|
298
|
+
cc.cmp(val, 2);
|
299
|
+
cc.je(L0);
|
300
|
+
|
301
|
+
cc.mov(x86::dword_ptr(dst), val);
|
302
|
+
cc.jmp(LEnd);
|
303
|
+
|
304
|
+
// On purpose. This tests whether the CFG constructs a single basic-block
|
305
|
+
// from multiple labels next to each other.
|
306
|
+
cc.bind(L0);
|
307
|
+
cc.bind(L1);
|
308
|
+
cc.bind(L2);
|
309
|
+
cc.mov(x86::dword_ptr(dst), 0);
|
310
|
+
|
311
|
+
cc.bind(LEnd);
|
312
|
+
cc.endFunc();
|
313
|
+
}
|
314
|
+
|
315
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
316
|
+
typedef void(*Func)(int*, int);
|
317
|
+
Func func = ptr_as_func<Func>(_func);
|
318
|
+
|
319
|
+
int arr[5] = { -1, -1, -1, -1, -1 };
|
320
|
+
int exp[5] = { 0, 0, 0, 3, 4 };
|
321
|
+
|
322
|
+
for (int i = 0; i < 5; i++)
|
323
|
+
func(&arr[i], i);
|
324
|
+
|
325
|
+
result.assignFormat("ret={%d, %d, %d, %d, %d}", arr[0], arr[1], arr[2], arr[3], arr[4]);
|
326
|
+
expect.assignFormat("ret={%d, %d, %d, %d, %d}", exp[0], exp[1], exp[2], exp[3], exp[4]);
|
327
|
+
|
328
|
+
return result == expect;
|
329
|
+
}
|
330
|
+
};
|
331
|
+
|
332
|
+
// x86::Compiler - X86Test_JumpCross
|
333
|
+
// =================================
|
334
|
+
|
335
|
+
class X86Test_JumpCross : public X86TestCase {
|
336
|
+
public:
|
337
|
+
X86Test_JumpCross() : X86TestCase("JumpCross") {}
|
338
|
+
|
339
|
+
static void add(TestApp& app) {
|
340
|
+
app.add(new X86Test_JumpCross());
|
341
|
+
}
|
342
|
+
|
343
|
+
virtual void compile(x86::Compiler& cc) {
|
344
|
+
cc.addFunc(FuncSignatureT<void>(CallConvId::kHost));
|
345
|
+
|
346
|
+
Label L1 = cc.newLabel();
|
347
|
+
Label L2 = cc.newLabel();
|
348
|
+
Label L3 = cc.newLabel();
|
349
|
+
|
350
|
+
cc.jmp(L2);
|
351
|
+
|
352
|
+
cc.bind(L1);
|
353
|
+
cc.jmp(L3);
|
354
|
+
|
355
|
+
cc.bind(L2);
|
356
|
+
cc.jmp(L1);
|
357
|
+
|
358
|
+
cc.bind(L3);
|
359
|
+
cc.endFunc();
|
360
|
+
}
|
361
|
+
|
362
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
363
|
+
DebugUtils::unused(result, expect);
|
364
|
+
|
365
|
+
typedef void (*Func)(void);
|
366
|
+
Func func = ptr_as_func<Func>(_func);
|
367
|
+
|
368
|
+
func();
|
369
|
+
return true;
|
370
|
+
}
|
371
|
+
};
|
372
|
+
|
373
|
+
// x86::Compiler - X86Test_JumpMany
|
374
|
+
// ================================
|
375
|
+
|
376
|
+
class X86Test_JumpMany : public X86TestCase {
|
377
|
+
public:
|
378
|
+
X86Test_JumpMany() : X86TestCase("JumpMany") {}
|
379
|
+
|
380
|
+
static void add(TestApp& app) {
|
381
|
+
app.add(new X86Test_JumpMany());
|
382
|
+
}
|
383
|
+
|
384
|
+
virtual void compile(x86::Compiler& cc) {
|
385
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
386
|
+
for (uint32_t i = 0; i < 1000; i++) {
|
387
|
+
Label L = cc.newLabel();
|
388
|
+
cc.jmp(L);
|
389
|
+
cc.bind(L);
|
390
|
+
}
|
391
|
+
|
392
|
+
x86::Gp ret = cc.newInt32("ret");
|
393
|
+
cc.xor_(ret, ret);
|
394
|
+
cc.ret(ret);
|
395
|
+
cc.endFunc();
|
396
|
+
}
|
397
|
+
|
398
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
399
|
+
typedef int (*Func)(void);
|
400
|
+
|
401
|
+
Func func = ptr_as_func<Func>(_func);
|
402
|
+
|
403
|
+
int resultRet = func();
|
404
|
+
int expectRet = 0;
|
405
|
+
|
406
|
+
result.assignFormat("ret={%d}", resultRet);
|
407
|
+
expect.assignFormat("ret={%d}", expectRet);
|
408
|
+
|
409
|
+
return resultRet == expectRet;
|
410
|
+
}
|
411
|
+
};
|
412
|
+
|
413
|
+
// x86::Compiler - X86Test_JumpUnreachable1
|
414
|
+
// ========================================
|
415
|
+
|
416
|
+
class X86Test_JumpUnreachable1 : public X86TestCase {
|
417
|
+
public:
|
418
|
+
X86Test_JumpUnreachable1() : X86TestCase("JumpUnreachable1") {}
|
419
|
+
|
420
|
+
static void add(TestApp& app) {
|
421
|
+
app.add(new X86Test_JumpUnreachable1());
|
422
|
+
}
|
423
|
+
|
424
|
+
virtual void compile(x86::Compiler& cc) {
|
425
|
+
cc.addFunc(FuncSignatureT<void>(CallConvId::kHost));
|
426
|
+
|
427
|
+
Label L_1 = cc.newLabel();
|
428
|
+
Label L_2 = cc.newLabel();
|
429
|
+
Label L_3 = cc.newLabel();
|
430
|
+
Label L_4 = cc.newLabel();
|
431
|
+
Label L_5 = cc.newLabel();
|
432
|
+
Label L_6 = cc.newLabel();
|
433
|
+
Label L_7 = cc.newLabel();
|
434
|
+
|
435
|
+
x86::Gp v0 = cc.newUInt32("v0");
|
436
|
+
x86::Gp v1 = cc.newUInt32("v1");
|
437
|
+
|
438
|
+
cc.bind(L_2);
|
439
|
+
cc.bind(L_3);
|
440
|
+
|
441
|
+
cc.jmp(L_1);
|
442
|
+
|
443
|
+
cc.bind(L_5);
|
444
|
+
cc.mov(v0, 0);
|
445
|
+
|
446
|
+
cc.bind(L_6);
|
447
|
+
cc.jmp(L_3);
|
448
|
+
cc.mov(v1, 1);
|
449
|
+
cc.jmp(L_1);
|
450
|
+
|
451
|
+
cc.bind(L_4);
|
452
|
+
cc.jmp(L_2);
|
453
|
+
cc.bind(L_7);
|
454
|
+
cc.add(v0, v1);
|
455
|
+
|
456
|
+
cc.align(AlignMode::kCode, 16);
|
457
|
+
cc.bind(L_1);
|
458
|
+
cc.ret();
|
459
|
+
cc.endFunc();
|
460
|
+
}
|
461
|
+
|
462
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
463
|
+
typedef void (*Func)(void);
|
464
|
+
Func func = ptr_as_func<Func>(_func);
|
465
|
+
|
466
|
+
func();
|
467
|
+
|
468
|
+
result.append("ret={}");
|
469
|
+
expect.append("ret={}");
|
470
|
+
|
471
|
+
return true;
|
472
|
+
}
|
473
|
+
};
|
474
|
+
|
475
|
+
// x86::Compiler - X86Test_JumpUnreachable2
|
476
|
+
// ========================================
|
477
|
+
|
478
|
+
class X86Test_JumpUnreachable2 : public X86TestCase {
|
479
|
+
public:
|
480
|
+
X86Test_JumpUnreachable2() : X86TestCase("JumpUnreachable2") {}
|
481
|
+
|
482
|
+
static void add(TestApp& app) {
|
483
|
+
app.add(new X86Test_JumpUnreachable2());
|
484
|
+
}
|
485
|
+
|
486
|
+
virtual void compile(x86::Compiler& cc) {
|
487
|
+
cc.addFunc(FuncSignatureT<void>(CallConvId::kHost));
|
488
|
+
|
489
|
+
Label L_1 = cc.newLabel();
|
490
|
+
Label L_2 = cc.newLabel();
|
491
|
+
|
492
|
+
x86::Gp v0 = cc.newUInt32("v0");
|
493
|
+
x86::Gp v1 = cc.newUInt32("v1");
|
494
|
+
|
495
|
+
cc.jmp(L_1);
|
496
|
+
cc.bind(L_2);
|
497
|
+
cc.mov(v0, 1);
|
498
|
+
cc.mov(v1, 2);
|
499
|
+
cc.cmp(v0, v1);
|
500
|
+
cc.jz(L_2);
|
501
|
+
cc.jmp(L_1);
|
502
|
+
|
503
|
+
cc.bind(L_1);
|
504
|
+
cc.ret();
|
505
|
+
cc.endFunc();
|
506
|
+
}
|
507
|
+
|
508
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
509
|
+
typedef void (*Func)(void);
|
510
|
+
Func func = ptr_as_func<Func>(_func);
|
511
|
+
|
512
|
+
func();
|
513
|
+
|
514
|
+
result.append("ret={}");
|
515
|
+
expect.append("ret={}");
|
516
|
+
|
517
|
+
return true;
|
518
|
+
}
|
519
|
+
};
|
520
|
+
|
521
|
+
// x86::Compiler - X86Test_JumpTable1
|
522
|
+
// ==================================
|
523
|
+
|
524
|
+
class X86Test_JumpTable1 : public X86TestCase {
|
525
|
+
public:
|
526
|
+
bool _annotated;
|
527
|
+
|
528
|
+
X86Test_JumpTable1(bool annotated)
|
529
|
+
: X86TestCase("X86Test_JumpTable1"),
|
530
|
+
_annotated(annotated) {
|
531
|
+
_name.assignFormat("JumpTable {%s}", annotated ? "Annotated" : "Unknown Reg/Mem");
|
532
|
+
}
|
533
|
+
|
534
|
+
enum Operator {
|
535
|
+
kOperatorAdd = 0,
|
536
|
+
kOperatorSub = 1,
|
537
|
+
kOperatorMul = 2,
|
538
|
+
kOperatorDiv = 3
|
539
|
+
};
|
540
|
+
|
541
|
+
static void add(TestApp& app) {
|
542
|
+
app.add(new X86Test_JumpTable1(false));
|
543
|
+
app.add(new X86Test_JumpTable1(true));
|
544
|
+
}
|
545
|
+
|
546
|
+
virtual void compile(x86::Compiler& cc) {
|
547
|
+
x86::Xmm a = cc.newXmmSs("a");
|
548
|
+
x86::Xmm b = cc.newXmmSs("b");
|
549
|
+
x86::Gp op = cc.newUInt32("op");
|
550
|
+
x86::Gp target = cc.newIntPtr("target");
|
551
|
+
x86::Gp offset = cc.newIntPtr("offset");
|
552
|
+
|
553
|
+
Label L_Table = cc.newLabel();
|
554
|
+
Label L_Add = cc.newLabel();
|
555
|
+
Label L_Sub = cc.newLabel();
|
556
|
+
Label L_Mul = cc.newLabel();
|
557
|
+
Label L_Div = cc.newLabel();
|
558
|
+
Label L_End = cc.newLabel();
|
559
|
+
|
560
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConvId::kHost));
|
561
|
+
funcNode->setArg(0, a);
|
562
|
+
funcNode->setArg(1, b);
|
563
|
+
funcNode->setArg(2, op);
|
564
|
+
|
565
|
+
cc.lea(offset, x86::ptr(L_Table));
|
566
|
+
if (cc.is64Bit())
|
567
|
+
cc.movsxd(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
|
568
|
+
else
|
569
|
+
cc.mov(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
|
570
|
+
cc.add(target, offset);
|
571
|
+
|
572
|
+
// JumpAnnotation allows to annotate all possible jump targets of
|
573
|
+
// instructions where it cannot be deduced from operands.
|
574
|
+
if (_annotated) {
|
575
|
+
JumpAnnotation* annotation = cc.newJumpAnnotation();
|
576
|
+
annotation->addLabel(L_Add);
|
577
|
+
annotation->addLabel(L_Sub);
|
578
|
+
annotation->addLabel(L_Mul);
|
579
|
+
annotation->addLabel(L_Div);
|
580
|
+
cc.jmp(target, annotation);
|
581
|
+
}
|
582
|
+
else {
|
583
|
+
cc.jmp(target);
|
584
|
+
}
|
585
|
+
|
586
|
+
cc.bind(L_Add);
|
587
|
+
cc.addss(a, b);
|
588
|
+
cc.jmp(L_End);
|
589
|
+
|
590
|
+
cc.bind(L_Sub);
|
591
|
+
cc.subss(a, b);
|
592
|
+
cc.jmp(L_End);
|
593
|
+
|
594
|
+
cc.bind(L_Mul);
|
595
|
+
cc.mulss(a, b);
|
596
|
+
cc.jmp(L_End);
|
597
|
+
|
598
|
+
cc.bind(L_Div);
|
599
|
+
cc.divss(a, b);
|
600
|
+
|
601
|
+
cc.bind(L_End);
|
602
|
+
cc.ret(a);
|
603
|
+
|
604
|
+
cc.endFunc();
|
605
|
+
|
606
|
+
cc.bind(L_Table);
|
607
|
+
cc.embedLabelDelta(L_Add, L_Table, 4);
|
608
|
+
cc.embedLabelDelta(L_Sub, L_Table, 4);
|
609
|
+
cc.embedLabelDelta(L_Mul, L_Table, 4);
|
610
|
+
cc.embedLabelDelta(L_Div, L_Table, 4);
|
611
|
+
}
|
612
|
+
|
613
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
614
|
+
typedef float (*Func)(float, float, uint32_t);
|
615
|
+
Func func = ptr_as_func<Func>(_func);
|
616
|
+
|
617
|
+
float results[4];
|
618
|
+
float expected[4];
|
619
|
+
|
620
|
+
results[0] = func(33.0f, 14.0f, kOperatorAdd);
|
621
|
+
results[1] = func(33.0f, 14.0f, kOperatorSub);
|
622
|
+
results[2] = func(10.0f, 6.0f, kOperatorMul);
|
623
|
+
results[3] = func(80.0f, 8.0f, kOperatorDiv);
|
624
|
+
|
625
|
+
expected[0] = 47.0f;
|
626
|
+
expected[1] = 19.0f;
|
627
|
+
expected[2] = 60.0f;
|
628
|
+
expected[3] = 10.0f;
|
629
|
+
|
630
|
+
result.assignFormat("ret={%f, %f, %f, %f}", results[0], results[1], results[2], results[3]);
|
631
|
+
expect.assignFormat("ret={%f, %f, %f, %f}", expected[0], expected[1], expected[2], expected[3]);
|
632
|
+
|
633
|
+
return result == expect;
|
634
|
+
}
|
635
|
+
};
|
636
|
+
|
637
|
+
// x86::Compiler - X86Test_JumpTable2
|
638
|
+
// ==================================
|
639
|
+
|
640
|
+
class X86Test_JumpTable2 : public X86TestCase {
|
641
|
+
public:
|
642
|
+
X86Test_JumpTable2()
|
643
|
+
: X86TestCase("JumpTable {Jumping to Begin}") {}
|
644
|
+
|
645
|
+
static void add(TestApp& app) {
|
646
|
+
app.add(new X86Test_JumpTable2());
|
647
|
+
}
|
648
|
+
|
649
|
+
virtual void compile(x86::Compiler& cc) {
|
650
|
+
x86::Gp result = cc.newUInt32("result");
|
651
|
+
x86::Gp value = cc.newUInt32("value");
|
652
|
+
x86::Gp target = cc.newIntPtr("target");
|
653
|
+
x86::Gp offset = cc.newIntPtr("offset");
|
654
|
+
|
655
|
+
Label L_Table = cc.newLabel();
|
656
|
+
Label L_Begin = cc.newLabel();
|
657
|
+
Label L_Case0 = cc.newLabel();
|
658
|
+
Label L_Case1 = cc.newLabel();
|
659
|
+
Label L_End = cc.newLabel();
|
660
|
+
|
661
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost));
|
662
|
+
funcNode->setArg(0, value);
|
663
|
+
|
664
|
+
cc.bind(L_Begin);
|
665
|
+
cc.lea(offset, x86::ptr(L_Table));
|
666
|
+
if (cc.is64Bit())
|
667
|
+
cc.movsxd(target, x86::dword_ptr(offset, value.cloneAs(offset), 2));
|
668
|
+
else
|
669
|
+
cc.mov(target, x86::dword_ptr(offset, value.cloneAs(offset), 2));
|
670
|
+
cc.add(target, offset);
|
671
|
+
|
672
|
+
{
|
673
|
+
JumpAnnotation* annotation = cc.newJumpAnnotation();
|
674
|
+
annotation->addLabel(L_Case0);
|
675
|
+
annotation->addLabel(L_Case1);
|
676
|
+
annotation->addLabel(L_Begin); // Never used, just for the purpose of the test.
|
677
|
+
cc.jmp(target, annotation);
|
678
|
+
|
679
|
+
cc.bind(L_Case0);
|
680
|
+
cc.mov(result, 0);
|
681
|
+
cc.jmp(L_End);
|
682
|
+
|
683
|
+
cc.bind(L_Case1);
|
684
|
+
cc.mov(result, 1);
|
685
|
+
cc.jmp(L_End);
|
686
|
+
}
|
687
|
+
|
688
|
+
cc.bind(L_End);
|
689
|
+
cc.ret(result);
|
690
|
+
|
691
|
+
cc.endFunc();
|
692
|
+
|
693
|
+
cc.bind(L_Table);
|
694
|
+
cc.embedLabelDelta(L_Case0, L_Table, 4);
|
695
|
+
cc.embedLabelDelta(L_Case1, L_Table, 4);
|
696
|
+
}
|
697
|
+
|
698
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
699
|
+
typedef int (*Func)(int);
|
700
|
+
Func func = ptr_as_func<Func>(_func);
|
701
|
+
|
702
|
+
int results[2];
|
703
|
+
int expected[2];
|
704
|
+
|
705
|
+
results[0] = func(0);
|
706
|
+
results[1] = func(1);
|
707
|
+
|
708
|
+
expected[0] = 0;
|
709
|
+
expected[1] = 1;
|
710
|
+
|
711
|
+
result.assignFormat("ret={%d, %d}", results[0], results[1]);
|
712
|
+
expect.assignFormat("ret={%d, %d}", expected[0], expected[1]);
|
713
|
+
|
714
|
+
return result == expect;
|
715
|
+
}
|
716
|
+
};
|
717
|
+
|
718
|
+
// x86::Compiler - X86Test_AllocBase
|
719
|
+
// =================================
|
720
|
+
|
721
|
+
class X86Test_AllocBase : public X86TestCase {
|
722
|
+
public:
|
723
|
+
X86Test_AllocBase() : X86TestCase("AllocBase") {}
|
724
|
+
|
725
|
+
static void add(TestApp& app) {
|
726
|
+
app.add(new X86Test_AllocBase());
|
727
|
+
}
|
728
|
+
|
729
|
+
virtual void compile(x86::Compiler& cc) {
|
730
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
731
|
+
|
732
|
+
x86::Gp v0 = cc.newInt32("v0");
|
733
|
+
x86::Gp v1 = cc.newInt32("v1");
|
734
|
+
x86::Gp v2 = cc.newInt32("v2");
|
735
|
+
x86::Gp v3 = cc.newInt32("v3");
|
736
|
+
x86::Gp v4 = cc.newInt32("v4");
|
737
|
+
|
738
|
+
cc.xor_(v0, v0);
|
739
|
+
|
740
|
+
cc.mov(v1, 1);
|
741
|
+
cc.mov(v2, 2);
|
742
|
+
cc.mov(v3, 3);
|
743
|
+
cc.mov(v4, 4);
|
744
|
+
|
745
|
+
cc.add(v0, v1);
|
746
|
+
cc.add(v0, v2);
|
747
|
+
cc.add(v0, v3);
|
748
|
+
cc.add(v0, v4);
|
749
|
+
|
750
|
+
cc.ret(v0);
|
751
|
+
cc.endFunc();
|
752
|
+
}
|
753
|
+
|
754
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
755
|
+
typedef int (*Func)(void);
|
756
|
+
Func func = ptr_as_func<Func>(_func);
|
757
|
+
|
758
|
+
int resultRet = func();
|
759
|
+
int expectRet = 1 + 2 + 3 + 4;
|
760
|
+
|
761
|
+
result.assignFormat("ret=%d", resultRet);
|
762
|
+
expect.assignFormat("ret=%d", expectRet);
|
763
|
+
|
764
|
+
return resultRet == expectRet;
|
765
|
+
}
|
766
|
+
};
|
767
|
+
|
768
|
+
// x86::Compiler - X86Test_AllocMany1
|
769
|
+
// ==================================
|
770
|
+
|
771
|
+
class X86Test_AllocMany1 : public X86TestCase {
|
772
|
+
public:
|
773
|
+
X86Test_AllocMany1() : X86TestCase("AllocMany1") {}
|
774
|
+
|
775
|
+
enum { kCount = 8 };
|
776
|
+
|
777
|
+
static void add(TestApp& app) {
|
778
|
+
app.add(new X86Test_AllocMany1());
|
779
|
+
}
|
780
|
+
|
781
|
+
virtual void compile(x86::Compiler& cc) {
|
782
|
+
x86::Gp a0 = cc.newIntPtr("a0");
|
783
|
+
x86::Gp a1 = cc.newIntPtr("a1");
|
784
|
+
|
785
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int*>(CallConvId::kHost));
|
786
|
+
funcNode->setArg(0, a0);
|
787
|
+
funcNode->setArg(1, a1);
|
788
|
+
|
789
|
+
// Create some variables.
|
790
|
+
x86::Gp t = cc.newInt32("t");
|
791
|
+
x86::Gp x[kCount];
|
792
|
+
|
793
|
+
uint32_t i;
|
794
|
+
|
795
|
+
// Setup variables (use mov with reg/imm to se if register allocator works).
|
796
|
+
for (i = 0; i < kCount; i++) x[i] = cc.newInt32("x%u", i);
|
797
|
+
for (i = 0; i < kCount; i++) cc.mov(x[i], int(i + 1));
|
798
|
+
|
799
|
+
// Make sum (addition).
|
800
|
+
cc.xor_(t, t);
|
801
|
+
for (i = 0; i < kCount; i++) cc.add(t, x[i]);
|
802
|
+
|
803
|
+
// Store result to a given pointer in first argument.
|
804
|
+
cc.mov(x86::dword_ptr(a0), t);
|
805
|
+
|
806
|
+
// Clear t.
|
807
|
+
cc.xor_(t, t);
|
808
|
+
|
809
|
+
// Make sum (subtraction).
|
810
|
+
for (i = 0; i < kCount; i++) cc.sub(t, x[i]);
|
811
|
+
|
812
|
+
// Store result to a given pointer in second argument.
|
813
|
+
cc.mov(x86::dword_ptr(a1), t);
|
814
|
+
|
815
|
+
// End of function.
|
816
|
+
cc.endFunc();
|
817
|
+
}
|
818
|
+
|
819
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
820
|
+
typedef void (*Func)(int*, int*);
|
821
|
+
Func func = ptr_as_func<Func>(_func);
|
822
|
+
|
823
|
+
int resultX;
|
824
|
+
int resultY;
|
825
|
+
|
826
|
+
int expectX = 36;
|
827
|
+
int expectY = -36;
|
828
|
+
|
829
|
+
func(&resultX, &resultY);
|
830
|
+
|
831
|
+
result.assignFormat("ret={x=%d, y=%d}", resultX, resultY);
|
832
|
+
expect.assignFormat("ret={x=%d, y=%d}", expectX, expectY);
|
833
|
+
|
834
|
+
return resultX == expectX && resultY == expectY;
|
835
|
+
}
|
836
|
+
};
|
837
|
+
|
838
|
+
// x86::Compiler - X86Test_AllocMany2
|
839
|
+
// ==================================
|
840
|
+
|
841
|
+
class X86Test_AllocMany2 : public X86TestCase {
|
842
|
+
public:
|
843
|
+
X86Test_AllocMany2() : X86TestCase("AllocMany2") {}
|
844
|
+
|
845
|
+
static void add(TestApp& app) {
|
846
|
+
app.add(new X86Test_AllocMany2());
|
847
|
+
}
|
848
|
+
|
849
|
+
virtual void compile(x86::Compiler& cc) {
|
850
|
+
x86::Gp a = cc.newIntPtr("a");
|
851
|
+
x86::Gp v[32];
|
852
|
+
|
853
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, uint32_t*>(CallConvId::kHost));
|
854
|
+
funcNode->setArg(0, a);
|
855
|
+
|
856
|
+
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.newInt32("v%d", i);
|
857
|
+
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.xor_(v[i], v[i]);
|
858
|
+
|
859
|
+
x86::Gp x = cc.newInt32("x");
|
860
|
+
Label L = cc.newLabel();
|
861
|
+
|
862
|
+
cc.mov(x, 32);
|
863
|
+
cc.bind(L);
|
864
|
+
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.add(v[i], i);
|
865
|
+
|
866
|
+
cc.dec(x);
|
867
|
+
cc.jnz(L);
|
868
|
+
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.mov(x86::dword_ptr(a, int(i * 4)), v[i]);
|
869
|
+
|
870
|
+
cc.endFunc();
|
871
|
+
}
|
872
|
+
|
873
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
874
|
+
typedef void (*Func)(uint32_t*);
|
875
|
+
Func func = ptr_as_func<Func>(_func);
|
876
|
+
|
877
|
+
uint32_t i;
|
878
|
+
uint32_t resultBuf[32];
|
879
|
+
uint32_t expectBuf[32];
|
880
|
+
|
881
|
+
for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++)
|
882
|
+
expectBuf[i] = i * 32;
|
883
|
+
func(resultBuf);
|
884
|
+
|
885
|
+
for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++) {
|
886
|
+
if (i != 0) {
|
887
|
+
result.append(',');
|
888
|
+
expect.append(',');
|
889
|
+
}
|
890
|
+
|
891
|
+
result.appendFormat("%u", resultBuf[i]);
|
892
|
+
expect.appendFormat("%u", expectBuf[i]);
|
893
|
+
}
|
894
|
+
|
895
|
+
return result == expect;
|
896
|
+
}
|
897
|
+
};
|
898
|
+
|
899
|
+
// x86::Compiler - X86Test_AllocImul1
|
900
|
+
// ==================================
|
901
|
+
|
902
|
+
class X86Test_AllocImul1 : public X86TestCase {
|
903
|
+
public:
|
904
|
+
X86Test_AllocImul1() : X86TestCase("AllocImul1") {}
|
905
|
+
|
906
|
+
static void add(TestApp& app) {
|
907
|
+
app.add(new X86Test_AllocImul1());
|
908
|
+
}
|
909
|
+
|
910
|
+
virtual void compile(x86::Compiler& cc) {
|
911
|
+
x86::Gp dstHi = cc.newIntPtr("dstHi");
|
912
|
+
x86::Gp dstLo = cc.newIntPtr("dstLo");
|
913
|
+
|
914
|
+
x86::Gp vHi = cc.newInt32("vHi");
|
915
|
+
x86::Gp vLo = cc.newInt32("vLo");
|
916
|
+
x86::Gp src = cc.newInt32("src");
|
917
|
+
|
918
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int*, int, int>(CallConvId::kHost));
|
919
|
+
funcNode->setArg(0, dstHi);
|
920
|
+
funcNode->setArg(1, dstLo);
|
921
|
+
funcNode->setArg(2, vLo);
|
922
|
+
funcNode->setArg(3, src);
|
923
|
+
|
924
|
+
cc.imul(vHi, vLo, src);
|
925
|
+
cc.mov(x86::dword_ptr(dstHi), vHi);
|
926
|
+
cc.mov(x86::dword_ptr(dstLo), vLo);
|
927
|
+
cc.endFunc();
|
928
|
+
}
|
929
|
+
|
930
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
931
|
+
typedef void (*Func)(int*, int*, int, int);
|
932
|
+
Func func = ptr_as_func<Func>(_func);
|
933
|
+
|
934
|
+
int v0 = 4;
|
935
|
+
int v1 = 4;
|
936
|
+
|
937
|
+
int resultHi;
|
938
|
+
int resultLo;
|
939
|
+
|
940
|
+
int expectHi = 0;
|
941
|
+
int expectLo = v0 * v1;
|
942
|
+
|
943
|
+
func(&resultHi, &resultLo, v0, v1);
|
944
|
+
|
945
|
+
result.assignFormat("hi=%d, lo=%d", resultHi, resultLo);
|
946
|
+
expect.assignFormat("hi=%d, lo=%d", expectHi, expectLo);
|
947
|
+
|
948
|
+
return resultHi == expectHi && resultLo == expectLo;
|
949
|
+
}
|
950
|
+
};
|
951
|
+
|
952
|
+
// x86::Compiler - X86Test_AllocImul2
|
953
|
+
// ==================================
|
954
|
+
|
955
|
+
class X86Test_AllocImul2 : public X86TestCase {
|
956
|
+
public:
|
957
|
+
X86Test_AllocImul2() : X86TestCase("AllocImul2") {}
|
958
|
+
|
959
|
+
static void add(TestApp& app) {
|
960
|
+
app.add(new X86Test_AllocImul2());
|
961
|
+
}
|
962
|
+
|
963
|
+
virtual void compile(x86::Compiler& cc) {
|
964
|
+
x86::Gp dst = cc.newIntPtr("dst");
|
965
|
+
x86::Gp src = cc.newIntPtr("src");
|
966
|
+
|
967
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, const int*>(CallConvId::kHost));
|
968
|
+
funcNode->setArg(0, dst);
|
969
|
+
funcNode->setArg(1, src);
|
970
|
+
|
971
|
+
for (unsigned int i = 0; i < 4; i++) {
|
972
|
+
x86::Gp x = cc.newInt32("x");
|
973
|
+
x86::Gp y = cc.newInt32("y");
|
974
|
+
x86::Gp hi = cc.newInt32("hi");
|
975
|
+
|
976
|
+
cc.mov(x, x86::dword_ptr(src, 0));
|
977
|
+
cc.mov(y, x86::dword_ptr(src, 4));
|
978
|
+
|
979
|
+
cc.imul(hi, x, y);
|
980
|
+
cc.add(x86::dword_ptr(dst, 0), hi);
|
981
|
+
cc.add(x86::dword_ptr(dst, 4), x);
|
982
|
+
}
|
983
|
+
|
984
|
+
cc.endFunc();
|
985
|
+
}
|
986
|
+
|
987
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
988
|
+
typedef void (*Func)(int*, const int*);
|
989
|
+
Func func = ptr_as_func<Func>(_func);
|
990
|
+
|
991
|
+
int src[2] = { 4, 9 };
|
992
|
+
int resultRet[2] = { 0, 0 };
|
993
|
+
int expectRet[2] = { 0, (4 * 9) * 4 };
|
994
|
+
|
995
|
+
func(resultRet, src);
|
996
|
+
|
997
|
+
result.assignFormat("ret={%d, %d}", resultRet[0], resultRet[1]);
|
998
|
+
expect.assignFormat("ret={%d, %d}", expectRet[0], expectRet[1]);
|
999
|
+
|
1000
|
+
return resultRet[0] == expectRet[0] && resultRet[1] == expectRet[1];
|
1001
|
+
}
|
1002
|
+
};
|
1003
|
+
|
1004
|
+
// x86::Compiler - X86Test_AllocIdiv1
|
1005
|
+
// ==================================
|
1006
|
+
|
1007
|
+
class X86Test_AllocIdiv1 : public X86TestCase {
|
1008
|
+
public:
|
1009
|
+
X86Test_AllocIdiv1() : X86TestCase("AllocIdiv1") {}
|
1010
|
+
|
1011
|
+
static void add(TestApp& app) {
|
1012
|
+
app.add(new X86Test_AllocIdiv1());
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
virtual void compile(x86::Compiler& cc) {
|
1016
|
+
x86::Gp a = cc.newInt32("a");
|
1017
|
+
x86::Gp b = cc.newInt32("b");
|
1018
|
+
x86::Gp dummy = cc.newInt32("dummy");
|
1019
|
+
|
1020
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
1021
|
+
funcNode->setArg(0, a);
|
1022
|
+
funcNode->setArg(1, b);
|
1023
|
+
|
1024
|
+
cc.xor_(dummy, dummy);
|
1025
|
+
cc.idiv(dummy, a, b);
|
1026
|
+
|
1027
|
+
cc.ret(a);
|
1028
|
+
cc.endFunc();
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1032
|
+
typedef int (*Func)(int, int);
|
1033
|
+
Func func = ptr_as_func<Func>(_func);
|
1034
|
+
|
1035
|
+
int v0 = 2999;
|
1036
|
+
int v1 = 245;
|
1037
|
+
|
1038
|
+
int resultRet = func(v0, v1);
|
1039
|
+
int expectRet = 2999 / 245;
|
1040
|
+
|
1041
|
+
result.assignFormat("result=%d", resultRet);
|
1042
|
+
expect.assignFormat("result=%d", expectRet);
|
1043
|
+
|
1044
|
+
return resultRet == expectRet;
|
1045
|
+
}
|
1046
|
+
};
|
1047
|
+
|
1048
|
+
// x86::Compiler - X86Test_AllocSetz
|
1049
|
+
// =================================
|
1050
|
+
|
1051
|
+
class X86Test_AllocSetz : public X86TestCase {
|
1052
|
+
public:
|
1053
|
+
X86Test_AllocSetz() : X86TestCase("AllocSetz") {}
|
1054
|
+
|
1055
|
+
static void add(TestApp& app) {
|
1056
|
+
app.add(new X86Test_AllocSetz());
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
virtual void compile(x86::Compiler& cc) {
|
1060
|
+
x86::Gp src0 = cc.newInt32("src0");
|
1061
|
+
x86::Gp src1 = cc.newInt32("src1");
|
1062
|
+
x86::Gp dst0 = cc.newIntPtr("dst0");
|
1063
|
+
|
1064
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int, int, char*>(CallConvId::kHost));
|
1065
|
+
funcNode->setArg(0, src0);
|
1066
|
+
funcNode->setArg(1, src1);
|
1067
|
+
funcNode->setArg(2, dst0);
|
1068
|
+
|
1069
|
+
cc.cmp(src0, src1);
|
1070
|
+
cc.setz(x86::byte_ptr(dst0));
|
1071
|
+
|
1072
|
+
cc.endFunc();
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1076
|
+
typedef void (*Func)(int, int, char*);
|
1077
|
+
Func func = ptr_as_func<Func>(_func);
|
1078
|
+
|
1079
|
+
char resultBuf[4];
|
1080
|
+
char expectBuf[4] = { 1, 0, 0, 1 };
|
1081
|
+
|
1082
|
+
func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0).
|
1083
|
+
func(0, 1, &resultBuf[1]); // We are expecting 0 (0 != 1).
|
1084
|
+
func(1, 0, &resultBuf[2]); // We are expecting 0 (1 != 0).
|
1085
|
+
func(1, 1, &resultBuf[3]); // We are expecting 1 (1 == 1).
|
1086
|
+
|
1087
|
+
result.assignFormat("out={%d, %d, %d, %d}", resultBuf[0], resultBuf[1], resultBuf[2], resultBuf[3]);
|
1088
|
+
expect.assignFormat("out={%d, %d, %d, %d}", expectBuf[0], expectBuf[1], expectBuf[2], expectBuf[3]);
|
1089
|
+
|
1090
|
+
return resultBuf[0] == expectBuf[0] &&
|
1091
|
+
resultBuf[1] == expectBuf[1] &&
|
1092
|
+
resultBuf[2] == expectBuf[2] &&
|
1093
|
+
resultBuf[3] == expectBuf[3] ;
|
1094
|
+
}
|
1095
|
+
};
|
1096
|
+
|
1097
|
+
// x86::Compiler - X86Test_AllocShlRor
|
1098
|
+
// ===================================
|
1099
|
+
|
1100
|
+
class X86Test_AllocShlRor : public X86TestCase {
|
1101
|
+
public:
|
1102
|
+
X86Test_AllocShlRor() : X86TestCase("AllocShlRor") {}
|
1103
|
+
|
1104
|
+
static void add(TestApp& app) {
|
1105
|
+
app.add(new X86Test_AllocShlRor());
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
virtual void compile(x86::Compiler& cc) {
|
1109
|
+
x86::Gp dst = cc.newIntPtr("dst");
|
1110
|
+
x86::Gp var = cc.newInt32("var");
|
1111
|
+
x86::Gp vShlParam = cc.newInt32("vShlParam");
|
1112
|
+
x86::Gp vRorParam = cc.newInt32("vRorParam");
|
1113
|
+
|
1114
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int, int, int>(CallConvId::kHost));
|
1115
|
+
funcNode->setArg(0, dst);
|
1116
|
+
funcNode->setArg(1, var);
|
1117
|
+
funcNode->setArg(2, vShlParam);
|
1118
|
+
funcNode->setArg(3, vRorParam);
|
1119
|
+
|
1120
|
+
cc.shl(var, vShlParam);
|
1121
|
+
cc.ror(var, vRorParam);
|
1122
|
+
cc.mov(x86::dword_ptr(dst), var);
|
1123
|
+
cc.endFunc();
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1127
|
+
typedef void (*Func)(int*, int, int, int);
|
1128
|
+
Func func = ptr_as_func<Func>(_func);
|
1129
|
+
|
1130
|
+
int v0 = 0x000000FF;
|
1131
|
+
|
1132
|
+
int resultRet;
|
1133
|
+
int expectRet = 0x0000FF00;
|
1134
|
+
|
1135
|
+
func(&resultRet, v0, 16, 8);
|
1136
|
+
|
1137
|
+
result.assignFormat("ret=%d", resultRet);
|
1138
|
+
expect.assignFormat("ret=%d", expectRet);
|
1139
|
+
|
1140
|
+
return resultRet == expectRet;
|
1141
|
+
}
|
1142
|
+
};
|
1143
|
+
|
1144
|
+
// x86::Compiler - X86Test_AllocGpbLo
|
1145
|
+
// ==================================
|
1146
|
+
|
1147
|
+
class X86Test_AllocGpbLo1 : public X86TestCase {
|
1148
|
+
public:
|
1149
|
+
X86Test_AllocGpbLo1() : X86TestCase("AllocGpbLo1") {}
|
1150
|
+
|
1151
|
+
enum : uint32_t { kCount = 32 };
|
1152
|
+
|
1153
|
+
static void add(TestApp& app) {
|
1154
|
+
app.add(new X86Test_AllocGpbLo1());
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
virtual void compile(x86::Compiler& cc) {
|
1158
|
+
x86::Gp rPtr = cc.newUIntPtr("rPtr");
|
1159
|
+
x86::Gp rSum = cc.newUInt32("rSum");
|
1160
|
+
x86::Gp x[kCount];
|
1161
|
+
|
1162
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t*>(CallConvId::kHost));
|
1163
|
+
funcNode->setArg(0, rPtr);
|
1164
|
+
|
1165
|
+
for (uint32_t i = 0; i < kCount; i++) {
|
1166
|
+
x[i] = cc.newUInt32("x%u", i);
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
// Init pseudo-regs with values from our array.
|
1170
|
+
for (uint32_t i = 0; i < kCount; i++) {
|
1171
|
+
cc.mov(x[i], x86::dword_ptr(rPtr, int(i * 4)));
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
for (uint32_t i = 2; i < kCount; i++) {
|
1175
|
+
// Add and truncate to 8 bit; no purpose, just mess with jit.
|
1176
|
+
cc.add (x[i ], x[i-1]);
|
1177
|
+
cc.movzx(x[i ], x[i ].r8());
|
1178
|
+
cc.movzx(x[i-2], x[i-1].r8());
|
1179
|
+
cc.movzx(x[i-1], x[i-2].r8());
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
// Sum up all computed values.
|
1183
|
+
cc.mov(rSum, 0);
|
1184
|
+
for (uint32_t i = 0; i < kCount; i++) {
|
1185
|
+
cc.add(rSum, x[i]);
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
// Return the sum.
|
1189
|
+
cc.ret(rSum);
|
1190
|
+
cc.endFunc();
|
1191
|
+
}
|
1192
|
+
|
1193
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1194
|
+
typedef uint32_t (*Func)(uint32_t*);
|
1195
|
+
Func func = ptr_as_func<Func>(_func);
|
1196
|
+
|
1197
|
+
uint32_t i;
|
1198
|
+
uint32_t buf[kCount];
|
1199
|
+
uint32_t resultRet;
|
1200
|
+
uint32_t expectRet;
|
1201
|
+
|
1202
|
+
expectRet = 0;
|
1203
|
+
for (i = 0; i < kCount; i++) {
|
1204
|
+
buf[i] = 1;
|
1205
|
+
}
|
1206
|
+
|
1207
|
+
for (i = 2; i < kCount; i++) {
|
1208
|
+
buf[i ]+= buf[i-1];
|
1209
|
+
buf[i ] = buf[i ] & 0xFF;
|
1210
|
+
buf[i-2] = buf[i-1] & 0xFF;
|
1211
|
+
buf[i-1] = buf[i-2] & 0xFF;
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
for (i = 0; i < kCount; i++) {
|
1215
|
+
expectRet += buf[i];
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
for (i = 0; i < kCount; i++) {
|
1219
|
+
buf[i] = 1;
|
1220
|
+
}
|
1221
|
+
resultRet = func(buf);
|
1222
|
+
|
1223
|
+
result.assignFormat("ret=%d", resultRet);
|
1224
|
+
expect.assignFormat("ret=%d", expectRet);
|
1225
|
+
|
1226
|
+
return resultRet == expectRet;
|
1227
|
+
}
|
1228
|
+
};
|
1229
|
+
|
1230
|
+
// x86::Compiler - X86Test_AllocGpbLo2
|
1231
|
+
// ===================================
|
1232
|
+
|
1233
|
+
class X86Test_AllocGpbLo2 : public X86TestCase {
|
1234
|
+
public:
|
1235
|
+
X86Test_AllocGpbLo2() : X86TestCase("AllocGpbLo2") {}
|
1236
|
+
|
1237
|
+
static void add(TestApp& app) {
|
1238
|
+
app.add(new X86Test_AllocGpbLo2());
|
1239
|
+
}
|
1240
|
+
|
1241
|
+
virtual void compile(x86::Compiler& cc) {
|
1242
|
+
x86::Gp v = cc.newUInt32("v");
|
1243
|
+
|
1244
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConvId::kHost));
|
1245
|
+
funcNode->setArg(0, v);
|
1246
|
+
|
1247
|
+
cc.mov(v.r8(), 0xFF);
|
1248
|
+
cc.ret(v);
|
1249
|
+
cc.endFunc();
|
1250
|
+
}
|
1251
|
+
|
1252
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1253
|
+
typedef uint32_t (*Func)(uint32_t);
|
1254
|
+
Func func = ptr_as_func<Func>(_func);
|
1255
|
+
|
1256
|
+
uint32_t resultRet = func(0x12345678u);
|
1257
|
+
uint32_t expectRet = 0x123456FFu;
|
1258
|
+
|
1259
|
+
result.assignFormat("ret=%d", resultRet);
|
1260
|
+
expect.assignFormat("ret=%d", expectRet);
|
1261
|
+
|
1262
|
+
return resultRet == expectRet;
|
1263
|
+
}
|
1264
|
+
};
|
1265
|
+
|
1266
|
+
// x86::Compiler - X86Test_AllocRepMovsb
|
1267
|
+
// =====================================
|
1268
|
+
|
1269
|
+
class X86Test_AllocRepMovsb : public X86TestCase {
|
1270
|
+
public:
|
1271
|
+
X86Test_AllocRepMovsb() : X86TestCase("AllocRepMovsb") {}
|
1272
|
+
|
1273
|
+
static void add(TestApp& app) {
|
1274
|
+
app.add(new X86Test_AllocRepMovsb());
|
1275
|
+
}
|
1276
|
+
|
1277
|
+
virtual void compile(x86::Compiler& cc) {
|
1278
|
+
x86::Gp dst = cc.newIntPtr("dst");
|
1279
|
+
x86::Gp src = cc.newIntPtr("src");
|
1280
|
+
x86::Gp cnt = cc.newIntPtr("cnt");
|
1281
|
+
|
1282
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, void*, size_t>(CallConvId::kHost));
|
1283
|
+
funcNode->setArg(0, dst);
|
1284
|
+
funcNode->setArg(1, src);
|
1285
|
+
funcNode->setArg(2, cnt);
|
1286
|
+
|
1287
|
+
cc.rep(cnt).movs(x86::byte_ptr(dst), x86::byte_ptr(src));
|
1288
|
+
cc.endFunc();
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1292
|
+
typedef void (*Func)(void*, void*, size_t);
|
1293
|
+
Func func = ptr_as_func<Func>(_func);
|
1294
|
+
|
1295
|
+
char dst[20] = { 0 };
|
1296
|
+
char src[20] = "Hello AsmJit!";
|
1297
|
+
func(dst, src, strlen(src) + 1);
|
1298
|
+
|
1299
|
+
result.assignFormat("ret=\"%s\"", dst);
|
1300
|
+
expect.assignFormat("ret=\"%s\"", src);
|
1301
|
+
|
1302
|
+
return result == expect;
|
1303
|
+
}
|
1304
|
+
};
|
1305
|
+
|
1306
|
+
// x86::Compiler - X86Test_AllocIfElse1
|
1307
|
+
// ====================================
|
1308
|
+
|
1309
|
+
class X86Test_AllocIfElse1 : public X86TestCase {
|
1310
|
+
public:
|
1311
|
+
X86Test_AllocIfElse1() : X86TestCase("AllocIfElse1") {}
|
1312
|
+
|
1313
|
+
static void add(TestApp& app) {
|
1314
|
+
app.add(new X86Test_AllocIfElse1());
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
virtual void compile(x86::Compiler& cc) {
|
1318
|
+
x86::Gp v1 = cc.newInt32("v1");
|
1319
|
+
x86::Gp v2 = cc.newInt32("v2");
|
1320
|
+
|
1321
|
+
Label L_1 = cc.newLabel();
|
1322
|
+
Label L_2 = cc.newLabel();
|
1323
|
+
|
1324
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
1325
|
+
funcNode->setArg(0, v1);
|
1326
|
+
funcNode->setArg(1, v2);
|
1327
|
+
|
1328
|
+
cc.cmp(v1, v2);
|
1329
|
+
cc.jg(L_1);
|
1330
|
+
|
1331
|
+
cc.mov(v1, 1);
|
1332
|
+
cc.jmp(L_2);
|
1333
|
+
|
1334
|
+
cc.bind(L_1);
|
1335
|
+
cc.mov(v1, 2);
|
1336
|
+
|
1337
|
+
cc.bind(L_2);
|
1338
|
+
cc.ret(v1);
|
1339
|
+
cc.endFunc();
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1343
|
+
typedef int (*Func)(int, int);
|
1344
|
+
Func func = ptr_as_func<Func>(_func);
|
1345
|
+
|
1346
|
+
int a = func(0, 1);
|
1347
|
+
int b = func(1, 0);
|
1348
|
+
|
1349
|
+
result.appendFormat("ret={%d, %d}", a, b);
|
1350
|
+
expect.appendFormat("ret={%d, %d}", 1, 2);
|
1351
|
+
|
1352
|
+
return result == expect;
|
1353
|
+
}
|
1354
|
+
};
|
1355
|
+
|
1356
|
+
// x86::Compiler - X86Test_AllocIfElse2
|
1357
|
+
// ====================================
|
1358
|
+
|
1359
|
+
class X86Test_AllocIfElse2 : public X86TestCase {
|
1360
|
+
public:
|
1361
|
+
X86Test_AllocIfElse2() : X86TestCase("AllocIfElse2") {}
|
1362
|
+
|
1363
|
+
static void add(TestApp& app) {
|
1364
|
+
app.add(new X86Test_AllocIfElse2());
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
virtual void compile(x86::Compiler& cc) {
|
1368
|
+
x86::Gp v1 = cc.newInt32("v1");
|
1369
|
+
x86::Gp v2 = cc.newInt32("v2");
|
1370
|
+
|
1371
|
+
Label L_1 = cc.newLabel();
|
1372
|
+
Label L_2 = cc.newLabel();
|
1373
|
+
Label L_3 = cc.newLabel();
|
1374
|
+
Label L_4 = cc.newLabel();
|
1375
|
+
|
1376
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
1377
|
+
funcNode->setArg(0, v1);
|
1378
|
+
funcNode->setArg(1, v2);
|
1379
|
+
|
1380
|
+
cc.jmp(L_1);
|
1381
|
+
cc.bind(L_2);
|
1382
|
+
cc.jmp(L_4);
|
1383
|
+
cc.bind(L_1);
|
1384
|
+
|
1385
|
+
cc.cmp(v1, v2);
|
1386
|
+
cc.jg(L_3);
|
1387
|
+
|
1388
|
+
cc.mov(v1, 1);
|
1389
|
+
cc.jmp(L_2);
|
1390
|
+
|
1391
|
+
cc.bind(L_3);
|
1392
|
+
cc.mov(v1, 2);
|
1393
|
+
cc.jmp(L_2);
|
1394
|
+
|
1395
|
+
cc.bind(L_4);
|
1396
|
+
|
1397
|
+
cc.ret(v1);
|
1398
|
+
cc.endFunc();
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1402
|
+
typedef int (*Func)(int, int);
|
1403
|
+
Func func = ptr_as_func<Func>(_func);
|
1404
|
+
|
1405
|
+
int a = func(0, 1);
|
1406
|
+
int b = func(1, 0);
|
1407
|
+
|
1408
|
+
result.appendFormat("ret={%d, %d}", a, b);
|
1409
|
+
expect.appendFormat("ret={%d, %d}", 1, 2);
|
1410
|
+
|
1411
|
+
return result == expect;
|
1412
|
+
}
|
1413
|
+
};
|
1414
|
+
|
1415
|
+
// x86::Compiler - X86Test_AllocIfElse3
|
1416
|
+
// ====================================
|
1417
|
+
|
1418
|
+
class X86Test_AllocIfElse3 : public X86TestCase {
|
1419
|
+
public:
|
1420
|
+
X86Test_AllocIfElse3() : X86TestCase("AllocIfElse3") {}
|
1421
|
+
|
1422
|
+
static void add(TestApp& app) {
|
1423
|
+
app.add(new X86Test_AllocIfElse3());
|
1424
|
+
}
|
1425
|
+
|
1426
|
+
virtual void compile(x86::Compiler& cc) {
|
1427
|
+
x86::Gp v1 = cc.newInt32("v1");
|
1428
|
+
x86::Gp v2 = cc.newInt32("v2");
|
1429
|
+
x86::Gp counter = cc.newInt32("counter");
|
1430
|
+
|
1431
|
+
Label L_1 = cc.newLabel();
|
1432
|
+
Label L_Loop = cc.newLabel();
|
1433
|
+
Label L_Exit = cc.newLabel();
|
1434
|
+
|
1435
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
1436
|
+
funcNode->setArg(0, v1);
|
1437
|
+
funcNode->setArg(1, v2);
|
1438
|
+
|
1439
|
+
cc.cmp(v1, v2);
|
1440
|
+
cc.jg(L_1);
|
1441
|
+
|
1442
|
+
cc.mov(counter, 0);
|
1443
|
+
|
1444
|
+
cc.bind(L_Loop);
|
1445
|
+
cc.mov(v1, counter);
|
1446
|
+
|
1447
|
+
cc.inc(counter);
|
1448
|
+
cc.cmp(counter, 1);
|
1449
|
+
cc.jle(L_Loop);
|
1450
|
+
cc.jmp(L_Exit);
|
1451
|
+
|
1452
|
+
cc.bind(L_1);
|
1453
|
+
cc.mov(v1, 2);
|
1454
|
+
|
1455
|
+
cc.bind(L_Exit);
|
1456
|
+
cc.ret(v1);
|
1457
|
+
cc.endFunc();
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1461
|
+
typedef int (*Func)(int, int);
|
1462
|
+
Func func = ptr_as_func<Func>(_func);
|
1463
|
+
|
1464
|
+
int a = func(0, 1);
|
1465
|
+
int b = func(1, 0);
|
1466
|
+
|
1467
|
+
result.appendFormat("ret={%d, %d}", a, b);
|
1468
|
+
expect.appendFormat("ret={%d, %d}", 1, 2);
|
1469
|
+
|
1470
|
+
return result == expect;
|
1471
|
+
}
|
1472
|
+
};
|
1473
|
+
|
1474
|
+
// x86::Compiler - X86Test_AllocIfElse4
|
1475
|
+
// ====================================
|
1476
|
+
|
1477
|
+
class X86Test_AllocIfElse4 : public X86TestCase {
|
1478
|
+
public:
|
1479
|
+
X86Test_AllocIfElse4() : X86TestCase("AllocIfElse4") {}
|
1480
|
+
|
1481
|
+
static void add(TestApp& app) {
|
1482
|
+
app.add(new X86Test_AllocIfElse4());
|
1483
|
+
}
|
1484
|
+
|
1485
|
+
virtual void compile(x86::Compiler& cc) {
|
1486
|
+
x86::Gp v1 = cc.newInt32("v1");
|
1487
|
+
x86::Gp v2 = cc.newInt32("v2");
|
1488
|
+
x86::Gp counter = cc.newInt32("counter");
|
1489
|
+
|
1490
|
+
Label L_1 = cc.newLabel();
|
1491
|
+
Label L_Loop1 = cc.newLabel();
|
1492
|
+
Label L_Loop2 = cc.newLabel();
|
1493
|
+
Label L_Exit = cc.newLabel();
|
1494
|
+
|
1495
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
1496
|
+
funcNode->setArg(0, v1);
|
1497
|
+
funcNode->setArg(1, v2);
|
1498
|
+
|
1499
|
+
cc.mov(counter, 0);
|
1500
|
+
cc.cmp(v1, v2);
|
1501
|
+
cc.jg(L_1);
|
1502
|
+
|
1503
|
+
cc.bind(L_Loop1);
|
1504
|
+
cc.mov(v1, counter);
|
1505
|
+
|
1506
|
+
cc.inc(counter);
|
1507
|
+
cc.cmp(counter, 1);
|
1508
|
+
cc.jle(L_Loop1);
|
1509
|
+
cc.jmp(L_Exit);
|
1510
|
+
|
1511
|
+
cc.bind(L_1);
|
1512
|
+
cc.bind(L_Loop2);
|
1513
|
+
cc.mov(v1, counter);
|
1514
|
+
cc.inc(counter);
|
1515
|
+
cc.cmp(counter, 2);
|
1516
|
+
cc.jle(L_Loop2);
|
1517
|
+
|
1518
|
+
cc.bind(L_Exit);
|
1519
|
+
cc.ret(v1);
|
1520
|
+
cc.endFunc();
|
1521
|
+
}
|
1522
|
+
|
1523
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1524
|
+
typedef int (*Func)(int, int);
|
1525
|
+
Func func = ptr_as_func<Func>(_func);
|
1526
|
+
|
1527
|
+
int a = func(0, 1);
|
1528
|
+
int b = func(1, 0);
|
1529
|
+
|
1530
|
+
result.appendFormat("ret={%d, %d}", a, b);
|
1531
|
+
expect.appendFormat("ret={%d, %d}", 1, 2);
|
1532
|
+
|
1533
|
+
return result == expect;
|
1534
|
+
}
|
1535
|
+
};
|
1536
|
+
|
1537
|
+
// x86::Compiler - X86Test_AllocInt8
|
1538
|
+
// =================================
|
1539
|
+
|
1540
|
+
class X86Test_AllocInt8 : public X86TestCase {
|
1541
|
+
public:
|
1542
|
+
X86Test_AllocInt8() : X86TestCase("AllocInt8") {}
|
1543
|
+
|
1544
|
+
static void add(TestApp& app) {
|
1545
|
+
app.add(new X86Test_AllocInt8());
|
1546
|
+
}
|
1547
|
+
|
1548
|
+
virtual void compile(x86::Compiler& cc) {
|
1549
|
+
x86::Gp x = cc.newInt8("x");
|
1550
|
+
x86::Gp y = cc.newInt32("y");
|
1551
|
+
|
1552
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, char>(CallConvId::kHost));
|
1553
|
+
funcNode->setArg(0, x);
|
1554
|
+
|
1555
|
+
cc.movsx(y, x);
|
1556
|
+
|
1557
|
+
cc.ret(y);
|
1558
|
+
cc.endFunc();
|
1559
|
+
}
|
1560
|
+
|
1561
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1562
|
+
typedef int (*Func)(char);
|
1563
|
+
Func func = ptr_as_func<Func>(_func);
|
1564
|
+
|
1565
|
+
int resultRet = func(-13);
|
1566
|
+
int expectRet = -13;
|
1567
|
+
|
1568
|
+
result.assignFormat("ret=%d", resultRet);
|
1569
|
+
expect.assignFormat("ret=%d", expectRet);
|
1570
|
+
|
1571
|
+
return result == expect;
|
1572
|
+
}
|
1573
|
+
};
|
1574
|
+
|
1575
|
+
// x86::Compiler - X86Test_AllocUnhandledArg
|
1576
|
+
// =========================================
|
1577
|
+
|
1578
|
+
class X86Test_AllocUnhandledArg : public X86TestCase {
|
1579
|
+
public:
|
1580
|
+
X86Test_AllocUnhandledArg() : X86TestCase("AllocUnhandledArg") {}
|
1581
|
+
|
1582
|
+
static void add(TestApp& app) {
|
1583
|
+
app.add(new X86Test_AllocUnhandledArg());
|
1584
|
+
}
|
1585
|
+
|
1586
|
+
virtual void compile(x86::Compiler& cc) {
|
1587
|
+
x86::Gp x = cc.newInt32("x");
|
1588
|
+
|
1589
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
1590
|
+
funcNode->setArg(2, x);
|
1591
|
+
|
1592
|
+
cc.ret(x);
|
1593
|
+
cc.endFunc();
|
1594
|
+
}
|
1595
|
+
|
1596
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1597
|
+
typedef int (*Func)(int, int, int);
|
1598
|
+
Func func = ptr_as_func<Func>(_func);
|
1599
|
+
|
1600
|
+
int resultRet = func(42, 155, 199);
|
1601
|
+
int expectRet = 199;
|
1602
|
+
|
1603
|
+
result.assignFormat("ret={%d}", resultRet);
|
1604
|
+
expect.assignFormat("ret={%d}", expectRet);
|
1605
|
+
|
1606
|
+
return result == expect;
|
1607
|
+
}
|
1608
|
+
};
|
1609
|
+
|
1610
|
+
// x86::Compiler - X86Test_AllocArgsIntPtr
|
1611
|
+
// =======================================
|
1612
|
+
|
1613
|
+
class X86Test_AllocArgsIntPtr : public X86TestCase {
|
1614
|
+
public:
|
1615
|
+
X86Test_AllocArgsIntPtr() : X86TestCase("AllocArgsIntPtr") {}
|
1616
|
+
|
1617
|
+
static void add(TestApp& app) {
|
1618
|
+
app.add(new X86Test_AllocArgsIntPtr());
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
virtual void compile(x86::Compiler& cc) {
|
1622
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, void*, void*, void*, void*, void*, void*, void*>(CallConvId::kHost));
|
1623
|
+
x86::Gp var[8];
|
1624
|
+
|
1625
|
+
for (uint32_t i = 0; i < 8; i++) {
|
1626
|
+
var[i] = cc.newIntPtr("var%u", i);
|
1627
|
+
funcNode->setArg(i, var[i]);
|
1628
|
+
}
|
1629
|
+
|
1630
|
+
for (uint32_t i = 0; i < 8; i++) {
|
1631
|
+
cc.add(var[i], int(i + 1));
|
1632
|
+
}
|
1633
|
+
|
1634
|
+
// Move some data into buffer provided by arguments so we can verify if it
|
1635
|
+
// really works without looking into assembler output.
|
1636
|
+
for (uint32_t i = 0; i < 8; i++) {
|
1637
|
+
cc.add(x86::byte_ptr(var[i]), int(i + 1));
|
1638
|
+
}
|
1639
|
+
|
1640
|
+
cc.endFunc();
|
1641
|
+
}
|
1642
|
+
|
1643
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1644
|
+
typedef void (*Func)(void*, void*, void*, void*, void*, void*, void*, void*);
|
1645
|
+
Func func = ptr_as_func<Func>(_func);
|
1646
|
+
|
1647
|
+
uint8_t resultBuf[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
1648
|
+
uint8_t expectBuf[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
1649
|
+
|
1650
|
+
func(resultBuf, resultBuf, resultBuf, resultBuf,
|
1651
|
+
resultBuf, resultBuf, resultBuf, resultBuf);
|
1652
|
+
|
1653
|
+
result.assignFormat("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
|
1654
|
+
resultBuf[0], resultBuf[1], resultBuf[2], resultBuf[3],
|
1655
|
+
resultBuf[4], resultBuf[5], resultBuf[6], resultBuf[7],
|
1656
|
+
resultBuf[8]);
|
1657
|
+
expect.assignFormat("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
|
1658
|
+
expectBuf[0], expectBuf[1], expectBuf[2], expectBuf[3],
|
1659
|
+
expectBuf[4], expectBuf[5], expectBuf[6], expectBuf[7],
|
1660
|
+
expectBuf[8]);
|
1661
|
+
|
1662
|
+
return result == expect;
|
1663
|
+
}
|
1664
|
+
};
|
1665
|
+
|
1666
|
+
// x86::Compiler - X86Test_AllocArgsFloat
|
1667
|
+
// ======================================
|
1668
|
+
|
1669
|
+
class X86Test_AllocArgsFloat : public X86TestCase {
|
1670
|
+
public:
|
1671
|
+
X86Test_AllocArgsFloat() : X86TestCase("AllocArgsFloat") {}
|
1672
|
+
|
1673
|
+
static void add(TestApp& app) {
|
1674
|
+
app.add(new X86Test_AllocArgsFloat());
|
1675
|
+
}
|
1676
|
+
|
1677
|
+
virtual void compile(x86::Compiler& cc) {
|
1678
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, float, float, float, float, float, float, float, void*>(CallConvId::kHost));
|
1679
|
+
|
1680
|
+
x86::Gp p = cc.newIntPtr("p");
|
1681
|
+
x86::Xmm xv[7];
|
1682
|
+
|
1683
|
+
for (uint32_t i = 0; i < 7; i++) {
|
1684
|
+
xv[i] = cc.newXmmSs("xv%u", i);
|
1685
|
+
funcNode->setArg(i, xv[i]);
|
1686
|
+
}
|
1687
|
+
|
1688
|
+
funcNode->setArg(7, p);
|
1689
|
+
|
1690
|
+
cc.addss(xv[0], xv[1]);
|
1691
|
+
cc.addss(xv[0], xv[2]);
|
1692
|
+
cc.addss(xv[0], xv[3]);
|
1693
|
+
cc.addss(xv[0], xv[4]);
|
1694
|
+
cc.addss(xv[0], xv[5]);
|
1695
|
+
cc.addss(xv[0], xv[6]);
|
1696
|
+
|
1697
|
+
cc.movss(x86::ptr(p), xv[0]);
|
1698
|
+
cc.endFunc();
|
1699
|
+
}
|
1700
|
+
|
1701
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1702
|
+
typedef void (*Func)(float, float, float, float, float, float, float, float*);
|
1703
|
+
Func func = ptr_as_func<Func>(_func);
|
1704
|
+
|
1705
|
+
float resultRet;
|
1706
|
+
float expectRet = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f;
|
1707
|
+
|
1708
|
+
func(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, &resultRet);
|
1709
|
+
|
1710
|
+
result.assignFormat("ret={%g}", resultRet);
|
1711
|
+
expect.assignFormat("ret={%g}", expectRet);
|
1712
|
+
|
1713
|
+
return resultRet == expectRet;
|
1714
|
+
}
|
1715
|
+
};
|
1716
|
+
|
1717
|
+
// x86::Compiler - X86Test_AllocArgsDouble
|
1718
|
+
// =======================================
|
1719
|
+
|
1720
|
+
class X86Test_AllocArgsDouble : public X86TestCase {
|
1721
|
+
public:
|
1722
|
+
X86Test_AllocArgsDouble() : X86TestCase("AllocArgsDouble") {}
|
1723
|
+
|
1724
|
+
static void add(TestApp& app) {
|
1725
|
+
app.add(new X86Test_AllocArgsDouble());
|
1726
|
+
}
|
1727
|
+
|
1728
|
+
virtual void compile(x86::Compiler& cc) {
|
1729
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, double, double, double, double, double, double, double, void*>(CallConvId::kHost));
|
1730
|
+
|
1731
|
+
x86::Gp p = cc.newIntPtr("p");
|
1732
|
+
x86::Xmm xv[7];
|
1733
|
+
|
1734
|
+
for (uint32_t i = 0; i < 7; i++) {
|
1735
|
+
xv[i] = cc.newXmmSd("xv%u", i);
|
1736
|
+
funcNode->setArg(i, xv[i]);
|
1737
|
+
}
|
1738
|
+
|
1739
|
+
funcNode->setArg(7, p);
|
1740
|
+
|
1741
|
+
cc.addsd(xv[0], xv[1]);
|
1742
|
+
cc.addsd(xv[0], xv[2]);
|
1743
|
+
cc.addsd(xv[0], xv[3]);
|
1744
|
+
cc.addsd(xv[0], xv[4]);
|
1745
|
+
cc.addsd(xv[0], xv[5]);
|
1746
|
+
cc.addsd(xv[0], xv[6]);
|
1747
|
+
|
1748
|
+
cc.movsd(x86::ptr(p), xv[0]);
|
1749
|
+
cc.endFunc();
|
1750
|
+
}
|
1751
|
+
|
1752
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1753
|
+
typedef void (*Func)(double, double, double, double, double, double, double, double*);
|
1754
|
+
Func func = ptr_as_func<Func>(_func);
|
1755
|
+
|
1756
|
+
double resultRet;
|
1757
|
+
double expectRet = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0;
|
1758
|
+
|
1759
|
+
func(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, &resultRet);
|
1760
|
+
|
1761
|
+
result.assignFormat("ret={%g}", resultRet);
|
1762
|
+
expect.assignFormat("ret={%g}", expectRet);
|
1763
|
+
|
1764
|
+
return resultRet == expectRet;
|
1765
|
+
}
|
1766
|
+
};
|
1767
|
+
|
1768
|
+
// x86::Compiler - X86Test_AllocArgsVec
|
1769
|
+
// ====================================
|
1770
|
+
|
1771
|
+
class X86Test_AllocArgsVec : public X86TestCase {
|
1772
|
+
public:
|
1773
|
+
X86Test_AllocArgsVec() : X86TestCase("AllocArgsVec") {}
|
1774
|
+
|
1775
|
+
static void add(TestApp& app) {
|
1776
|
+
// Not supported on Windows.
|
1777
|
+
#ifndef _WIN32
|
1778
|
+
app.add(new X86Test_AllocArgsVec());
|
1779
|
+
#else
|
1780
|
+
DebugUtils::unused(app);
|
1781
|
+
#endif
|
1782
|
+
}
|
1783
|
+
|
1784
|
+
virtual void compile(x86::Compiler& cc) {
|
1785
|
+
x86::Xmm a = cc.newXmm("aXmm");
|
1786
|
+
x86::Xmm b = cc.newXmm("bXmm");
|
1787
|
+
|
1788
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm>(CallConvId::kHost));
|
1789
|
+
funcNode->setArg(0, a);
|
1790
|
+
funcNode->setArg(1, b);
|
1791
|
+
|
1792
|
+
cc.paddb(a, b);
|
1793
|
+
cc.ret(a);
|
1794
|
+
|
1795
|
+
cc.endFunc();
|
1796
|
+
}
|
1797
|
+
|
1798
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1799
|
+
typedef __m128i (*Func)(__m128i, __m128i);
|
1800
|
+
Func func = ptr_as_func<Func>(_func);
|
1801
|
+
|
1802
|
+
uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
1803
|
+
uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
|
1804
|
+
|
1805
|
+
uint8_t rData[16];
|
1806
|
+
uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
|
1807
|
+
|
1808
|
+
__m128i aVec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(aData));
|
1809
|
+
__m128i bVec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(bData));
|
1810
|
+
|
1811
|
+
__m128i rVec = func(aVec, bVec);
|
1812
|
+
_mm_storeu_si128(reinterpret_cast<__m128i*>(rData), rVec);
|
1813
|
+
|
1814
|
+
result.appendHex(rData, 16);
|
1815
|
+
expect.appendHex(eData, 16);
|
1816
|
+
|
1817
|
+
return result == expect;
|
1818
|
+
}
|
1819
|
+
};
|
1820
|
+
|
1821
|
+
// x86::Compiler - X86Test_AllocRetFloat1
|
1822
|
+
// ======================================
|
1823
|
+
|
1824
|
+
class X86Test_AllocRetFloat1 : public X86TestCase {
|
1825
|
+
public:
|
1826
|
+
X86Test_AllocRetFloat1() : X86TestCase("AllocRetFloat1") {}
|
1827
|
+
|
1828
|
+
static void add(TestApp& app) {
|
1829
|
+
app.add(new X86Test_AllocRetFloat1());
|
1830
|
+
}
|
1831
|
+
|
1832
|
+
virtual void compile(x86::Compiler& cc) {
|
1833
|
+
x86::Xmm x = cc.newXmmSs("x");
|
1834
|
+
|
1835
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float>(CallConvId::kHost));
|
1836
|
+
funcNode->setArg(0, x);
|
1837
|
+
|
1838
|
+
cc.ret(x);
|
1839
|
+
cc.endFunc();
|
1840
|
+
}
|
1841
|
+
|
1842
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1843
|
+
typedef float (*Func)(float);
|
1844
|
+
Func func = ptr_as_func<Func>(_func);
|
1845
|
+
|
1846
|
+
float resultRet = func(42.0f);
|
1847
|
+
float expectRet = 42.0f;
|
1848
|
+
|
1849
|
+
result.assignFormat("ret={%g}", resultRet);
|
1850
|
+
expect.assignFormat("ret={%g}", expectRet);
|
1851
|
+
|
1852
|
+
return resultRet == expectRet;
|
1853
|
+
}
|
1854
|
+
};
|
1855
|
+
|
1856
|
+
// x86::Compiler - X86Test_AllocRetFloat2
|
1857
|
+
// ======================================
|
1858
|
+
|
1859
|
+
class X86Test_AllocRetFloat2 : public X86TestCase {
|
1860
|
+
public:
|
1861
|
+
X86Test_AllocRetFloat2() : X86TestCase("AllocRetFloat2") {}
|
1862
|
+
|
1863
|
+
static void add(TestApp& app) {
|
1864
|
+
app.add(new X86Test_AllocRetFloat2());
|
1865
|
+
}
|
1866
|
+
|
1867
|
+
virtual void compile(x86::Compiler& cc) {
|
1868
|
+
x86::Xmm x = cc.newXmmSs("x");
|
1869
|
+
x86::Xmm y = cc.newXmmSs("y");
|
1870
|
+
|
1871
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float>(CallConvId::kHost));
|
1872
|
+
funcNode->setArg(0, x);
|
1873
|
+
funcNode->setArg(1, y);
|
1874
|
+
|
1875
|
+
cc.addss(x, y);
|
1876
|
+
cc.ret(x);
|
1877
|
+
|
1878
|
+
cc.endFunc();
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1882
|
+
typedef float (*Func)(float, float);
|
1883
|
+
Func func = ptr_as_func<Func>(_func);
|
1884
|
+
|
1885
|
+
float resultRet = func(1.0f, 2.0f);
|
1886
|
+
float expectRet = 1.0f + 2.0f;
|
1887
|
+
|
1888
|
+
result.assignFormat("ret={%g}", resultRet);
|
1889
|
+
expect.assignFormat("ret={%g}", expectRet);
|
1890
|
+
|
1891
|
+
return resultRet == expectRet;
|
1892
|
+
}
|
1893
|
+
};
|
1894
|
+
|
1895
|
+
// x86::Compiler - X86Test_AllocRetDouble1
|
1896
|
+
// =======================================
|
1897
|
+
|
1898
|
+
class X86Test_AllocRetDouble1 : public X86TestCase {
|
1899
|
+
public:
|
1900
|
+
X86Test_AllocRetDouble1() : X86TestCase("AllocRetDouble1") {}
|
1901
|
+
|
1902
|
+
static void add(TestApp& app) {
|
1903
|
+
app.add(new X86Test_AllocRetDouble1());
|
1904
|
+
}
|
1905
|
+
|
1906
|
+
virtual void compile(x86::Compiler& cc) {
|
1907
|
+
x86::Xmm x = cc.newXmmSd("x");
|
1908
|
+
|
1909
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double>(CallConvId::kHost));
|
1910
|
+
funcNode->setArg(0, x);
|
1911
|
+
|
1912
|
+
cc.ret(x);
|
1913
|
+
cc.endFunc();
|
1914
|
+
}
|
1915
|
+
|
1916
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1917
|
+
typedef double (*Func)(double);
|
1918
|
+
Func func = ptr_as_func<Func>(_func);
|
1919
|
+
|
1920
|
+
double resultRet = func(42.0);
|
1921
|
+
double expectRet = 42.0;
|
1922
|
+
|
1923
|
+
result.assignFormat("ret={%g}", resultRet);
|
1924
|
+
expect.assignFormat("ret={%g}", expectRet);
|
1925
|
+
|
1926
|
+
return resultRet == expectRet;
|
1927
|
+
}
|
1928
|
+
};
|
1929
|
+
|
1930
|
+
// x86::Compiler - X86Test_AllocRetDouble2
|
1931
|
+
// =======================================
|
1932
|
+
|
1933
|
+
class X86Test_AllocRetDouble2 : public X86TestCase {
|
1934
|
+
public:
|
1935
|
+
X86Test_AllocRetDouble2() : X86TestCase("AllocRetDouble2") {}
|
1936
|
+
|
1937
|
+
static void add(TestApp& app) {
|
1938
|
+
app.add(new X86Test_AllocRetDouble2());
|
1939
|
+
}
|
1940
|
+
|
1941
|
+
virtual void compile(x86::Compiler& cc) {
|
1942
|
+
x86::Xmm x = cc.newXmmSd("x");
|
1943
|
+
x86::Xmm y = cc.newXmmSd("y");
|
1944
|
+
|
1945
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>(CallConvId::kHost));
|
1946
|
+
funcNode->setArg(0, x);
|
1947
|
+
funcNode->setArg(1, y);
|
1948
|
+
|
1949
|
+
cc.addsd(x, y);
|
1950
|
+
cc.ret(x);
|
1951
|
+
|
1952
|
+
cc.endFunc();
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
1956
|
+
typedef double (*Func)(double, double);
|
1957
|
+
Func func = ptr_as_func<Func>(_func);
|
1958
|
+
|
1959
|
+
double resultRet = func(1.0, 2.0);
|
1960
|
+
double expectRet = 1.0 + 2.0;
|
1961
|
+
|
1962
|
+
result.assignFormat("ret={%g}", resultRet);
|
1963
|
+
expect.assignFormat("ret={%g}", expectRet);
|
1964
|
+
|
1965
|
+
return resultRet == expectRet;
|
1966
|
+
}
|
1967
|
+
};
|
1968
|
+
|
1969
|
+
// x86::Compiler - X86Test_AllocStack
|
1970
|
+
// ==================================
|
1971
|
+
|
1972
|
+
class X86Test_AllocStack : public X86TestCase {
|
1973
|
+
public:
|
1974
|
+
X86Test_AllocStack() : X86TestCase("AllocStack") {}
|
1975
|
+
|
1976
|
+
enum { kSize = 256 };
|
1977
|
+
|
1978
|
+
static void add(TestApp& app) {
|
1979
|
+
app.add(new X86Test_AllocStack());
|
1980
|
+
}
|
1981
|
+
|
1982
|
+
virtual void compile(x86::Compiler& cc) {
|
1983
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
1984
|
+
|
1985
|
+
x86::Mem stack = cc.newStack(kSize, 1);
|
1986
|
+
stack.setSize(1);
|
1987
|
+
|
1988
|
+
x86::Gp i = cc.newIntPtr("i");
|
1989
|
+
x86::Gp a = cc.newInt32("a");
|
1990
|
+
x86::Gp b = cc.newInt32("b");
|
1991
|
+
|
1992
|
+
Label L_1 = cc.newLabel();
|
1993
|
+
Label L_2 = cc.newLabel();
|
1994
|
+
|
1995
|
+
// Fill stack by sequence [0, 1, 2, 3 ... 255].
|
1996
|
+
cc.xor_(i, i);
|
1997
|
+
|
1998
|
+
x86::Mem stackWithIndex = stack.clone();
|
1999
|
+
stackWithIndex.setIndex(i, 0);
|
2000
|
+
|
2001
|
+
cc.bind(L_1);
|
2002
|
+
cc.mov(stackWithIndex, i.r8());
|
2003
|
+
cc.inc(i);
|
2004
|
+
cc.cmp(i, 255);
|
2005
|
+
cc.jle(L_1);
|
2006
|
+
|
2007
|
+
// Sum sequence in stack.
|
2008
|
+
cc.xor_(i, i);
|
2009
|
+
cc.xor_(a, a);
|
2010
|
+
|
2011
|
+
cc.bind(L_2);
|
2012
|
+
cc.movzx(b, stackWithIndex);
|
2013
|
+
cc.add(a, b);
|
2014
|
+
cc.inc(i);
|
2015
|
+
cc.cmp(i, 255);
|
2016
|
+
cc.jle(L_2);
|
2017
|
+
|
2018
|
+
cc.ret(a);
|
2019
|
+
cc.endFunc();
|
2020
|
+
}
|
2021
|
+
|
2022
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2023
|
+
typedef int (*Func)(void);
|
2024
|
+
Func func = ptr_as_func<Func>(_func);
|
2025
|
+
|
2026
|
+
int resultRet = func();
|
2027
|
+
int expectRet = 32640;
|
2028
|
+
|
2029
|
+
result.assignInt(resultRet);
|
2030
|
+
expect.assignInt(expectRet);
|
2031
|
+
|
2032
|
+
return resultRet == expectRet;
|
2033
|
+
}
|
2034
|
+
};
|
2035
|
+
|
2036
|
+
// x86::Compiler - X86Test_AllocMemcpy
|
2037
|
+
// ===================================
|
2038
|
+
|
2039
|
+
class X86Test_AllocMemcpy : public X86TestCase {
|
2040
|
+
public:
|
2041
|
+
X86Test_AllocMemcpy() : X86TestCase("AllocMemcpy") {}
|
2042
|
+
|
2043
|
+
enum { kCount = 32 };
|
2044
|
+
|
2045
|
+
static void add(TestApp& app) {
|
2046
|
+
app.add(new X86Test_AllocMemcpy());
|
2047
|
+
}
|
2048
|
+
|
2049
|
+
virtual void compile(x86::Compiler& cc) {
|
2050
|
+
x86::Gp dst = cc.newIntPtr("dst");
|
2051
|
+
x86::Gp src = cc.newIntPtr("src");
|
2052
|
+
x86::Gp cnt = cc.newUIntPtr("cnt");
|
2053
|
+
|
2054
|
+
Label L_Loop = cc.newLabel(); // Create base labels we use
|
2055
|
+
Label L_Exit = cc.newLabel(); // in our function.
|
2056
|
+
|
2057
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, uint32_t*, const uint32_t*, size_t>(CallConvId::kHost));
|
2058
|
+
funcNode->setArg(0, dst);
|
2059
|
+
funcNode->setArg(1, src);
|
2060
|
+
funcNode->setArg(2, cnt);
|
2061
|
+
|
2062
|
+
cc.test(cnt, cnt); // Exit if the size is zero.
|
2063
|
+
cc.jz(L_Exit);
|
2064
|
+
|
2065
|
+
cc.bind(L_Loop); // Bind the loop label here.
|
2066
|
+
|
2067
|
+
x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes).
|
2068
|
+
cc.mov(tmp, x86::dword_ptr(src));
|
2069
|
+
cc.mov(x86::dword_ptr(dst), tmp);
|
2070
|
+
|
2071
|
+
cc.add(src, 4); // Increment dst/src pointers.
|
2072
|
+
cc.add(dst, 4);
|
2073
|
+
|
2074
|
+
cc.dec(cnt); // Loop until cnt isn't zero.
|
2075
|
+
cc.jnz(L_Loop);
|
2076
|
+
|
2077
|
+
cc.bind(L_Exit); // Bind the exit label here.
|
2078
|
+
cc.endFunc(); // End of function.
|
2079
|
+
}
|
2080
|
+
|
2081
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2082
|
+
typedef void (*Func)(uint32_t*, const uint32_t*, size_t);
|
2083
|
+
Func func = ptr_as_func<Func>(_func);
|
2084
|
+
|
2085
|
+
uint32_t i;
|
2086
|
+
|
2087
|
+
uint32_t dstBuffer[kCount];
|
2088
|
+
uint32_t srcBuffer[kCount];
|
2089
|
+
|
2090
|
+
for (i = 0; i < kCount; i++) {
|
2091
|
+
dstBuffer[i] = 0;
|
2092
|
+
srcBuffer[i] = i;
|
2093
|
+
}
|
2094
|
+
|
2095
|
+
func(dstBuffer, srcBuffer, kCount);
|
2096
|
+
|
2097
|
+
result.assign("buf={");
|
2098
|
+
expect.assign("buf={");
|
2099
|
+
|
2100
|
+
for (i = 0; i < kCount; i++) {
|
2101
|
+
if (i != 0) {
|
2102
|
+
result.append(", ");
|
2103
|
+
expect.append(", ");
|
2104
|
+
}
|
2105
|
+
|
2106
|
+
result.appendFormat("%u", unsigned(dstBuffer[i]));
|
2107
|
+
expect.appendFormat("%u", unsigned(srcBuffer[i]));
|
2108
|
+
}
|
2109
|
+
|
2110
|
+
result.append("}");
|
2111
|
+
expect.append("}");
|
2112
|
+
|
2113
|
+
return result == expect;
|
2114
|
+
}
|
2115
|
+
};
|
2116
|
+
|
2117
|
+
// x86::Compiler - X86Test_AllocExtraBlock
|
2118
|
+
// =======================================
|
2119
|
+
|
2120
|
+
class X86Test_AllocExtraBlock : public X86TestCase {
|
2121
|
+
public:
|
2122
|
+
X86Test_AllocExtraBlock() : X86TestCase("AllocExtraBlock") {}
|
2123
|
+
|
2124
|
+
static void add(TestApp& app) {
|
2125
|
+
app.add(new X86Test_AllocExtraBlock());
|
2126
|
+
}
|
2127
|
+
|
2128
|
+
virtual void compile(x86::Compiler& cc) {
|
2129
|
+
x86::Gp cond = cc.newInt32("cond");
|
2130
|
+
x86::Gp ret = cc.newInt32("ret");
|
2131
|
+
x86::Gp a = cc.newInt32("a");
|
2132
|
+
x86::Gp b = cc.newInt32("b");
|
2133
|
+
|
2134
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
2135
|
+
funcNode->setArg(0, cond);
|
2136
|
+
funcNode->setArg(1, a);
|
2137
|
+
funcNode->setArg(2, b);
|
2138
|
+
|
2139
|
+
Label L_Ret = cc.newLabel();
|
2140
|
+
Label L_Extra = cc.newLabel();
|
2141
|
+
|
2142
|
+
cc.test(cond, cond);
|
2143
|
+
cc.jnz(L_Extra);
|
2144
|
+
|
2145
|
+
cc.mov(ret, a);
|
2146
|
+
cc.add(ret, b);
|
2147
|
+
|
2148
|
+
cc.bind(L_Ret);
|
2149
|
+
cc.ret(ret);
|
2150
|
+
|
2151
|
+
// Emit code sequence at the end of the function.
|
2152
|
+
BaseNode* prevCursor = cc.setCursor(funcNode->endNode()->prev());
|
2153
|
+
cc.bind(L_Extra);
|
2154
|
+
cc.mov(ret, a);
|
2155
|
+
cc.sub(ret, b);
|
2156
|
+
cc.jmp(L_Ret);
|
2157
|
+
cc.setCursor(prevCursor);
|
2158
|
+
|
2159
|
+
cc.endFunc();
|
2160
|
+
}
|
2161
|
+
|
2162
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2163
|
+
typedef int (*Func)(int, int, int);
|
2164
|
+
Func func = ptr_as_func<Func>(_func);
|
2165
|
+
|
2166
|
+
int ret1 = func(0, 4, 5);
|
2167
|
+
int ret2 = func(1, 4, 5);
|
2168
|
+
|
2169
|
+
int exp1 = 4 + 5;
|
2170
|
+
int exp2 = 4 - 5;
|
2171
|
+
|
2172
|
+
result.assignFormat("ret={%d, %d}", ret1, ret2);
|
2173
|
+
expect.assignFormat("ret={%d, %d}", exp1, exp2);
|
2174
|
+
|
2175
|
+
return result == expect;
|
2176
|
+
}
|
2177
|
+
};
|
2178
|
+
|
2179
|
+
// x86::Compiler - X86Test_AllocAlphaBlend
|
2180
|
+
// =======================================
|
2181
|
+
|
2182
|
+
class X86Test_AllocAlphaBlend : public X86TestCase {
|
2183
|
+
public:
|
2184
|
+
X86Test_AllocAlphaBlend() : X86TestCase("AllocAlphaBlend") {}
|
2185
|
+
|
2186
|
+
enum { kCount = 17 };
|
2187
|
+
|
2188
|
+
static void add(TestApp& app) {
|
2189
|
+
app.add(new X86Test_AllocAlphaBlend());
|
2190
|
+
}
|
2191
|
+
|
2192
|
+
static uint32_t blendSrcOver(uint32_t d, uint32_t s) {
|
2193
|
+
uint32_t saInv = ~s >> 24;
|
2194
|
+
|
2195
|
+
uint32_t d_20 = (d ) & 0x00FF00FF;
|
2196
|
+
uint32_t d_31 = (d >> 8) & 0x00FF00FF;
|
2197
|
+
|
2198
|
+
d_20 *= saInv;
|
2199
|
+
d_31 *= saInv;
|
2200
|
+
|
2201
|
+
d_20 = ((d_20 + ((d_20 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u) >> 8;
|
2202
|
+
d_31 = ((d_31 + ((d_31 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u);
|
2203
|
+
|
2204
|
+
return d_20 + d_31 + s;
|
2205
|
+
}
|
2206
|
+
|
2207
|
+
virtual void compile(x86::Compiler& cc) {
|
2208
|
+
asmtest::generateSseAlphaBlend(cc, true);
|
2209
|
+
}
|
2210
|
+
|
2211
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2212
|
+
typedef void (*Func)(void*, const void*, size_t);
|
2213
|
+
Func func = ptr_as_func<Func>(_func);
|
2214
|
+
|
2215
|
+
static const uint32_t dstConstData[] = { 0x00000000, 0x10101010, 0x20100804, 0x30200003, 0x40204040, 0x5000004D, 0x60302E2C, 0x706F6E6D, 0x807F4F2F, 0x90349001, 0xA0010203, 0xB03204AB, 0xC023AFBD, 0xD0D0D0C0, 0xE0AABBCC, 0xFFFFFFFF, 0xF8F4F2F1 };
|
2216
|
+
static const uint32_t srcConstData[] = { 0xE0E0E0E0, 0xA0008080, 0x341F1E1A, 0xFEFEFEFE, 0x80302010, 0x49490A0B, 0x998F7798, 0x00000000, 0x01010101, 0xA0264733, 0xBAB0B1B9, 0xFF000000, 0xDAB0A0C1, 0xE0BACFDA, 0x99887766, 0xFFFFFF80, 0xEE0A5FEC };
|
2217
|
+
|
2218
|
+
uint32_t _dstBuffer[kCount + 3];
|
2219
|
+
uint32_t _srcBuffer[kCount + 3];
|
2220
|
+
|
2221
|
+
// Has to be aligned.
|
2222
|
+
uint32_t* dstBuffer = (uint32_t*)Support::alignUp<intptr_t>((intptr_t)_dstBuffer, 16);
|
2223
|
+
uint32_t* srcBuffer = (uint32_t*)Support::alignUp<intptr_t>((intptr_t)_srcBuffer, 16);
|
2224
|
+
|
2225
|
+
memcpy(dstBuffer, dstConstData, sizeof(dstConstData));
|
2226
|
+
memcpy(srcBuffer, srcConstData, sizeof(srcConstData));
|
2227
|
+
|
2228
|
+
uint32_t i;
|
2229
|
+
uint32_t expBuffer[kCount];
|
2230
|
+
|
2231
|
+
for (i = 0; i < kCount; i++) {
|
2232
|
+
expBuffer[i] = blendSrcOver(dstBuffer[i], srcBuffer[i]);
|
2233
|
+
}
|
2234
|
+
|
2235
|
+
func(dstBuffer, srcBuffer, kCount);
|
2236
|
+
|
2237
|
+
result.assign("buf={");
|
2238
|
+
expect.assign("buf={");
|
2239
|
+
|
2240
|
+
for (i = 0; i < kCount; i++) {
|
2241
|
+
if (i != 0) {
|
2242
|
+
result.append(", ");
|
2243
|
+
expect.append(", ");
|
2244
|
+
}
|
2245
|
+
|
2246
|
+
result.appendFormat("%08X", unsigned(dstBuffer[i]));
|
2247
|
+
expect.appendFormat("%08X", unsigned(expBuffer[i]));
|
2248
|
+
}
|
2249
|
+
|
2250
|
+
result.append("}");
|
2251
|
+
expect.append("}");
|
2252
|
+
|
2253
|
+
return result == expect;
|
2254
|
+
}
|
2255
|
+
};
|
2256
|
+
|
2257
|
+
// x86::Compiler - X86Test_FuncCallBase1
|
2258
|
+
// =====================================
|
2259
|
+
|
2260
|
+
class X86Test_FuncCallBase1 : public X86TestCase {
|
2261
|
+
public:
|
2262
|
+
X86Test_FuncCallBase1() : X86TestCase("FuncCallBase1") {}
|
2263
|
+
|
2264
|
+
static void add(TestApp& app) {
|
2265
|
+
app.add(new X86Test_FuncCallBase1());
|
2266
|
+
}
|
2267
|
+
|
2268
|
+
virtual void compile(x86::Compiler& cc) {
|
2269
|
+
x86::Gp v0 = cc.newInt32("v0");
|
2270
|
+
x86::Gp v1 = cc.newInt32("v1");
|
2271
|
+
x86::Gp v2 = cc.newInt32("v2");
|
2272
|
+
|
2273
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
2274
|
+
funcNode->setArg(0, v0);
|
2275
|
+
funcNode->setArg(1, v1);
|
2276
|
+
funcNode->setArg(2, v2);
|
2277
|
+
|
2278
|
+
// Just do something.
|
2279
|
+
cc.shl(v0, 1);
|
2280
|
+
cc.shl(v1, 1);
|
2281
|
+
cc.shl(v2, 1);
|
2282
|
+
|
2283
|
+
// Call a function.
|
2284
|
+
InvokeNode* invokeNode;
|
2285
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
2286
|
+
invokeNode->setArg(0, v2);
|
2287
|
+
invokeNode->setArg(1, v1);
|
2288
|
+
invokeNode->setArg(2, v0);
|
2289
|
+
invokeNode->setRet(0, v0);
|
2290
|
+
|
2291
|
+
cc.ret(v0);
|
2292
|
+
cc.endFunc();
|
2293
|
+
}
|
2294
|
+
|
2295
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2296
|
+
typedef int (*Func)(int, int, int);
|
2297
|
+
Func func = ptr_as_func<Func>(_func);
|
2298
|
+
|
2299
|
+
int resultRet = func(3, 2, 1);
|
2300
|
+
int expectRet = 36;
|
2301
|
+
|
2302
|
+
result.assignFormat("ret=%d", resultRet);
|
2303
|
+
expect.assignFormat("ret=%d", expectRet);
|
2304
|
+
|
2305
|
+
return resultRet == expectRet;
|
2306
|
+
}
|
2307
|
+
|
2308
|
+
static int calledFunc(int a, int b, int c) { return (a + b) * c; }
|
2309
|
+
};
|
2310
|
+
|
2311
|
+
// x86::Compiler - X86Test_FuncCallBase2
|
2312
|
+
// =====================================
|
2313
|
+
|
2314
|
+
class X86Test_FuncCallBase2 : public X86TestCase {
|
2315
|
+
public:
|
2316
|
+
X86Test_FuncCallBase2() : X86TestCase("FuncCallBase2") {}
|
2317
|
+
|
2318
|
+
enum { kSize = 256 };
|
2319
|
+
|
2320
|
+
static void add(TestApp& app) {
|
2321
|
+
app.add(new X86Test_FuncCallBase2());
|
2322
|
+
}
|
2323
|
+
|
2324
|
+
virtual void compile(x86::Compiler& cc) {
|
2325
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
2326
|
+
|
2327
|
+
const int kTokenSize = 32;
|
2328
|
+
|
2329
|
+
x86::Mem s1 = cc.newStack(kTokenSize, 32);
|
2330
|
+
x86::Mem s2 = cc.newStack(kTokenSize, 32);
|
2331
|
+
|
2332
|
+
x86::Gp p1 = cc.newIntPtr("p1");
|
2333
|
+
x86::Gp p2 = cc.newIntPtr("p2");
|
2334
|
+
|
2335
|
+
x86::Gp ret = cc.newInt32("ret");
|
2336
|
+
Label L_Exit = cc.newLabel();
|
2337
|
+
|
2338
|
+
static const char token[kTokenSize] = "-+:|abcdefghijklmnopqrstuvwxyz|";
|
2339
|
+
InvokeNode* invokeNode;
|
2340
|
+
|
2341
|
+
cc.lea(p1, s1);
|
2342
|
+
cc.lea(p2, s2);
|
2343
|
+
|
2344
|
+
// Try to corrupt the stack if wrongly allocated.
|
2345
|
+
cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConvId::kCDecl));
|
2346
|
+
invokeNode->setArg(0, p1);
|
2347
|
+
invokeNode->setArg(1, imm(token));
|
2348
|
+
invokeNode->setArg(2, imm(kTokenSize));
|
2349
|
+
invokeNode->setRet(0, p1);
|
2350
|
+
|
2351
|
+
cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConvId::kCDecl));
|
2352
|
+
invokeNode->setArg(0, p2);
|
2353
|
+
invokeNode->setArg(1, imm(token));
|
2354
|
+
invokeNode->setArg(2, imm(kTokenSize));
|
2355
|
+
invokeNode->setRet(0, p2);
|
2356
|
+
|
2357
|
+
cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignatureT<int, void*, void*, size_t>(CallConvId::kCDecl));
|
2358
|
+
invokeNode->setArg(0, p1);
|
2359
|
+
invokeNode->setArg(1, p2);
|
2360
|
+
invokeNode->setArg(2, imm(kTokenSize));
|
2361
|
+
invokeNode->setRet(0, ret);
|
2362
|
+
|
2363
|
+
// This should be 0 on success, however, if both `p1` and `p2` were
|
2364
|
+
// allocated in the same address this check will still pass.
|
2365
|
+
cc.cmp(ret, 0);
|
2366
|
+
cc.jnz(L_Exit);
|
2367
|
+
|
2368
|
+
// Checks whether `p1` and `p2` are different (must be).
|
2369
|
+
cc.xor_(ret, ret);
|
2370
|
+
cc.cmp(p1, p2);
|
2371
|
+
cc.setz(ret.r8());
|
2372
|
+
|
2373
|
+
cc.bind(L_Exit);
|
2374
|
+
cc.ret(ret);
|
2375
|
+
cc.endFunc();
|
2376
|
+
}
|
2377
|
+
|
2378
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2379
|
+
typedef int (*Func)(void);
|
2380
|
+
Func func = ptr_as_func<Func>(_func);
|
2381
|
+
|
2382
|
+
int resultRet = func();
|
2383
|
+
int expectRet = 0; // Must be zero, stack addresses must be different.
|
2384
|
+
|
2385
|
+
result.assignInt(resultRet);
|
2386
|
+
expect.assignInt(expectRet);
|
2387
|
+
|
2388
|
+
return resultRet == expectRet;
|
2389
|
+
}
|
2390
|
+
};
|
2391
|
+
|
2392
|
+
// x86::Compiler - X86Test_FuncCallStd
|
2393
|
+
// ===================================
|
2394
|
+
|
2395
|
+
class X86Test_FuncCallStd : public X86TestCase {
|
2396
|
+
public:
|
2397
|
+
X86Test_FuncCallStd() : X86TestCase("FuncCallStd") {}
|
2398
|
+
|
2399
|
+
static void add(TestApp& app) {
|
2400
|
+
app.add(new X86Test_FuncCallStd());
|
2401
|
+
}
|
2402
|
+
|
2403
|
+
virtual void compile(x86::Compiler& cc) {
|
2404
|
+
x86::Gp x = cc.newInt32("x");
|
2405
|
+
x86::Gp y = cc.newInt32("y");
|
2406
|
+
x86::Gp z = cc.newInt32("z");
|
2407
|
+
|
2408
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
2409
|
+
funcNode->setArg(0, x);
|
2410
|
+
funcNode->setArg(1, y);
|
2411
|
+
funcNode->setArg(2, z);
|
2412
|
+
|
2413
|
+
InvokeNode* invokeNode;
|
2414
|
+
cc.invoke(&invokeNode,
|
2415
|
+
imm((void*)calledFunc),
|
2416
|
+
FuncSignatureT<int, int, int, int>(CallConvId::kStdCall));
|
2417
|
+
invokeNode->setArg(0, x);
|
2418
|
+
invokeNode->setArg(1, y);
|
2419
|
+
invokeNode->setArg(2, z);
|
2420
|
+
invokeNode->setRet(0, x);
|
2421
|
+
|
2422
|
+
cc.ret(x);
|
2423
|
+
cc.endFunc();
|
2424
|
+
}
|
2425
|
+
|
2426
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2427
|
+
typedef int (*Func)(int, int, int);
|
2428
|
+
Func func = ptr_as_func<Func>(_func);
|
2429
|
+
|
2430
|
+
int resultRet = func(1, 42, 3);
|
2431
|
+
int expectRet = calledFunc(1, 42, 3);
|
2432
|
+
|
2433
|
+
result.assignFormat("ret=%d", resultRet);
|
2434
|
+
expect.assignFormat("ret=%d", expectRet);
|
2435
|
+
|
2436
|
+
return resultRet == expectRet;
|
2437
|
+
}
|
2438
|
+
|
2439
|
+
// STDCALL function that is called inside the generated one.
|
2440
|
+
static int ASMJIT_STDCALL calledFunc(int a, int b, int c) noexcept {
|
2441
|
+
return (a + b) * c;
|
2442
|
+
}
|
2443
|
+
};
|
2444
|
+
|
2445
|
+
// x86::Compiler - X86Test_FuncCallFast
|
2446
|
+
// ====================================
|
2447
|
+
|
2448
|
+
class X86Test_FuncCallFast : public X86TestCase {
|
2449
|
+
public:
|
2450
|
+
X86Test_FuncCallFast() : X86TestCase("FuncCallFast") {}
|
2451
|
+
|
2452
|
+
static void add(TestApp& app) {
|
2453
|
+
app.add(new X86Test_FuncCallFast());
|
2454
|
+
}
|
2455
|
+
|
2456
|
+
virtual void compile(x86::Compiler& cc) {
|
2457
|
+
x86::Gp var = cc.newInt32("var");
|
2458
|
+
|
2459
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost));
|
2460
|
+
funcNode->setArg(0, var);
|
2461
|
+
|
2462
|
+
InvokeNode* invokeNode;
|
2463
|
+
|
2464
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConvId::kFastCall));
|
2465
|
+
invokeNode->setArg(0, var);
|
2466
|
+
invokeNode->setRet(0, var);
|
2467
|
+
|
2468
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConvId::kFastCall));
|
2469
|
+
invokeNode->setArg(0, var);
|
2470
|
+
invokeNode->setRet(0, var);
|
2471
|
+
|
2472
|
+
cc.ret(var);
|
2473
|
+
cc.endFunc();
|
2474
|
+
}
|
2475
|
+
|
2476
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2477
|
+
typedef int (*Func)(int);
|
2478
|
+
Func func = ptr_as_func<Func>(_func);
|
2479
|
+
|
2480
|
+
int resultRet = func(9);
|
2481
|
+
int expectRet = (9 * 9) * (9 * 9);
|
2482
|
+
|
2483
|
+
result.assignFormat("ret=%d", resultRet);
|
2484
|
+
expect.assignFormat("ret=%d", expectRet);
|
2485
|
+
|
2486
|
+
return resultRet == expectRet;
|
2487
|
+
}
|
2488
|
+
|
2489
|
+
// FASTCALL function that is called inside the generated one.
|
2490
|
+
static int ASMJIT_FASTCALL calledFunc(int a) noexcept {
|
2491
|
+
return a * a;
|
2492
|
+
}
|
2493
|
+
};
|
2494
|
+
|
2495
|
+
// x86::Compiler - X86Test_FuncCallSIMD
|
2496
|
+
// ====================================
|
2497
|
+
|
2498
|
+
class X86Test_FuncCallSIMD : public X86TestCase {
|
2499
|
+
public:
|
2500
|
+
bool _useVectorCall;
|
2501
|
+
|
2502
|
+
X86Test_FuncCallSIMD(bool useVectorCall)
|
2503
|
+
: X86TestCase(),
|
2504
|
+
_useVectorCall(useVectorCall) {
|
2505
|
+
_name.assignFormat("FuncCallSIMD {%s}", _useVectorCall ? "__vectorcall" : "__cdecl");
|
2506
|
+
}
|
2507
|
+
|
2508
|
+
static void add(TestApp& app) {
|
2509
|
+
app.add(new X86Test_FuncCallSIMD(false));
|
2510
|
+
#ifdef _MSC_VER
|
2511
|
+
app.add(new X86Test_FuncCallSIMD(true));
|
2512
|
+
#endif
|
2513
|
+
}
|
2514
|
+
|
2515
|
+
virtual void compile(x86::Compiler& cc) {
|
2516
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, const void*, const void*>(CallConvId::kHost));
|
2517
|
+
|
2518
|
+
x86::Gp resultPtr = cc.newIntPtr("resultPtr");
|
2519
|
+
x86::Gp aPtr = cc.newIntPtr("aPtr");
|
2520
|
+
x86::Gp bPtr = cc.newIntPtr("bPtr");
|
2521
|
+
x86::Gp pFn = cc.newIntPtr("pFn");
|
2522
|
+
|
2523
|
+
x86::Xmm aXmm = cc.newXmm("aXmm");
|
2524
|
+
x86::Xmm bXmm = cc.newXmm("bXmm");
|
2525
|
+
|
2526
|
+
funcNode->setArg(0, resultPtr);
|
2527
|
+
funcNode->setArg(1, aPtr);
|
2528
|
+
funcNode->setArg(2, bPtr);
|
2529
|
+
|
2530
|
+
CallConvId ccId = CallConvId::kCDecl;
|
2531
|
+
Imm pFnImm = imm((void*)calledFunc_cdecl);
|
2532
|
+
|
2533
|
+
#ifdef _MSC_VER
|
2534
|
+
if (_useVectorCall) {
|
2535
|
+
ccId = CallConvId::kVectorCall;
|
2536
|
+
pFnImm = imm((void*)calledFunc_vcall);
|
2537
|
+
}
|
2538
|
+
#endif
|
2539
|
+
|
2540
|
+
cc.mov(pFn, pFnImm);
|
2541
|
+
cc.movdqu(aXmm, x86::ptr(aPtr));
|
2542
|
+
cc.movdqu(bXmm, x86::ptr(bPtr));
|
2543
|
+
|
2544
|
+
InvokeNode* invokeNode;
|
2545
|
+
cc.invoke(&invokeNode, pFn, FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm>(ccId));
|
2546
|
+
|
2547
|
+
invokeNode->setArg(0, aXmm);
|
2548
|
+
invokeNode->setArg(1, bXmm);
|
2549
|
+
invokeNode->setRet(0, aXmm);
|
2550
|
+
|
2551
|
+
cc.movdqu(x86::ptr(resultPtr), aXmm);
|
2552
|
+
|
2553
|
+
cc.endFunc();
|
2554
|
+
}
|
2555
|
+
|
2556
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2557
|
+
typedef void (*Func)(void*, const void*, const void*);
|
2558
|
+
Func func = ptr_as_func<Func>(_func);
|
2559
|
+
|
2560
|
+
uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
2561
|
+
uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
|
2562
|
+
|
2563
|
+
uint8_t rData[16];
|
2564
|
+
uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
|
2565
|
+
|
2566
|
+
func(rData, aData, bData);
|
2567
|
+
|
2568
|
+
result.appendHex(rData, 16);
|
2569
|
+
expect.appendHex(eData, 16);
|
2570
|
+
|
2571
|
+
return result == expect;
|
2572
|
+
}
|
2573
|
+
|
2574
|
+
static __m128i calledFunc_cdecl(__m128i a, __m128i b) {
|
2575
|
+
return _mm_add_epi8(a, b);
|
2576
|
+
}
|
2577
|
+
|
2578
|
+
#ifdef _MSC_VER
|
2579
|
+
static __m128i __vectorcall calledFunc_vcall(__m128i a, __m128i b) {
|
2580
|
+
return _mm_add_epi8(a, b);
|
2581
|
+
}
|
2582
|
+
#endif
|
2583
|
+
};
|
2584
|
+
|
2585
|
+
// x86::Compiler - X86Test_FuncCallLight
|
2586
|
+
// =====================================
|
2587
|
+
|
2588
|
+
class X86Test_FuncCallLight : public X86TestCase {
|
2589
|
+
public:
|
2590
|
+
X86Test_FuncCallLight() : X86TestCase("FuncCallLight") {}
|
2591
|
+
|
2592
|
+
static void add(TestApp& app) {
|
2593
|
+
app.add(new X86Test_FuncCallLight());
|
2594
|
+
}
|
2595
|
+
|
2596
|
+
virtual void compile(x86::Compiler& cc) {
|
2597
|
+
FuncSignatureT<void, const void*, const void*, const void*, const void*, void*> f1Sig(CallConvId::kCDecl);
|
2598
|
+
FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm> f2Sig(CallConvId::kLightCall2);
|
2599
|
+
|
2600
|
+
FuncNode* f1Node = cc.newFunc(f1Sig);
|
2601
|
+
FuncNode* f2Node = cc.newFunc(f2Sig);
|
2602
|
+
|
2603
|
+
{
|
2604
|
+
x86::Gp aPtr = cc.newIntPtr("aPtr");
|
2605
|
+
x86::Gp bPtr = cc.newIntPtr("bPtr");
|
2606
|
+
x86::Gp cPtr = cc.newIntPtr("cPtr");
|
2607
|
+
x86::Gp dPtr = cc.newIntPtr("dPtr");
|
2608
|
+
x86::Gp pOut = cc.newIntPtr("pOut");
|
2609
|
+
|
2610
|
+
x86::Xmm aXmm = cc.newXmm("aXmm");
|
2611
|
+
x86::Xmm bXmm = cc.newXmm("bXmm");
|
2612
|
+
x86::Xmm cXmm = cc.newXmm("cXmm");
|
2613
|
+
x86::Xmm dXmm = cc.newXmm("dXmm");
|
2614
|
+
|
2615
|
+
cc.addFunc(f1Node);
|
2616
|
+
f1Node->setArg(0, aPtr);
|
2617
|
+
f1Node->setArg(1, bPtr);
|
2618
|
+
f1Node->setArg(2, cPtr);
|
2619
|
+
f1Node->setArg(3, dPtr);
|
2620
|
+
f1Node->setArg(4, pOut);
|
2621
|
+
|
2622
|
+
cc.movups(aXmm, x86::ptr(aPtr));
|
2623
|
+
cc.movups(bXmm, x86::ptr(bPtr));
|
2624
|
+
cc.movups(cXmm, x86::ptr(cPtr));
|
2625
|
+
cc.movups(dXmm, x86::ptr(dPtr));
|
2626
|
+
|
2627
|
+
x86::Xmm xXmm = cc.newXmm("xXmm");
|
2628
|
+
x86::Xmm yXmm = cc.newXmm("yXmm");
|
2629
|
+
|
2630
|
+
InvokeNode* invokeNode;
|
2631
|
+
|
2632
|
+
cc.invoke(&invokeNode, f2Node->label(), f2Sig);
|
2633
|
+
invokeNode->setArg(0, aXmm);
|
2634
|
+
invokeNode->setArg(1, bXmm);
|
2635
|
+
invokeNode->setRet(0, xXmm);
|
2636
|
+
|
2637
|
+
cc.invoke(&invokeNode, f2Node->label(), f2Sig);
|
2638
|
+
invokeNode->setArg(0, cXmm);
|
2639
|
+
invokeNode->setArg(1, dXmm);
|
2640
|
+
invokeNode->setRet(0, yXmm);
|
2641
|
+
|
2642
|
+
cc.pmullw(xXmm, yXmm);
|
2643
|
+
cc.movups(x86::ptr(pOut), xXmm);
|
2644
|
+
|
2645
|
+
cc.endFunc();
|
2646
|
+
}
|
2647
|
+
|
2648
|
+
{
|
2649
|
+
x86::Xmm aXmm = cc.newXmm("aXmm");
|
2650
|
+
x86::Xmm bXmm = cc.newXmm("bXmm");
|
2651
|
+
|
2652
|
+
cc.addFunc(f2Node);
|
2653
|
+
f2Node->setArg(0, aXmm);
|
2654
|
+
f2Node->setArg(1, bXmm);
|
2655
|
+
cc.paddw(aXmm, bXmm);
|
2656
|
+
cc.ret(aXmm);
|
2657
|
+
cc.endFunc();
|
2658
|
+
}
|
2659
|
+
}
|
2660
|
+
|
2661
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2662
|
+
typedef void (*Func)(const void*, const void*, const void*, const void*, void*);
|
2663
|
+
|
2664
|
+
Func func = ptr_as_func<Func>(_func);
|
2665
|
+
|
2666
|
+
int16_t a[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
2667
|
+
int16_t b[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
|
2668
|
+
int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 };
|
2669
|
+
int16_t d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 };
|
2670
|
+
|
2671
|
+
int16_t o[8];
|
2672
|
+
int oExp = 7 * 3;
|
2673
|
+
|
2674
|
+
func(a, b, c, d, o);
|
2675
|
+
|
2676
|
+
result.assignFormat("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7]);
|
2677
|
+
expect.assignFormat("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", oExp, oExp, oExp, oExp, oExp, oExp, oExp, oExp);
|
2678
|
+
|
2679
|
+
return result == expect;
|
2680
|
+
}
|
2681
|
+
};
|
2682
|
+
|
2683
|
+
// x86::Compiler - X86Test_FuncCallManyArgs
|
2684
|
+
// ========================================
|
2685
|
+
|
2686
|
+
class X86Test_FuncCallManyArgs : public X86TestCase {
|
2687
|
+
public:
|
2688
|
+
X86Test_FuncCallManyArgs() : X86TestCase("FuncCallManyArgs") {}
|
2689
|
+
|
2690
|
+
static void add(TestApp& app) {
|
2691
|
+
app.add(new X86Test_FuncCallManyArgs());
|
2692
|
+
}
|
2693
|
+
|
2694
|
+
static int calledFunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
|
2695
|
+
return (a * b * c * d * e) + (f * g * h * i * j);
|
2696
|
+
}
|
2697
|
+
|
2698
|
+
virtual void compile(x86::Compiler& cc) {
|
2699
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
2700
|
+
|
2701
|
+
// Prepare.
|
2702
|
+
x86::Gp va = cc.newInt32("va");
|
2703
|
+
x86::Gp vb = cc.newInt32("vb");
|
2704
|
+
x86::Gp vc = cc.newInt32("vc");
|
2705
|
+
x86::Gp vd = cc.newInt32("vd");
|
2706
|
+
x86::Gp ve = cc.newInt32("ve");
|
2707
|
+
x86::Gp vf = cc.newInt32("vf");
|
2708
|
+
x86::Gp vg = cc.newInt32("vg");
|
2709
|
+
x86::Gp vh = cc.newInt32("vh");
|
2710
|
+
x86::Gp vi = cc.newInt32("vi");
|
2711
|
+
x86::Gp vj = cc.newInt32("vj");
|
2712
|
+
|
2713
|
+
cc.mov(va, 0x03);
|
2714
|
+
cc.mov(vb, 0x12);
|
2715
|
+
cc.mov(vc, 0xA0);
|
2716
|
+
cc.mov(vd, 0x0B);
|
2717
|
+
cc.mov(ve, 0x2F);
|
2718
|
+
cc.mov(vf, 0x02);
|
2719
|
+
cc.mov(vg, 0x0C);
|
2720
|
+
cc.mov(vh, 0x12);
|
2721
|
+
cc.mov(vi, 0x18);
|
2722
|
+
cc.mov(vj, 0x1E);
|
2723
|
+
|
2724
|
+
// Function call.
|
2725
|
+
InvokeNode* invokeNode;
|
2726
|
+
cc.invoke(&invokeNode,
|
2727
|
+
imm((void*)calledFunc),
|
2728
|
+
FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConvId::kHost));
|
2729
|
+
invokeNode->setArg(0, va);
|
2730
|
+
invokeNode->setArg(1, vb);
|
2731
|
+
invokeNode->setArg(2, vc);
|
2732
|
+
invokeNode->setArg(3, vd);
|
2733
|
+
invokeNode->setArg(4, ve);
|
2734
|
+
invokeNode->setArg(5, vf);
|
2735
|
+
invokeNode->setArg(6, vg);
|
2736
|
+
invokeNode->setArg(7, vh);
|
2737
|
+
invokeNode->setArg(8, vi);
|
2738
|
+
invokeNode->setArg(9, vj);
|
2739
|
+
invokeNode->setRet(0, va);
|
2740
|
+
|
2741
|
+
cc.ret(va);
|
2742
|
+
cc.endFunc();
|
2743
|
+
}
|
2744
|
+
|
2745
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2746
|
+
typedef int (*Func)(void);
|
2747
|
+
Func func = ptr_as_func<Func>(_func);
|
2748
|
+
|
2749
|
+
int resultRet = func();
|
2750
|
+
int expectRet = calledFunc(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
|
2751
|
+
|
2752
|
+
result.assignFormat("ret=%d", resultRet);
|
2753
|
+
expect.assignFormat("ret=%d", expectRet);
|
2754
|
+
|
2755
|
+
return resultRet == expectRet;
|
2756
|
+
}
|
2757
|
+
};
|
2758
|
+
|
2759
|
+
// x86::Compiler - X86Test_FuncCallDuplicateArgs
|
2760
|
+
// =============================================
|
2761
|
+
|
2762
|
+
class X86Test_FuncCallDuplicateArgs : public X86TestCase {
|
2763
|
+
public:
|
2764
|
+
X86Test_FuncCallDuplicateArgs() : X86TestCase("FuncCallDuplicateArgs") {}
|
2765
|
+
|
2766
|
+
static void add(TestApp& app) {
|
2767
|
+
app.add(new X86Test_FuncCallDuplicateArgs());
|
2768
|
+
}
|
2769
|
+
|
2770
|
+
static int calledFunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
|
2771
|
+
return (a * b * c * d * e) + (f * g * h * i * j);
|
2772
|
+
}
|
2773
|
+
|
2774
|
+
virtual void compile(x86::Compiler& cc) {
|
2775
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
2776
|
+
|
2777
|
+
// Prepare.
|
2778
|
+
x86::Gp a = cc.newInt32("a");
|
2779
|
+
cc.mov(a, 3);
|
2780
|
+
|
2781
|
+
// Call function.
|
2782
|
+
InvokeNode* invokeNode;
|
2783
|
+
cc.invoke(&invokeNode,
|
2784
|
+
imm((void*)calledFunc),
|
2785
|
+
FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConvId::kHost));
|
2786
|
+
invokeNode->setArg(0, a);
|
2787
|
+
invokeNode->setArg(1, a);
|
2788
|
+
invokeNode->setArg(2, a);
|
2789
|
+
invokeNode->setArg(3, a);
|
2790
|
+
invokeNode->setArg(4, a);
|
2791
|
+
invokeNode->setArg(5, a);
|
2792
|
+
invokeNode->setArg(6, a);
|
2793
|
+
invokeNode->setArg(7, a);
|
2794
|
+
invokeNode->setArg(8, a);
|
2795
|
+
invokeNode->setArg(9, a);
|
2796
|
+
invokeNode->setRet(0, a);
|
2797
|
+
|
2798
|
+
cc.ret(a);
|
2799
|
+
cc.endFunc();
|
2800
|
+
}
|
2801
|
+
|
2802
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2803
|
+
typedef int (*Func)(void);
|
2804
|
+
Func func = ptr_as_func<Func>(_func);
|
2805
|
+
|
2806
|
+
int resultRet = func();
|
2807
|
+
int expectRet = calledFunc(3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
|
2808
|
+
|
2809
|
+
result.assignFormat("ret=%d", resultRet);
|
2810
|
+
expect.assignFormat("ret=%d", expectRet);
|
2811
|
+
|
2812
|
+
return resultRet == expectRet;
|
2813
|
+
}
|
2814
|
+
};
|
2815
|
+
|
2816
|
+
// x86::Compiler - X86Test_FuncCallImmArgs
|
2817
|
+
// =======================================
|
2818
|
+
|
2819
|
+
class X86Test_FuncCallImmArgs : public X86TestCase {
|
2820
|
+
public:
|
2821
|
+
X86Test_FuncCallImmArgs() : X86TestCase("FuncCallImmArgs") {}
|
2822
|
+
|
2823
|
+
static void add(TestApp& app) {
|
2824
|
+
app.add(new X86Test_FuncCallImmArgs());
|
2825
|
+
}
|
2826
|
+
|
2827
|
+
virtual void compile(x86::Compiler& cc) {
|
2828
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
2829
|
+
|
2830
|
+
// Prepare.
|
2831
|
+
x86::Gp rv = cc.newInt32("rv");
|
2832
|
+
|
2833
|
+
// Call function.
|
2834
|
+
InvokeNode* invokeNode;
|
2835
|
+
cc.invoke(&invokeNode,
|
2836
|
+
imm((void*)X86Test_FuncCallManyArgs::calledFunc),
|
2837
|
+
FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConvId::kHost));
|
2838
|
+
|
2839
|
+
invokeNode->setArg(0, imm(0x03));
|
2840
|
+
invokeNode->setArg(1, imm(0x12));
|
2841
|
+
invokeNode->setArg(2, imm(0xA0));
|
2842
|
+
invokeNode->setArg(3, imm(0x0B));
|
2843
|
+
invokeNode->setArg(4, imm(0x2F));
|
2844
|
+
invokeNode->setArg(5, imm(0x02));
|
2845
|
+
invokeNode->setArg(6, imm(0x0C));
|
2846
|
+
invokeNode->setArg(7, imm(0x12));
|
2847
|
+
invokeNode->setArg(8, imm(0x18));
|
2848
|
+
invokeNode->setArg(9, imm(0x1E));
|
2849
|
+
invokeNode->setRet(0, rv);
|
2850
|
+
|
2851
|
+
cc.ret(rv);
|
2852
|
+
cc.endFunc();
|
2853
|
+
}
|
2854
|
+
|
2855
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2856
|
+
typedef int (*Func)(void);
|
2857
|
+
Func func = ptr_as_func<Func>(_func);
|
2858
|
+
|
2859
|
+
int resultRet = func();
|
2860
|
+
int expectRet = X86Test_FuncCallManyArgs::calledFunc(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
|
2861
|
+
|
2862
|
+
result.assignFormat("ret=%d", resultRet);
|
2863
|
+
expect.assignFormat("ret=%d", expectRet);
|
2864
|
+
|
2865
|
+
return resultRet == expectRet;
|
2866
|
+
}
|
2867
|
+
};
|
2868
|
+
|
2869
|
+
// x86::Compiler - X86Test_FuncCallPtrArgs
|
2870
|
+
// =======================================
|
2871
|
+
|
2872
|
+
class X86Test_FuncCallPtrArgs : public X86TestCase {
|
2873
|
+
public:
|
2874
|
+
X86Test_FuncCallPtrArgs() : X86TestCase("FuncCallPtrArgs") {}
|
2875
|
+
|
2876
|
+
static void add(TestApp& app) {
|
2877
|
+
app.add(new X86Test_FuncCallPtrArgs());
|
2878
|
+
}
|
2879
|
+
|
2880
|
+
static int calledFunc(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j) {
|
2881
|
+
return int((intptr_t)a) +
|
2882
|
+
int((intptr_t)b) +
|
2883
|
+
int((intptr_t)c) +
|
2884
|
+
int((intptr_t)d) +
|
2885
|
+
int((intptr_t)e) +
|
2886
|
+
int((intptr_t)f) +
|
2887
|
+
int((intptr_t)g) +
|
2888
|
+
int((intptr_t)h) +
|
2889
|
+
int((intptr_t)i) +
|
2890
|
+
int((intptr_t)j) ;
|
2891
|
+
}
|
2892
|
+
|
2893
|
+
virtual void compile(x86::Compiler& cc) {
|
2894
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
2895
|
+
|
2896
|
+
// Prepare.
|
2897
|
+
x86::Gp rv = cc.newInt32("rv");
|
2898
|
+
|
2899
|
+
// Call function.
|
2900
|
+
InvokeNode* invokeNode;
|
2901
|
+
cc.invoke(&invokeNode,
|
2902
|
+
imm((void*)calledFunc),
|
2903
|
+
FuncSignatureT<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>(CallConvId::kHost));
|
2904
|
+
|
2905
|
+
invokeNode->setArg(0, imm(0x01));
|
2906
|
+
invokeNode->setArg(1, imm(0x02));
|
2907
|
+
invokeNode->setArg(2, imm(0x03));
|
2908
|
+
invokeNode->setArg(3, imm(0x04));
|
2909
|
+
invokeNode->setArg(4, imm(0x05));
|
2910
|
+
invokeNode->setArg(5, imm(0x06));
|
2911
|
+
invokeNode->setArg(6, imm(0x07));
|
2912
|
+
invokeNode->setArg(7, imm(0x08));
|
2913
|
+
invokeNode->setArg(8, imm(0x09));
|
2914
|
+
invokeNode->setArg(9, imm(0x0A));
|
2915
|
+
invokeNode->setRet(0, rv);
|
2916
|
+
|
2917
|
+
cc.ret(rv);
|
2918
|
+
cc.endFunc();
|
2919
|
+
}
|
2920
|
+
|
2921
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2922
|
+
typedef int (*Func)(void);
|
2923
|
+
Func func = ptr_as_func<Func>(_func);
|
2924
|
+
|
2925
|
+
int resultRet = func();
|
2926
|
+
int expectRet = 55;
|
2927
|
+
|
2928
|
+
result.assignFormat("ret=%d", resultRet);
|
2929
|
+
expect.assignFormat("ret=%d", expectRet);
|
2930
|
+
|
2931
|
+
return resultRet == expectRet;
|
2932
|
+
}
|
2933
|
+
};
|
2934
|
+
|
2935
|
+
// x86::Compiler - X86Test_FuncCallRefArgs
|
2936
|
+
// =======================================
|
2937
|
+
|
2938
|
+
class X86Test_FuncCallRefArgs : public X86TestCase {
|
2939
|
+
public:
|
2940
|
+
X86Test_FuncCallRefArgs() : X86TestCase("FuncCallRefArgs") {}
|
2941
|
+
|
2942
|
+
static void add(TestApp& app) {
|
2943
|
+
app.add(new X86Test_FuncCallRefArgs());
|
2944
|
+
}
|
2945
|
+
|
2946
|
+
static int calledFunc(int& a, int& b, int& c, int& d) {
|
2947
|
+
a += a;
|
2948
|
+
b += b;
|
2949
|
+
c += c;
|
2950
|
+
d += d;
|
2951
|
+
return a + b + c + d;
|
2952
|
+
}
|
2953
|
+
|
2954
|
+
virtual void compile(x86::Compiler& cc) {
|
2955
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int&, int&, int&, int&>(CallConvId::kHost));
|
2956
|
+
|
2957
|
+
// Prepare.
|
2958
|
+
x86::Gp arg1 = cc.newInt32();
|
2959
|
+
x86::Gp arg2 = cc.newInt32();
|
2960
|
+
x86::Gp arg3 = cc.newInt32();
|
2961
|
+
x86::Gp arg4 = cc.newInt32();
|
2962
|
+
x86::Gp rv = cc.newInt32("rv");
|
2963
|
+
|
2964
|
+
funcNode->setArg(0, arg1);
|
2965
|
+
funcNode->setArg(1, arg2);
|
2966
|
+
funcNode->setArg(2, arg3);
|
2967
|
+
funcNode->setArg(3, arg4);
|
2968
|
+
|
2969
|
+
// Call function.
|
2970
|
+
InvokeNode* invokeNode;
|
2971
|
+
cc.invoke(&invokeNode,
|
2972
|
+
imm((void*)calledFunc),
|
2973
|
+
FuncSignatureT<int, int&, int&, int&, int&>(CallConvId::kHost));
|
2974
|
+
|
2975
|
+
invokeNode->setArg(0, arg1);
|
2976
|
+
invokeNode->setArg(1, arg2);
|
2977
|
+
invokeNode->setArg(2, arg3);
|
2978
|
+
invokeNode->setArg(3, arg4);
|
2979
|
+
invokeNode->setRet(0, rv);
|
2980
|
+
|
2981
|
+
cc.ret(rv);
|
2982
|
+
cc.endFunc();
|
2983
|
+
}
|
2984
|
+
|
2985
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
2986
|
+
typedef int (*Func)(int&, int&, int&, int&);
|
2987
|
+
Func func = ptr_as_func<Func>(_func);
|
2988
|
+
|
2989
|
+
int inputs[4] = { 1, 2, 3, 4 };
|
2990
|
+
int outputs[4] = { 2, 4, 6, 8 };
|
2991
|
+
int resultRet = func(inputs[0], inputs[1], inputs[2], inputs[3]);
|
2992
|
+
int expectRet = 20;
|
2993
|
+
|
2994
|
+
result.assignFormat("ret={%08X %08X %08X %08X %08X}", resultRet, inputs[0], inputs[1], inputs[2], inputs[3]);
|
2995
|
+
expect.assignFormat("ret={%08X %08X %08X %08X %08X}", expectRet, outputs[0], outputs[1], outputs[2], outputs[3]);
|
2996
|
+
|
2997
|
+
return resultRet == expectRet;
|
2998
|
+
}
|
2999
|
+
};
|
3000
|
+
|
3001
|
+
// x86::Compiler - X86Test_FuncCallFloatAsXmmRet
|
3002
|
+
// =============================================
|
3003
|
+
|
3004
|
+
class X86Test_FuncCallFloatAsXmmRet : public X86TestCase {
|
3005
|
+
public:
|
3006
|
+
X86Test_FuncCallFloatAsXmmRet() : X86TestCase("FuncCallFloatAsXmmRet") {}
|
3007
|
+
|
3008
|
+
static void add(TestApp& app) {
|
3009
|
+
app.add(new X86Test_FuncCallFloatAsXmmRet());
|
3010
|
+
}
|
3011
|
+
|
3012
|
+
static float calledFunc(float a, float b) {
|
3013
|
+
return a * b;
|
3014
|
+
}
|
3015
|
+
|
3016
|
+
virtual void compile(x86::Compiler& cc) {
|
3017
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float>(CallConvId::kHost));
|
3018
|
+
|
3019
|
+
x86::Xmm a = cc.newXmmSs("a");
|
3020
|
+
x86::Xmm b = cc.newXmmSs("b");
|
3021
|
+
x86::Xmm ret = cc.newXmmSs("ret");
|
3022
|
+
|
3023
|
+
funcNode->setArg(0, a);
|
3024
|
+
funcNode->setArg(1, b);
|
3025
|
+
|
3026
|
+
// Call function.
|
3027
|
+
InvokeNode* invokeNode;
|
3028
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<float, float, float>(CallConvId::kHost));
|
3029
|
+
invokeNode->setArg(0, a);
|
3030
|
+
invokeNode->setArg(1, b);
|
3031
|
+
invokeNode->setRet(0, ret);
|
3032
|
+
|
3033
|
+
cc.ret(ret);
|
3034
|
+
cc.endFunc();
|
3035
|
+
}
|
3036
|
+
|
3037
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3038
|
+
typedef float (*Func)(float, float);
|
3039
|
+
Func func = ptr_as_func<Func>(_func);
|
3040
|
+
|
3041
|
+
float resultRet = func(15.5f, 2.0f);
|
3042
|
+
float expectRet = calledFunc(15.5f, 2.0f);
|
3043
|
+
|
3044
|
+
result.assignFormat("ret=%g", resultRet);
|
3045
|
+
expect.assignFormat("ret=%g", expectRet);
|
3046
|
+
|
3047
|
+
return resultRet == expectRet;
|
3048
|
+
}
|
3049
|
+
};
|
3050
|
+
|
3051
|
+
// x86::Compiler - X86Test_FuncCallDoubleAsXmmRet
|
3052
|
+
// ==============================================
|
3053
|
+
|
3054
|
+
class X86Test_FuncCallDoubleAsXmmRet : public X86TestCase {
|
3055
|
+
public:
|
3056
|
+
X86Test_FuncCallDoubleAsXmmRet() : X86TestCase("FuncCallDoubleAsXmmRet") {}
|
3057
|
+
|
3058
|
+
static void add(TestApp& app) {
|
3059
|
+
app.add(new X86Test_FuncCallDoubleAsXmmRet());
|
3060
|
+
}
|
3061
|
+
|
3062
|
+
static double calledFunc(double a, double b) {
|
3063
|
+
return a * b;
|
3064
|
+
}
|
3065
|
+
|
3066
|
+
virtual void compile(x86::Compiler& cc) {
|
3067
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>(CallConvId::kHost));
|
3068
|
+
|
3069
|
+
x86::Xmm a = cc.newXmmSd("a");
|
3070
|
+
x86::Xmm b = cc.newXmmSd("b");
|
3071
|
+
x86::Xmm ret = cc.newXmmSd("ret");
|
3072
|
+
|
3073
|
+
funcNode->setArg(0, a);
|
3074
|
+
funcNode->setArg(1, b);
|
3075
|
+
|
3076
|
+
InvokeNode* invokeNode;
|
3077
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<double, double, double>(CallConvId::kHost));
|
3078
|
+
invokeNode->setArg(0, a);
|
3079
|
+
invokeNode->setArg(1, b);
|
3080
|
+
invokeNode->setRet(0, ret);
|
3081
|
+
|
3082
|
+
cc.ret(ret);
|
3083
|
+
cc.endFunc();
|
3084
|
+
}
|
3085
|
+
|
3086
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3087
|
+
typedef double (*Func)(double, double);
|
3088
|
+
Func func = ptr_as_func<Func>(_func);
|
3089
|
+
|
3090
|
+
double resultRet = func(15.5, 2.0);
|
3091
|
+
double expectRet = calledFunc(15.5, 2.0);
|
3092
|
+
|
3093
|
+
result.assignFormat("ret=%g", resultRet);
|
3094
|
+
expect.assignFormat("ret=%g", expectRet);
|
3095
|
+
|
3096
|
+
return resultRet == expectRet;
|
3097
|
+
}
|
3098
|
+
};
|
3099
|
+
|
3100
|
+
// x86::Compiler - X86Test_FuncCallConditional
|
3101
|
+
// ===========================================
|
3102
|
+
|
3103
|
+
class X86Test_FuncCallConditional : public X86TestCase {
|
3104
|
+
public:
|
3105
|
+
X86Test_FuncCallConditional() : X86TestCase("FuncCallConditional") {}
|
3106
|
+
|
3107
|
+
static void add(TestApp& app) {
|
3108
|
+
app.add(new X86Test_FuncCallConditional());
|
3109
|
+
}
|
3110
|
+
|
3111
|
+
virtual void compile(x86::Compiler& cc) {
|
3112
|
+
x86::Gp x = cc.newInt32("x");
|
3113
|
+
x86::Gp y = cc.newInt32("y");
|
3114
|
+
x86::Gp op = cc.newInt32("op");
|
3115
|
+
|
3116
|
+
InvokeNode* invokeNode;
|
3117
|
+
x86::Gp result;
|
3118
|
+
|
3119
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
3120
|
+
funcNode->setArg(0, x);
|
3121
|
+
funcNode->setArg(1, y);
|
3122
|
+
funcNode->setArg(2, op);
|
3123
|
+
|
3124
|
+
Label opAdd = cc.newLabel();
|
3125
|
+
Label opMul = cc.newLabel();
|
3126
|
+
|
3127
|
+
cc.cmp(op, 0);
|
3128
|
+
cc.jz(opAdd);
|
3129
|
+
cc.cmp(op, 1);
|
3130
|
+
cc.jz(opMul);
|
3131
|
+
|
3132
|
+
result = cc.newInt32("result_0");
|
3133
|
+
cc.mov(result, 0);
|
3134
|
+
cc.ret(result);
|
3135
|
+
|
3136
|
+
cc.bind(opAdd);
|
3137
|
+
result = cc.newInt32("result_1");
|
3138
|
+
|
3139
|
+
cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignatureT<int, int, int>(CallConvId::kHost));
|
3140
|
+
invokeNode->setArg(0, x);
|
3141
|
+
invokeNode->setArg(1, y);
|
3142
|
+
invokeNode->setRet(0, result);
|
3143
|
+
cc.ret(result);
|
3144
|
+
|
3145
|
+
cc.bind(opMul);
|
3146
|
+
result = cc.newInt32("result_2");
|
3147
|
+
|
3148
|
+
cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignatureT<int, int, int>(CallConvId::kHost));
|
3149
|
+
invokeNode->setArg(0, x);
|
3150
|
+
invokeNode->setArg(1, y);
|
3151
|
+
invokeNode->setRet(0, result);
|
3152
|
+
|
3153
|
+
cc.ret(result);
|
3154
|
+
cc.endFunc();
|
3155
|
+
}
|
3156
|
+
|
3157
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3158
|
+
typedef int (*Func)(int, int, int);
|
3159
|
+
Func func = ptr_as_func<Func>(_func);
|
3160
|
+
|
3161
|
+
int arg1 = 4;
|
3162
|
+
int arg2 = 8;
|
3163
|
+
|
3164
|
+
int resultAdd = func(arg1, arg2, 0);
|
3165
|
+
int expectAdd = calledFuncAdd(arg1, arg2);
|
3166
|
+
|
3167
|
+
int resultMul = func(arg1, arg2, 1);
|
3168
|
+
int expectMul = calledFuncMul(arg1, arg2);
|
3169
|
+
|
3170
|
+
result.assignFormat("ret={add=%d, mul=%d}", resultAdd, resultMul);
|
3171
|
+
expect.assignFormat("ret={add=%d, mul=%d}", expectAdd, expectMul);
|
3172
|
+
|
3173
|
+
return (resultAdd == expectAdd) && (resultMul == expectMul);
|
3174
|
+
}
|
3175
|
+
|
3176
|
+
static int calledFuncAdd(int x, int y) { return x + y; }
|
3177
|
+
static int calledFuncMul(int x, int y) { return x * y; }
|
3178
|
+
};
|
3179
|
+
|
3180
|
+
// x86::Compiler - X86Test_FuncCallMultiple
|
3181
|
+
// ========================================
|
3182
|
+
|
3183
|
+
class X86Test_FuncCallMultiple : public X86TestCase {
|
3184
|
+
public:
|
3185
|
+
X86Test_FuncCallMultiple() : X86TestCase("FuncCallMultiple") {}
|
3186
|
+
|
3187
|
+
static void add(TestApp& app) {
|
3188
|
+
app.add(new X86Test_FuncCallMultiple());
|
3189
|
+
}
|
3190
|
+
|
3191
|
+
static int ASMJIT_FASTCALL calledFunc(int* pInt, int index) {
|
3192
|
+
return pInt[index];
|
3193
|
+
}
|
3194
|
+
|
3195
|
+
virtual void compile(x86::Compiler& cc) {
|
3196
|
+
unsigned int i;
|
3197
|
+
|
3198
|
+
x86::Gp buf = cc.newIntPtr("buf");
|
3199
|
+
x86::Gp acc0 = cc.newInt32("acc0");
|
3200
|
+
x86::Gp acc1 = cc.newInt32("acc1");
|
3201
|
+
|
3202
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int*>(CallConvId::kHost));
|
3203
|
+
funcNode->setArg(0, buf);
|
3204
|
+
|
3205
|
+
cc.mov(acc0, 0);
|
3206
|
+
cc.mov(acc1, 0);
|
3207
|
+
|
3208
|
+
for (i = 0; i < 4; i++) {
|
3209
|
+
x86::Gp ret = cc.newInt32("ret");
|
3210
|
+
x86::Gp ptr = cc.newIntPtr("ptr");
|
3211
|
+
x86::Gp idx = cc.newInt32("idx");
|
3212
|
+
InvokeNode* invokeNode;
|
3213
|
+
|
3214
|
+
cc.mov(ptr, buf);
|
3215
|
+
cc.mov(idx, int(i));
|
3216
|
+
|
3217
|
+
cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConvId::kFastCall));
|
3218
|
+
invokeNode->setArg(0, ptr);
|
3219
|
+
invokeNode->setArg(1, idx);
|
3220
|
+
invokeNode->setRet(0, ret);
|
3221
|
+
|
3222
|
+
cc.add(acc0, ret);
|
3223
|
+
|
3224
|
+
cc.mov(ptr, buf);
|
3225
|
+
cc.mov(idx, int(i));
|
3226
|
+
|
3227
|
+
cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConvId::kFastCall));
|
3228
|
+
invokeNode->setArg(0, ptr);
|
3229
|
+
invokeNode->setArg(1, idx);
|
3230
|
+
invokeNode->setRet(0, ret);
|
3231
|
+
|
3232
|
+
cc.sub(acc1, ret);
|
3233
|
+
}
|
3234
|
+
|
3235
|
+
cc.add(acc0, acc1);
|
3236
|
+
cc.ret(acc0);
|
3237
|
+
cc.endFunc();
|
3238
|
+
}
|
3239
|
+
|
3240
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3241
|
+
typedef int (*Func)(int*);
|
3242
|
+
Func func = ptr_as_func<Func>(_func);
|
3243
|
+
|
3244
|
+
int buffer[4] = { 127, 87, 23, 17 };
|
3245
|
+
|
3246
|
+
int resultRet = func(buffer);
|
3247
|
+
int expectRet = 0;
|
3248
|
+
|
3249
|
+
result.assignFormat("ret=%d", resultRet);
|
3250
|
+
expect.assignFormat("ret=%d", expectRet);
|
3251
|
+
|
3252
|
+
return resultRet == expectRet;
|
3253
|
+
}
|
3254
|
+
};
|
3255
|
+
|
3256
|
+
// x86::Compiler - X86Test_FuncCallRecursive
|
3257
|
+
// =========================================
|
3258
|
+
|
3259
|
+
class X86Test_FuncCallRecursive : public X86TestCase {
|
3260
|
+
public:
|
3261
|
+
X86Test_FuncCallRecursive() : X86TestCase("FuncCallRecursive") {}
|
3262
|
+
|
3263
|
+
static void add(TestApp& app) {
|
3264
|
+
app.add(new X86Test_FuncCallRecursive());
|
3265
|
+
}
|
3266
|
+
|
3267
|
+
virtual void compile(x86::Compiler& cc) {
|
3268
|
+
x86::Gp val = cc.newInt32("val");
|
3269
|
+
Label skip = cc.newLabel();
|
3270
|
+
|
3271
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost));
|
3272
|
+
funcNode->setArg(0, val);
|
3273
|
+
|
3274
|
+
cc.cmp(val, 1);
|
3275
|
+
cc.jle(skip);
|
3276
|
+
|
3277
|
+
x86::Gp tmp = cc.newInt32("tmp");
|
3278
|
+
cc.mov(tmp, val);
|
3279
|
+
cc.dec(tmp);
|
3280
|
+
|
3281
|
+
InvokeNode* invokeNode;
|
3282
|
+
|
3283
|
+
cc.invoke(&invokeNode, funcNode->label(), FuncSignatureT<int, int>(CallConvId::kHost));
|
3284
|
+
invokeNode->setArg(0, tmp);
|
3285
|
+
invokeNode->setRet(0, tmp);
|
3286
|
+
cc.mul(cc.newInt32(), val, tmp);
|
3287
|
+
|
3288
|
+
cc.bind(skip);
|
3289
|
+
cc.ret(val);
|
3290
|
+
cc.endFunc();
|
3291
|
+
}
|
3292
|
+
|
3293
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3294
|
+
typedef int (*Func)(int);
|
3295
|
+
Func func = ptr_as_func<Func>(_func);
|
3296
|
+
|
3297
|
+
int resultRet = func(5);
|
3298
|
+
int expectRet = 1 * 2 * 3 * 4 * 5;
|
3299
|
+
|
3300
|
+
result.assignFormat("ret=%d", resultRet);
|
3301
|
+
expect.assignFormat("ret=%d", expectRet);
|
3302
|
+
|
3303
|
+
return resultRet == expectRet;
|
3304
|
+
}
|
3305
|
+
};
|
3306
|
+
|
3307
|
+
// x86::Compiler - X86Test_FuncCallVarArg1
|
3308
|
+
// =======================================
|
3309
|
+
|
3310
|
+
class X86Test_FuncCallVarArg1 : public X86TestCase {
|
3311
|
+
public:
|
3312
|
+
X86Test_FuncCallVarArg1() : X86TestCase("FuncCallVarArg1") {}
|
3313
|
+
|
3314
|
+
static void add(TestApp& app) {
|
3315
|
+
app.add(new X86Test_FuncCallVarArg1());
|
3316
|
+
}
|
3317
|
+
|
3318
|
+
virtual void compile(x86::Compiler& cc) {
|
3319
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int, int>(CallConvId::kHost));
|
3320
|
+
|
3321
|
+
x86::Gp a0 = cc.newInt32("a0");
|
3322
|
+
x86::Gp a1 = cc.newInt32("a1");
|
3323
|
+
x86::Gp a2 = cc.newInt32("a2");
|
3324
|
+
x86::Gp a3 = cc.newInt32("a3");
|
3325
|
+
|
3326
|
+
funcNode->setArg(0, a0);
|
3327
|
+
funcNode->setArg(1, a1);
|
3328
|
+
funcNode->setArg(2, a2);
|
3329
|
+
funcNode->setArg(3, a3);
|
3330
|
+
|
3331
|
+
// We call `int func(size_t, ...)`
|
3332
|
+
// - The `vaIndex` must be 1 (first argument after size_t).
|
3333
|
+
// - The full signature of varargs (int, int, int, int) must follow.
|
3334
|
+
InvokeNode* invokeNode;
|
3335
|
+
cc.invoke(&invokeNode,
|
3336
|
+
imm((void*)calledFunc),
|
3337
|
+
FuncSignatureT<int, size_t, int, int, int, int>(CallConvId::kHost, 1));
|
3338
|
+
invokeNode->setArg(0, imm(4));
|
3339
|
+
invokeNode->setArg(1, a0);
|
3340
|
+
invokeNode->setArg(2, a1);
|
3341
|
+
invokeNode->setArg(3, a2);
|
3342
|
+
invokeNode->setArg(4, a3);
|
3343
|
+
invokeNode->setRet(0, a0);
|
3344
|
+
|
3345
|
+
cc.ret(a0);
|
3346
|
+
cc.endFunc();
|
3347
|
+
}
|
3348
|
+
|
3349
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3350
|
+
typedef int (*Func)(int, int, int, int);
|
3351
|
+
Func func = ptr_as_func<Func>(_func);
|
3352
|
+
|
3353
|
+
int resultRet = func(1, 2, 3, 4);
|
3354
|
+
int expectRet = 1 + 2 + 3 + 4;
|
3355
|
+
|
3356
|
+
result.assignFormat("ret=%d", resultRet);
|
3357
|
+
expect.assignFormat("ret=%d", expectRet);
|
3358
|
+
|
3359
|
+
return resultRet == expectRet;
|
3360
|
+
}
|
3361
|
+
|
3362
|
+
static int calledFunc(size_t n, ...) {
|
3363
|
+
int sum = 0;
|
3364
|
+
va_list ap;
|
3365
|
+
va_start(ap, n);
|
3366
|
+
for (size_t i = 0; i < n; i++) {
|
3367
|
+
int arg = va_arg(ap, int);
|
3368
|
+
sum += arg;
|
3369
|
+
}
|
3370
|
+
va_end(ap);
|
3371
|
+
return sum;
|
3372
|
+
}
|
3373
|
+
};
|
3374
|
+
|
3375
|
+
// x86::Compiler - X86Test_FuncCallVarArg2
|
3376
|
+
// =======================================
|
3377
|
+
|
3378
|
+
class X86Test_FuncCallVarArg2 : public X86TestCase {
|
3379
|
+
public:
|
3380
|
+
X86Test_FuncCallVarArg2() : X86TestCase("FuncCallVarArg2") {}
|
3381
|
+
|
3382
|
+
static void add(TestApp& app) {
|
3383
|
+
app.add(new X86Test_FuncCallVarArg2());
|
3384
|
+
}
|
3385
|
+
|
3386
|
+
virtual void compile(x86::Compiler& cc) {
|
3387
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double, double, double>(CallConvId::kHost));
|
3388
|
+
|
3389
|
+
x86::Xmm a0 = cc.newXmmSd("a0");
|
3390
|
+
x86::Xmm a1 = cc.newXmmSd("a1");
|
3391
|
+
x86::Xmm a2 = cc.newXmmSd("a2");
|
3392
|
+
x86::Xmm a3 = cc.newXmmSd("a3");
|
3393
|
+
|
3394
|
+
funcNode->setArg(0, a0);
|
3395
|
+
funcNode->setArg(1, a1);
|
3396
|
+
funcNode->setArg(2, a2);
|
3397
|
+
funcNode->setArg(3, a3);
|
3398
|
+
|
3399
|
+
// We call `double func(size_t, ...)`
|
3400
|
+
// - The `vaIndex` must be 1 (first argument after size_t).
|
3401
|
+
// - The full signature of varargs (double, double, double, double) must follow.
|
3402
|
+
InvokeNode* invokeNode;
|
3403
|
+
cc.invoke(&invokeNode,
|
3404
|
+
imm((void*)calledFunc),
|
3405
|
+
FuncSignatureT<double, size_t, double, double, double, double>(CallConvId::kHost, 1));
|
3406
|
+
invokeNode->setArg(0, imm(4));
|
3407
|
+
invokeNode->setArg(1, a0);
|
3408
|
+
invokeNode->setArg(2, a1);
|
3409
|
+
invokeNode->setArg(3, a2);
|
3410
|
+
invokeNode->setArg(4, a3);
|
3411
|
+
invokeNode->setRet(0, a0);
|
3412
|
+
|
3413
|
+
cc.ret(a0);
|
3414
|
+
cc.endFunc();
|
3415
|
+
}
|
3416
|
+
|
3417
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3418
|
+
typedef double (*Func)(double, double, double, double);
|
3419
|
+
Func func = ptr_as_func<Func>(_func);
|
3420
|
+
|
3421
|
+
double resultRet = func(1.0, 2.0, 3.0, 4.0);
|
3422
|
+
double expectRet = 1.0 + 2.0 + 3.0 + 4.0;
|
3423
|
+
|
3424
|
+
result.assignFormat("ret=%f", resultRet);
|
3425
|
+
expect.assignFormat("ret=%f", expectRet);
|
3426
|
+
|
3427
|
+
return resultRet == expectRet;
|
3428
|
+
}
|
3429
|
+
|
3430
|
+
static double calledFunc(size_t n, ...) {
|
3431
|
+
double sum = 0;
|
3432
|
+
va_list ap;
|
3433
|
+
va_start(ap, n);
|
3434
|
+
for (size_t i = 0; i < n; i++) {
|
3435
|
+
double arg = va_arg(ap, double);
|
3436
|
+
sum += arg;
|
3437
|
+
}
|
3438
|
+
va_end(ap);
|
3439
|
+
return sum;
|
3440
|
+
}
|
3441
|
+
};
|
3442
|
+
|
3443
|
+
// x86::Compiler - X86Test_FuncCallInt64Arg
|
3444
|
+
// ========================================
|
3445
|
+
|
3446
|
+
class X86Test_FuncCallInt64Arg : public X86TestCase {
|
3447
|
+
public:
|
3448
|
+
X86Test_FuncCallInt64Arg() : X86TestCase("FuncCallInt64Arg") {}
|
3449
|
+
|
3450
|
+
static void add(TestApp& app) {
|
3451
|
+
app.add(new X86Test_FuncCallInt64Arg());
|
3452
|
+
}
|
3453
|
+
|
3454
|
+
virtual void compile(x86::Compiler& cc) {
|
3455
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint64_t, uint64_t>(CallConvId::kHost));
|
3456
|
+
|
3457
|
+
if (cc.is64Bit()) {
|
3458
|
+
x86::Gp reg = cc.newUInt64();
|
3459
|
+
funcNode->setArg(0, reg);
|
3460
|
+
cc.add(reg, 1);
|
3461
|
+
cc.ret(reg);
|
3462
|
+
}
|
3463
|
+
else {
|
3464
|
+
x86::Gp hi = cc.newUInt32("hi");
|
3465
|
+
x86::Gp lo = cc.newUInt32("lo");
|
3466
|
+
|
3467
|
+
funcNode->setArg(0, 0, lo);
|
3468
|
+
funcNode->setArg(0, 1, hi);
|
3469
|
+
|
3470
|
+
cc.add(lo, 1);
|
3471
|
+
cc.adc(hi, 0);
|
3472
|
+
cc.ret(lo, hi);
|
3473
|
+
}
|
3474
|
+
|
3475
|
+
cc.endFunc();
|
3476
|
+
}
|
3477
|
+
|
3478
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3479
|
+
typedef uint64_t (*Func)(uint64_t);
|
3480
|
+
Func func = ptr_as_func<Func>(_func);
|
3481
|
+
|
3482
|
+
uint64_t resultRet = func(uint64_t(0xFFFFFFFF));
|
3483
|
+
uint64_t expectRet = 0x100000000;
|
3484
|
+
|
3485
|
+
result.assignFormat("ret=%llu", (unsigned long long)resultRet);
|
3486
|
+
expect.assignFormat("ret=%llu", (unsigned long long)expectRet);
|
3487
|
+
|
3488
|
+
return resultRet == expectRet;
|
3489
|
+
}
|
3490
|
+
|
3491
|
+
static double calledFunc(size_t n, ...) {
|
3492
|
+
double sum = 0;
|
3493
|
+
va_list ap;
|
3494
|
+
va_start(ap, n);
|
3495
|
+
for (size_t i = 0; i < n; i++) {
|
3496
|
+
double arg = va_arg(ap, double);
|
3497
|
+
sum += arg;
|
3498
|
+
}
|
3499
|
+
va_end(ap);
|
3500
|
+
return sum;
|
3501
|
+
}
|
3502
|
+
};
|
3503
|
+
|
3504
|
+
// x86::Compiler - X86Test_FuncCallMisc1
|
3505
|
+
// =====================================
|
3506
|
+
|
3507
|
+
class X86Test_FuncCallMisc1 : public X86TestCase {
|
3508
|
+
public:
|
3509
|
+
X86Test_FuncCallMisc1() : X86TestCase("FuncCallMisc1") {}
|
3510
|
+
|
3511
|
+
static void add(TestApp& app) {
|
3512
|
+
app.add(new X86Test_FuncCallMisc1());
|
3513
|
+
}
|
3514
|
+
|
3515
|
+
static void dummy(int, int) {}
|
3516
|
+
|
3517
|
+
virtual void compile(x86::Compiler& cc) {
|
3518
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
3519
|
+
|
3520
|
+
x86::Gp a = cc.newInt32("a");
|
3521
|
+
x86::Gp b = cc.newInt32("b");
|
3522
|
+
x86::Gp r = cc.newInt32("r");
|
3523
|
+
|
3524
|
+
funcNode->setArg(0, a);
|
3525
|
+
funcNode->setArg(1, b);
|
3526
|
+
|
3527
|
+
InvokeNode* invokeNode;
|
3528
|
+
cc.invoke(&invokeNode,
|
3529
|
+
imm((void*)dummy),
|
3530
|
+
FuncSignatureT<void, int, int>(CallConvId::kHost));
|
3531
|
+
invokeNode->setArg(0, a);
|
3532
|
+
invokeNode->setArg(1, b);
|
3533
|
+
|
3534
|
+
cc.lea(r, x86::ptr(a, b));
|
3535
|
+
cc.ret(r);
|
3536
|
+
|
3537
|
+
cc.endFunc();
|
3538
|
+
}
|
3539
|
+
|
3540
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3541
|
+
typedef int (*Func)(int, int);
|
3542
|
+
Func func = ptr_as_func<Func>(_func);
|
3543
|
+
|
3544
|
+
int resultRet = func(44, 199);
|
3545
|
+
int expectRet = 243;
|
3546
|
+
|
3547
|
+
result.assignFormat("ret=%d", resultRet);
|
3548
|
+
expect.assignFormat("ret=%d", expectRet);
|
3549
|
+
|
3550
|
+
return resultRet == expectRet;
|
3551
|
+
}
|
3552
|
+
};
|
3553
|
+
|
3554
|
+
// x86::Compiler - X86Test_FuncCallMisc2
|
3555
|
+
// =====================================
|
3556
|
+
|
3557
|
+
class X86Test_FuncCallMisc2 : public X86TestCase {
|
3558
|
+
public:
|
3559
|
+
X86Test_FuncCallMisc2() : X86TestCase("FuncCallMisc2") {}
|
3560
|
+
|
3561
|
+
static void add(TestApp& app) {
|
3562
|
+
app.add(new X86Test_FuncCallMisc2());
|
3563
|
+
}
|
3564
|
+
|
3565
|
+
virtual void compile(x86::Compiler& cc) {
|
3566
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, const double*>(CallConvId::kHost));
|
3567
|
+
|
3568
|
+
x86::Gp p = cc.newIntPtr("p");
|
3569
|
+
x86::Xmm arg = cc.newXmmSd("arg");
|
3570
|
+
x86::Xmm ret = cc.newXmmSd("ret");
|
3571
|
+
|
3572
|
+
funcNode->setArg(0, p);
|
3573
|
+
cc.movsd(arg, x86::ptr(p));
|
3574
|
+
|
3575
|
+
InvokeNode* invokeNode;
|
3576
|
+
cc.invoke(&invokeNode,
|
3577
|
+
imm((void*)op),
|
3578
|
+
FuncSignatureT<double, double>(CallConvId::kHost));
|
3579
|
+
invokeNode->setArg(0, arg);
|
3580
|
+
invokeNode->setRet(0, ret);
|
3581
|
+
|
3582
|
+
cc.ret(ret);
|
3583
|
+
cc.endFunc();
|
3584
|
+
}
|
3585
|
+
|
3586
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3587
|
+
typedef double (*Func)(const double*);
|
3588
|
+
Func func = ptr_as_func<Func>(_func);
|
3589
|
+
|
3590
|
+
double arg = 2;
|
3591
|
+
|
3592
|
+
double resultRet = func(&arg);
|
3593
|
+
double expectRet = op(arg);
|
3594
|
+
|
3595
|
+
result.assignFormat("ret=%g", resultRet);
|
3596
|
+
expect.assignFormat("ret=%g", expectRet);
|
3597
|
+
|
3598
|
+
return resultRet == expectRet;
|
3599
|
+
}
|
3600
|
+
|
3601
|
+
static double op(double a) { return a * a; }
|
3602
|
+
};
|
3603
|
+
|
3604
|
+
// x86::Compiler - X86Test_FuncCallMisc3
|
3605
|
+
// =====================================
|
3606
|
+
|
3607
|
+
class X86Test_FuncCallMisc3 : public X86TestCase {
|
3608
|
+
public:
|
3609
|
+
X86Test_FuncCallMisc3() : X86TestCase("FuncCallMisc3") {}
|
3610
|
+
|
3611
|
+
static void add(TestApp& app) {
|
3612
|
+
app.add(new X86Test_FuncCallMisc3());
|
3613
|
+
}
|
3614
|
+
|
3615
|
+
virtual void compile(x86::Compiler& cc) {
|
3616
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, const double*>(CallConvId::kHost));
|
3617
|
+
|
3618
|
+
x86::Gp p = cc.newIntPtr("p");
|
3619
|
+
x86::Xmm arg = cc.newXmmSd("arg");
|
3620
|
+
x86::Xmm ret = cc.newXmmSd("ret");
|
3621
|
+
|
3622
|
+
funcNode->setArg(0, p);
|
3623
|
+
cc.movsd(arg, x86::ptr(p));
|
3624
|
+
|
3625
|
+
InvokeNode* invokeNode;
|
3626
|
+
cc.invoke(&invokeNode,
|
3627
|
+
imm((void*)op),
|
3628
|
+
FuncSignatureT<double, double>(CallConvId::kHost));
|
3629
|
+
invokeNode->setArg(0, arg);
|
3630
|
+
invokeNode->setRet(0, ret);
|
3631
|
+
|
3632
|
+
cc.xorps(arg, arg);
|
3633
|
+
cc.subsd(arg, ret);
|
3634
|
+
|
3635
|
+
cc.ret(arg);
|
3636
|
+
cc.endFunc();
|
3637
|
+
}
|
3638
|
+
|
3639
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3640
|
+
typedef double (*Func)(const double*);
|
3641
|
+
Func func = ptr_as_func<Func>(_func);
|
3642
|
+
|
3643
|
+
double arg = 2;
|
3644
|
+
|
3645
|
+
double resultRet = func(&arg);
|
3646
|
+
double expectRet = -op(arg);
|
3647
|
+
|
3648
|
+
result.assignFormat("ret=%g", resultRet);
|
3649
|
+
expect.assignFormat("ret=%g", expectRet);
|
3650
|
+
|
3651
|
+
return resultRet == expectRet;
|
3652
|
+
}
|
3653
|
+
|
3654
|
+
static double op(double a) { return a * a; }
|
3655
|
+
};
|
3656
|
+
|
3657
|
+
// x86::Compiler - X86Test_FuncCallMisc4
|
3658
|
+
// =====================================
|
3659
|
+
|
3660
|
+
class X86Test_FuncCallMisc4 : public X86TestCase {
|
3661
|
+
public:
|
3662
|
+
X86Test_FuncCallMisc4() : X86TestCase("FuncCallMisc4") {}
|
3663
|
+
|
3664
|
+
static void add(TestApp& app) {
|
3665
|
+
app.add(new X86Test_FuncCallMisc4());
|
3666
|
+
}
|
3667
|
+
|
3668
|
+
virtual void compile(x86::Compiler& cc) {
|
3669
|
+
InvokeNode* invokeNode;
|
3670
|
+
|
3671
|
+
FuncSignatureBuilder funcSignature;
|
3672
|
+
funcSignature.setCallConvId(CallConvId::kHost);
|
3673
|
+
funcSignature.setRet(TypeId::kFloat64);
|
3674
|
+
cc.addFunc(funcSignature);
|
3675
|
+
|
3676
|
+
FuncSignatureBuilder invokeSignature;
|
3677
|
+
invokeSignature.setCallConvId(CallConvId::kHost);
|
3678
|
+
invokeSignature.setRet(TypeId::kFloat64);
|
3679
|
+
|
3680
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), invokeSignature);
|
3681
|
+
x86::Xmm ret = cc.newXmmSd("ret");
|
3682
|
+
invokeNode->setRet(0, ret);
|
3683
|
+
cc.ret(ret);
|
3684
|
+
|
3685
|
+
cc.endFunc();
|
3686
|
+
}
|
3687
|
+
|
3688
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3689
|
+
typedef double (*Func)(void);
|
3690
|
+
Func func = ptr_as_func<Func>(_func);
|
3691
|
+
|
3692
|
+
double resultRet = func();
|
3693
|
+
double expectRet = 3.14;
|
3694
|
+
|
3695
|
+
result.assignFormat("ret=%g", resultRet);
|
3696
|
+
expect.assignFormat("ret=%g", expectRet);
|
3697
|
+
|
3698
|
+
return resultRet == expectRet;
|
3699
|
+
}
|
3700
|
+
|
3701
|
+
static double calledFunc() { return 3.14; }
|
3702
|
+
};
|
3703
|
+
|
3704
|
+
// x86::Compiler - X86Test_FuncCallMisc5
|
3705
|
+
// =====================================
|
3706
|
+
|
3707
|
+
// The register allocator should clobber the register used by the `call` itself.
|
3708
|
+
class X86Test_FuncCallMisc5 : public X86TestCase {
|
3709
|
+
public:
|
3710
|
+
X86Test_FuncCallMisc5() : X86TestCase("FuncCallMisc5") {}
|
3711
|
+
|
3712
|
+
static void add(TestApp& app) {
|
3713
|
+
app.add(new X86Test_FuncCallMisc5());
|
3714
|
+
}
|
3715
|
+
|
3716
|
+
virtual void compile(x86::Compiler& cc) {
|
3717
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
3718
|
+
|
3719
|
+
x86::Gp pFn = cc.newIntPtr("pFn");
|
3720
|
+
x86::Gp vars[16];
|
3721
|
+
|
3722
|
+
uint32_t i, regCount = cc.arch() == Arch::kX86 ? 8 : 16;
|
3723
|
+
ASMJIT_ASSERT(regCount <= ASMJIT_ARRAY_SIZE(vars));
|
3724
|
+
|
3725
|
+
cc.mov(pFn, imm((void*)calledFunc));
|
3726
|
+
|
3727
|
+
for (i = 0; i < regCount; i++) {
|
3728
|
+
if (i == x86::Gp::kIdBp || i == x86::Gp::kIdSp)
|
3729
|
+
continue;
|
3730
|
+
|
3731
|
+
vars[i] = cc.newInt32("%%%u", unsigned(i));
|
3732
|
+
cc.mov(vars[i], 1);
|
3733
|
+
}
|
3734
|
+
|
3735
|
+
InvokeNode* invokeNode;
|
3736
|
+
cc.invoke(&invokeNode, pFn, FuncSignatureT<void>(CallConvId::kHost));
|
3737
|
+
|
3738
|
+
for (i = 1; i < regCount; i++)
|
3739
|
+
if (vars[i].isValid())
|
3740
|
+
cc.add(vars[0], vars[i]);
|
3741
|
+
cc.ret(vars[0]);
|
3742
|
+
|
3743
|
+
cc.endFunc();
|
3744
|
+
}
|
3745
|
+
|
3746
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3747
|
+
typedef int (*Func)(void);
|
3748
|
+
Func func = ptr_as_func<Func>(_func);
|
3749
|
+
|
3750
|
+
int resultRet = func();
|
3751
|
+
int expectRet = sizeof(void*) == 4 ? 6 : 14;
|
3752
|
+
|
3753
|
+
result.assignFormat("ret=%d", resultRet);
|
3754
|
+
expect.assignFormat("ret=%d", expectRet);
|
3755
|
+
|
3756
|
+
return resultRet == expectRet;
|
3757
|
+
}
|
3758
|
+
|
3759
|
+
static void calledFunc() {}
|
3760
|
+
};
|
3761
|
+
|
3762
|
+
// x86::Compiler - X86Test_FuncCallMisc6
|
3763
|
+
// =====================================
|
3764
|
+
|
3765
|
+
class X86Test_FuncCallMisc6 : public X86TestCase {
|
3766
|
+
public:
|
3767
|
+
X86Test_FuncCallMisc6() : X86TestCase("FuncCallMisc6") {}
|
3768
|
+
|
3769
|
+
static void add(TestApp& app) {
|
3770
|
+
app.add(new X86Test_FuncCallMisc6());
|
3771
|
+
}
|
3772
|
+
|
3773
|
+
virtual void compile(x86::Compiler& cc) {
|
3774
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConvId::kHost));
|
3775
|
+
|
3776
|
+
constexpr uint32_t kCount = 16;
|
3777
|
+
|
3778
|
+
x86::Gp v[kCount];
|
3779
|
+
x86::Gp argVal = cc.newUInt32("argVal");
|
3780
|
+
x86::Gp retVal = cc.newUInt32("retVal");
|
3781
|
+
uint32_t i;
|
3782
|
+
|
3783
|
+
funcNode->setArg(0, argVal);
|
3784
|
+
cc.add(argVal, 1);
|
3785
|
+
|
3786
|
+
for (i = 0; i < kCount; i++)
|
3787
|
+
v[i] = cc.newUInt32("v%u", i);
|
3788
|
+
|
3789
|
+
InvokeNode* invokeNode;
|
3790
|
+
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<uint32_t, uint32_t>(CallConvId::kHost));
|
3791
|
+
invokeNode->setArg(0, argVal);
|
3792
|
+
invokeNode->setRet(0, retVal);
|
3793
|
+
|
3794
|
+
for (i = 0; i < kCount; i++)
|
3795
|
+
cc.mov(v[i], i + 1);
|
3796
|
+
|
3797
|
+
for (i = 0; i < kCount; i++)
|
3798
|
+
cc.add(argVal, v[i]);
|
3799
|
+
|
3800
|
+
cc.add(retVal, argVal);
|
3801
|
+
cc.ret(retVal);
|
3802
|
+
|
3803
|
+
cc.endFunc();
|
3804
|
+
}
|
3805
|
+
|
3806
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3807
|
+
typedef uint32_t (*Func)(uint32_t x);
|
3808
|
+
Func func = ptr_as_func<Func>(_func);
|
3809
|
+
|
3810
|
+
uint32_t resultRet = func(111);
|
3811
|
+
uint32_t expectRet = 111 + 112 + 2 + (1 + 16) * 8;
|
3812
|
+
|
3813
|
+
result.assignFormat("ret=%u", resultRet);
|
3814
|
+
expect.assignFormat("ret=%u", expectRet);
|
3815
|
+
|
3816
|
+
return resultRet == expectRet;
|
3817
|
+
}
|
3818
|
+
|
3819
|
+
static uint32_t calledFunc(uint32_t x) { return x + 1; }
|
3820
|
+
};
|
3821
|
+
|
3822
|
+
// x86::Compiler - X86Test_FuncCallAVXClobber
|
3823
|
+
// ==========================================
|
3824
|
+
|
3825
|
+
class X86Test_FuncCallAVXClobber : public X86TestCase {
|
3826
|
+
public:
|
3827
|
+
X86Test_FuncCallAVXClobber() : X86TestCase("FuncCallAVXClobber") {}
|
3828
|
+
|
3829
|
+
static void add(TestApp& app) {
|
3830
|
+
const CpuInfo& cpuInfo = CpuInfo::host();
|
3831
|
+
|
3832
|
+
if (cpuInfo.features().x86().hasAVX2() && sizeof(void*) == 8)
|
3833
|
+
app.add(new X86Test_FuncCallAVXClobber());
|
3834
|
+
}
|
3835
|
+
|
3836
|
+
virtual void compile(x86::Compiler& cc) {
|
3837
|
+
FuncNode* mainFunc = cc.addFunc(FuncSignatureT<void, void*, const void*, const void*>(CallConvId::kHost));
|
3838
|
+
mainFunc->frame().setAvxEnabled();
|
3839
|
+
mainFunc->frame().setAvxCleanup();
|
3840
|
+
|
3841
|
+
// We need a Windows calling convention to test this properly also on a non-Windows machine.
|
3842
|
+
FuncNode* helperFunc = cc.newFunc(FuncSignatureT<void, void*, const void*>(CallConvId::kX64Windows));
|
3843
|
+
helperFunc->frame().setAvxEnabled();
|
3844
|
+
helperFunc->frame().setAvxCleanup();
|
3845
|
+
|
3846
|
+
{
|
3847
|
+
size_t i;
|
3848
|
+
|
3849
|
+
x86::Gp dPtr = cc.newIntPtr("dPtr");
|
3850
|
+
x86::Gp aPtr = cc.newIntPtr("aPtr");
|
3851
|
+
x86::Gp bPtr = cc.newIntPtr("bPtr");
|
3852
|
+
x86::Gp tPtr = cc.newIntPtr("tPtr");
|
3853
|
+
x86::Ymm acc[8];
|
3854
|
+
x86::Mem stack = cc.newStack(32, 1, "stack");
|
3855
|
+
|
3856
|
+
mainFunc->setArg(0, dPtr);
|
3857
|
+
mainFunc->setArg(1, aPtr);
|
3858
|
+
mainFunc->setArg(2, bPtr);
|
3859
|
+
|
3860
|
+
cc.lea(tPtr, stack);
|
3861
|
+
for (i = 0; i < 8; i++) {
|
3862
|
+
acc[i] = cc.newYmm("acc%zu", i);
|
3863
|
+
cc.vmovdqu(acc[i], x86::ptr(aPtr));
|
3864
|
+
}
|
3865
|
+
|
3866
|
+
InvokeNode* invokeNode;
|
3867
|
+
cc.invoke(&invokeNode,
|
3868
|
+
helperFunc->label(),
|
3869
|
+
FuncSignatureT<void, void*, const void*>(CallConvId::kX64Windows));
|
3870
|
+
invokeNode->setArg(0, tPtr);
|
3871
|
+
invokeNode->setArg(1, bPtr);
|
3872
|
+
|
3873
|
+
for (i = 1; i < 8; i++) {
|
3874
|
+
cc.vpaddd(acc[0], acc[0], acc[i]);
|
3875
|
+
}
|
3876
|
+
|
3877
|
+
cc.vpaddd(acc[0], acc[0], x86::ptr(tPtr));
|
3878
|
+
cc.vmovdqu(x86::ptr(dPtr), acc[0]);
|
3879
|
+
|
3880
|
+
cc.endFunc();
|
3881
|
+
}
|
3882
|
+
|
3883
|
+
{
|
3884
|
+
cc.addFunc(helperFunc);
|
3885
|
+
|
3886
|
+
x86::Gp dPtr = cc.newIntPtr("dPtr");
|
3887
|
+
x86::Gp aPtr = cc.newIntPtr("aPtr");
|
3888
|
+
|
3889
|
+
helperFunc->setArg(0, dPtr);
|
3890
|
+
helperFunc->setArg(1, aPtr);
|
3891
|
+
|
3892
|
+
x86::Gp tmp = cc.newIntPtr("tmp");
|
3893
|
+
x86::Ymm acc = cc.newYmm("acc");
|
3894
|
+
|
3895
|
+
cc.mov(tmp, 1);
|
3896
|
+
cc.vmovd(acc.xmm(), tmp);
|
3897
|
+
cc.vpbroadcastd(acc, acc.xmm());
|
3898
|
+
cc.vpaddd(acc, acc, x86::ptr(aPtr));
|
3899
|
+
cc.vmovdqu(x86::ptr(dPtr), acc);
|
3900
|
+
|
3901
|
+
cc.endFunc();
|
3902
|
+
}
|
3903
|
+
}
|
3904
|
+
|
3905
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3906
|
+
typedef void (*Func)(void*, const void*, const void*);
|
3907
|
+
Func func = ptr_as_func<Func>(_func);
|
3908
|
+
|
3909
|
+
size_t i;
|
3910
|
+
|
3911
|
+
static const uint32_t aData[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
3912
|
+
static const uint32_t bData[8] = { 6, 3, 5, 9, 1, 8, 7, 2 };
|
3913
|
+
|
3914
|
+
uint32_t resultData[8];
|
3915
|
+
uint32_t expectData[8];
|
3916
|
+
|
3917
|
+
for (i = 0; i < 8; i++)
|
3918
|
+
expectData[i] = aData[i] * 8 + bData[i] + 1;
|
3919
|
+
|
3920
|
+
func(resultData, aData, bData);
|
3921
|
+
|
3922
|
+
result.assign("{");
|
3923
|
+
expect.assign("{");
|
3924
|
+
|
3925
|
+
for (i = 0; i < 8; i++) {
|
3926
|
+
result.appendFormat("%u", resultData[i]);
|
3927
|
+
expect.appendFormat("%u", expectData[i]);
|
3928
|
+
|
3929
|
+
if (i != 7) result.append(", ");
|
3930
|
+
if (i != 7) expect.append(", ");
|
3931
|
+
}
|
3932
|
+
|
3933
|
+
result.append("}");
|
3934
|
+
expect.append("}");
|
3935
|
+
|
3936
|
+
return result == expect;
|
3937
|
+
}
|
3938
|
+
};
|
3939
|
+
|
3940
|
+
// x86::Compiler - X86Test_MiscLocalConstPool
|
3941
|
+
// ==========================================
|
3942
|
+
|
3943
|
+
class X86Test_MiscLocalConstPool : public X86TestCase {
|
3944
|
+
public:
|
3945
|
+
X86Test_MiscLocalConstPool() : X86TestCase("MiscLocalConstPool") {}
|
3946
|
+
|
3947
|
+
static void add(TestApp& app) {
|
3948
|
+
app.add(new X86Test_MiscLocalConstPool());
|
3949
|
+
}
|
3950
|
+
|
3951
|
+
virtual void compile(x86::Compiler& cc) {
|
3952
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
3953
|
+
|
3954
|
+
x86::Gp v0 = cc.newInt32("v0");
|
3955
|
+
x86::Gp v1 = cc.newInt32("v1");
|
3956
|
+
|
3957
|
+
x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kLocal, 200);
|
3958
|
+
x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kLocal, 33);
|
3959
|
+
|
3960
|
+
cc.mov(v0, c0);
|
3961
|
+
cc.mov(v1, c1);
|
3962
|
+
cc.add(v0, v1);
|
3963
|
+
|
3964
|
+
cc.ret(v0);
|
3965
|
+
cc.endFunc();
|
3966
|
+
}
|
3967
|
+
|
3968
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
3969
|
+
typedef int (*Func)(void);
|
3970
|
+
Func func = ptr_as_func<Func>(_func);
|
3971
|
+
|
3972
|
+
int resultRet = func();
|
3973
|
+
int expectRet = 233;
|
3974
|
+
|
3975
|
+
result.assignFormat("ret=%d", resultRet);
|
3976
|
+
expect.assignFormat("ret=%d", expectRet);
|
3977
|
+
|
3978
|
+
return resultRet == expectRet;
|
3979
|
+
}
|
3980
|
+
};
|
3981
|
+
|
3982
|
+
// x86::Compiler - X86Test_MiscGlobalConstPool
|
3983
|
+
// ===========================================
|
3984
|
+
|
3985
|
+
class X86Test_MiscGlobalConstPool : public X86TestCase {
|
3986
|
+
public:
|
3987
|
+
X86Test_MiscGlobalConstPool() : X86TestCase("MiscGlobalConstPool") {}
|
3988
|
+
|
3989
|
+
static void add(TestApp& app) {
|
3990
|
+
app.add(new X86Test_MiscGlobalConstPool());
|
3991
|
+
}
|
3992
|
+
|
3993
|
+
virtual void compile(x86::Compiler& cc) {
|
3994
|
+
cc.addFunc(FuncSignatureT<int>(CallConvId::kHost));
|
3995
|
+
|
3996
|
+
x86::Gp v0 = cc.newInt32("v0");
|
3997
|
+
x86::Gp v1 = cc.newInt32("v1");
|
3998
|
+
|
3999
|
+
x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kGlobal, 200);
|
4000
|
+
x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kGlobal, 33);
|
4001
|
+
|
4002
|
+
cc.mov(v0, c0);
|
4003
|
+
cc.mov(v1, c1);
|
4004
|
+
cc.add(v0, v1);
|
4005
|
+
|
4006
|
+
cc.ret(v0);
|
4007
|
+
cc.endFunc();
|
4008
|
+
}
|
4009
|
+
|
4010
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
4011
|
+
typedef int (*Func)(void);
|
4012
|
+
Func func = ptr_as_func<Func>(_func);
|
4013
|
+
|
4014
|
+
int resultRet = func();
|
4015
|
+
int expectRet = 233;
|
4016
|
+
|
4017
|
+
result.assignFormat("ret=%d", resultRet);
|
4018
|
+
expect.assignFormat("ret=%d", expectRet);
|
4019
|
+
|
4020
|
+
return resultRet == expectRet;
|
4021
|
+
}
|
4022
|
+
};
|
4023
|
+
|
4024
|
+
// x86::Compiler - X86Test_MiscMultiRet
|
4025
|
+
// ====================================
|
4026
|
+
|
4027
|
+
struct X86Test_MiscMultiRet : public X86TestCase {
|
4028
|
+
X86Test_MiscMultiRet() : X86TestCase("MiscMultiRet") {}
|
4029
|
+
|
4030
|
+
static void add(TestApp& app) {
|
4031
|
+
app.add(new X86Test_MiscMultiRet());
|
4032
|
+
}
|
4033
|
+
|
4034
|
+
virtual void compile(x86::Compiler& cc) {
|
4035
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost));
|
4036
|
+
|
4037
|
+
x86::Gp op = cc.newInt32("op");
|
4038
|
+
x86::Gp a = cc.newInt32("a");
|
4039
|
+
x86::Gp b = cc.newInt32("b");
|
4040
|
+
|
4041
|
+
Label L_Zero = cc.newLabel();
|
4042
|
+
Label L_Add = cc.newLabel();
|
4043
|
+
Label L_Sub = cc.newLabel();
|
4044
|
+
Label L_Mul = cc.newLabel();
|
4045
|
+
Label L_Div = cc.newLabel();
|
4046
|
+
|
4047
|
+
funcNode->setArg(0, op);
|
4048
|
+
funcNode->setArg(1, a);
|
4049
|
+
funcNode->setArg(2, b);
|
4050
|
+
|
4051
|
+
cc.cmp(op, 0);
|
4052
|
+
cc.jz(L_Add);
|
4053
|
+
|
4054
|
+
cc.cmp(op, 1);
|
4055
|
+
cc.jz(L_Sub);
|
4056
|
+
|
4057
|
+
cc.cmp(op, 2);
|
4058
|
+
cc.jz(L_Mul);
|
4059
|
+
|
4060
|
+
cc.cmp(op, 3);
|
4061
|
+
cc.jz(L_Div);
|
4062
|
+
|
4063
|
+
cc.bind(L_Zero);
|
4064
|
+
cc.xor_(a, a);
|
4065
|
+
cc.ret(a);
|
4066
|
+
|
4067
|
+
cc.bind(L_Add);
|
4068
|
+
cc.add(a, b);
|
4069
|
+
cc.ret(a);
|
4070
|
+
|
4071
|
+
cc.bind(L_Sub);
|
4072
|
+
cc.sub(a, b);
|
4073
|
+
cc.ret(a);
|
4074
|
+
|
4075
|
+
cc.bind(L_Mul);
|
4076
|
+
cc.imul(a, b);
|
4077
|
+
cc.ret(a);
|
4078
|
+
|
4079
|
+
cc.bind(L_Div);
|
4080
|
+
cc.cmp(b, 0);
|
4081
|
+
cc.jz(L_Zero);
|
4082
|
+
|
4083
|
+
x86::Gp zero = cc.newInt32("zero");
|
4084
|
+
cc.xor_(zero, zero);
|
4085
|
+
cc.idiv(zero, a, b);
|
4086
|
+
cc.ret(a);
|
4087
|
+
|
4088
|
+
cc.endFunc();
|
4089
|
+
}
|
4090
|
+
|
4091
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
4092
|
+
typedef int (*Func)(int, int, int);
|
4093
|
+
|
4094
|
+
Func func = ptr_as_func<Func>(_func);
|
4095
|
+
|
4096
|
+
int a = 44;
|
4097
|
+
int b = 3;
|
4098
|
+
|
4099
|
+
int r0 = func(0, a, b);
|
4100
|
+
int r1 = func(1, a, b);
|
4101
|
+
int r2 = func(2, a, b);
|
4102
|
+
int r3 = func(3, a, b);
|
4103
|
+
int e0 = a + b;
|
4104
|
+
int e1 = a - b;
|
4105
|
+
int e2 = a * b;
|
4106
|
+
int e3 = a / b;
|
4107
|
+
|
4108
|
+
result.assignFormat("ret={%d %d %d %d}", r0, r1, r2, r3);
|
4109
|
+
expect.assignFormat("ret={%d %d %d %d}", e0, e1, e2, e3);
|
4110
|
+
|
4111
|
+
return result.eq(expect);
|
4112
|
+
}
|
4113
|
+
};
|
4114
|
+
|
4115
|
+
// x86::Compiler - X86Test_MiscMultiFunc
|
4116
|
+
// =====================================
|
4117
|
+
|
4118
|
+
class X86Test_MiscMultiFunc : public X86TestCase {
|
4119
|
+
public:
|
4120
|
+
X86Test_MiscMultiFunc() : X86TestCase("MiscMultiFunc") {}
|
4121
|
+
|
4122
|
+
static void add(TestApp& app) {
|
4123
|
+
app.add(new X86Test_MiscMultiFunc());
|
4124
|
+
}
|
4125
|
+
|
4126
|
+
virtual void compile(x86::Compiler& cc) {
|
4127
|
+
FuncNode* f1Node = cc.newFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
4128
|
+
FuncNode* f2Node = cc.newFunc(FuncSignatureT<int, int, int>(CallConvId::kHost));
|
4129
|
+
|
4130
|
+
{
|
4131
|
+
x86::Gp a = cc.newInt32("a");
|
4132
|
+
x86::Gp b = cc.newInt32("b");
|
4133
|
+
|
4134
|
+
cc.addFunc(f1Node);
|
4135
|
+
f1Node->setArg(0, a);
|
4136
|
+
f1Node->setArg(1, b);
|
4137
|
+
|
4138
|
+
InvokeNode* invokeNode;
|
4139
|
+
cc.invoke(&invokeNode, f2Node->label(), FuncSignatureT<int, int, int>(CallConvId::kHost));
|
4140
|
+
invokeNode->setArg(0, a);
|
4141
|
+
invokeNode->setArg(1, b);
|
4142
|
+
invokeNode->setRet(0, a);
|
4143
|
+
|
4144
|
+
cc.ret(a);
|
4145
|
+
cc.endFunc();
|
4146
|
+
}
|
4147
|
+
|
4148
|
+
{
|
4149
|
+
x86::Gp a = cc.newInt32("a");
|
4150
|
+
x86::Gp b = cc.newInt32("b");
|
4151
|
+
|
4152
|
+
cc.addFunc(f2Node);
|
4153
|
+
f2Node->setArg(0, a);
|
4154
|
+
f2Node->setArg(1, b);
|
4155
|
+
|
4156
|
+
cc.add(a, b);
|
4157
|
+
cc.ret(a);
|
4158
|
+
cc.endFunc();
|
4159
|
+
}
|
4160
|
+
}
|
4161
|
+
|
4162
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
4163
|
+
typedef int (*Func)(int, int);
|
4164
|
+
|
4165
|
+
Func func = ptr_as_func<Func>(_func);
|
4166
|
+
|
4167
|
+
int resultRet = func(56, 22);
|
4168
|
+
int expectRet = 56 + 22;
|
4169
|
+
|
4170
|
+
result.assignFormat("ret=%d", resultRet);
|
4171
|
+
expect.assignFormat("ret=%d", expectRet);
|
4172
|
+
|
4173
|
+
return result.eq(expect);
|
4174
|
+
}
|
4175
|
+
};
|
4176
|
+
|
4177
|
+
// x86::Compiler - X86Test_MiscUnfollow
|
4178
|
+
// ====================================
|
4179
|
+
|
4180
|
+
// Global (I didn't find a better way to test this).
|
4181
|
+
static jmp_buf globalJmpBuf;
|
4182
|
+
|
4183
|
+
class X86Test_MiscUnfollow : public X86TestCase {
|
4184
|
+
public:
|
4185
|
+
X86Test_MiscUnfollow() : X86TestCase("MiscUnfollow") {}
|
4186
|
+
|
4187
|
+
static void add(TestApp& app) {
|
4188
|
+
app.add(new X86Test_MiscUnfollow());
|
4189
|
+
}
|
4190
|
+
|
4191
|
+
virtual void compile(x86::Compiler& cc) {
|
4192
|
+
// NOTE: Fastcall calling convention is the most appropriate here as all arguments are passed via registers and
|
4193
|
+
// there won't be any stack misalignment in the `handler()`. This was failing on MacOS when targeting 32-bit mode.
|
4194
|
+
x86::Gp a = cc.newInt32("a");
|
4195
|
+
x86::Gp b = cc.newIntPtr("b");
|
4196
|
+
Label tramp = cc.newLabel();
|
4197
|
+
|
4198
|
+
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, void*>(CallConvId::kFastCall));
|
4199
|
+
funcNode->setArg(0, a);
|
4200
|
+
funcNode->setArg(1, b);
|
4201
|
+
|
4202
|
+
cc.cmp(a, 0);
|
4203
|
+
cc.jz(tramp);
|
4204
|
+
cc.ret(a);
|
4205
|
+
cc.bind(tramp);
|
4206
|
+
cc.unfollow().jmp(b);
|
4207
|
+
cc.endFunc();
|
4208
|
+
}
|
4209
|
+
|
4210
|
+
virtual bool run(void* _func, String& result, String& expect) {
|
4211
|
+
typedef int (ASMJIT_FASTCALL *Func)(int, void*);
|
4212
|
+
|
4213
|
+
Func func = ptr_as_func<Func>(_func);
|
4214
|
+
|
4215
|
+
int resultRet = 0;
|
4216
|
+
int expectRet = 1;
|
4217
|
+
|
4218
|
+
if (!setjmp(globalJmpBuf))
|
4219
|
+
resultRet = func(0, (void*)handler);
|
4220
|
+
else
|
4221
|
+
resultRet = 1;
|
4222
|
+
|
4223
|
+
result.assignFormat("ret={%d}", resultRet);
|
4224
|
+
expect.assignFormat("ret={%d}", expectRet);
|
4225
|
+
|
4226
|
+
return resultRet == expectRet;
|
4227
|
+
}
|
4228
|
+
|
4229
|
+
static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); }
|
4230
|
+
};
|
4231
|
+
|
4232
|
+
// x86::Compiler - Tests
|
4233
|
+
// =====================
|
4234
|
+
|
4235
|
+
void compiler_add_x86_tests(TestApp& app) {
|
4236
|
+
// Base tests.
|
4237
|
+
app.addT<X86Test_NoCode>();
|
4238
|
+
app.addT<X86Test_NoAlign>();
|
4239
|
+
app.addT<X86Test_AlignBase>();
|
4240
|
+
|
4241
|
+
// Jump tests.
|
4242
|
+
app.addT<X86Test_JumpMerge>();
|
4243
|
+
app.addT<X86Test_JumpCross>();
|
4244
|
+
app.addT<X86Test_JumpMany>();
|
4245
|
+
app.addT<X86Test_JumpUnreachable1>();
|
4246
|
+
app.addT<X86Test_JumpUnreachable2>();
|
4247
|
+
app.addT<X86Test_JumpTable1>();
|
4248
|
+
app.addT<X86Test_JumpTable2>();
|
4249
|
+
|
4250
|
+
// Alloc tests.
|
4251
|
+
app.addT<X86Test_AllocBase>();
|
4252
|
+
app.addT<X86Test_AllocMany1>();
|
4253
|
+
app.addT<X86Test_AllocMany2>();
|
4254
|
+
app.addT<X86Test_AllocImul1>();
|
4255
|
+
app.addT<X86Test_AllocImul2>();
|
4256
|
+
app.addT<X86Test_AllocIdiv1>();
|
4257
|
+
app.addT<X86Test_AllocSetz>();
|
4258
|
+
app.addT<X86Test_AllocShlRor>();
|
4259
|
+
app.addT<X86Test_AllocGpbLo1>();
|
4260
|
+
app.addT<X86Test_AllocGpbLo2>();
|
4261
|
+
app.addT<X86Test_AllocRepMovsb>();
|
4262
|
+
app.addT<X86Test_AllocIfElse1>();
|
4263
|
+
app.addT<X86Test_AllocIfElse2>();
|
4264
|
+
app.addT<X86Test_AllocIfElse3>();
|
4265
|
+
app.addT<X86Test_AllocIfElse4>();
|
4266
|
+
app.addT<X86Test_AllocInt8>();
|
4267
|
+
app.addT<X86Test_AllocUnhandledArg>();
|
4268
|
+
app.addT<X86Test_AllocArgsIntPtr>();
|
4269
|
+
app.addT<X86Test_AllocArgsFloat>();
|
4270
|
+
app.addT<X86Test_AllocArgsDouble>();
|
4271
|
+
app.addT<X86Test_AllocArgsVec>();
|
4272
|
+
app.addT<X86Test_AllocRetFloat1>();
|
4273
|
+
app.addT<X86Test_AllocRetFloat2>();
|
4274
|
+
app.addT<X86Test_AllocRetDouble1>();
|
4275
|
+
app.addT<X86Test_AllocRetDouble2>();
|
4276
|
+
app.addT<X86Test_AllocStack>();
|
4277
|
+
app.addT<X86Test_AllocMemcpy>();
|
4278
|
+
app.addT<X86Test_AllocExtraBlock>();
|
4279
|
+
app.addT<X86Test_AllocAlphaBlend>();
|
4280
|
+
|
4281
|
+
// Function call tests.
|
4282
|
+
app.addT<X86Test_FuncCallBase1>();
|
4283
|
+
app.addT<X86Test_FuncCallBase2>();
|
4284
|
+
app.addT<X86Test_FuncCallStd>();
|
4285
|
+
app.addT<X86Test_FuncCallFast>();
|
4286
|
+
app.addT<X86Test_FuncCallSIMD>();
|
4287
|
+
app.addT<X86Test_FuncCallLight>();
|
4288
|
+
app.addT<X86Test_FuncCallManyArgs>();
|
4289
|
+
app.addT<X86Test_FuncCallDuplicateArgs>();
|
4290
|
+
app.addT<X86Test_FuncCallImmArgs>();
|
4291
|
+
app.addT<X86Test_FuncCallPtrArgs>();
|
4292
|
+
app.addT<X86Test_FuncCallRefArgs>();
|
4293
|
+
app.addT<X86Test_FuncCallFloatAsXmmRet>();
|
4294
|
+
app.addT<X86Test_FuncCallDoubleAsXmmRet>();
|
4295
|
+
app.addT<X86Test_FuncCallConditional>();
|
4296
|
+
app.addT<X86Test_FuncCallMultiple>();
|
4297
|
+
app.addT<X86Test_FuncCallRecursive>();
|
4298
|
+
app.addT<X86Test_FuncCallVarArg1>();
|
4299
|
+
app.addT<X86Test_FuncCallVarArg2>();
|
4300
|
+
app.addT<X86Test_FuncCallInt64Arg>();
|
4301
|
+
app.addT<X86Test_FuncCallMisc1>();
|
4302
|
+
app.addT<X86Test_FuncCallMisc2>();
|
4303
|
+
app.addT<X86Test_FuncCallMisc3>();
|
4304
|
+
app.addT<X86Test_FuncCallMisc4>();
|
4305
|
+
app.addT<X86Test_FuncCallMisc5>();
|
4306
|
+
app.addT<X86Test_FuncCallMisc6>();
|
4307
|
+
app.addT<X86Test_FuncCallAVXClobber>();
|
4308
|
+
|
4309
|
+
// Miscellaneous tests.
|
4310
|
+
app.addT<X86Test_MiscLocalConstPool>();
|
4311
|
+
app.addT<X86Test_MiscGlobalConstPool>();
|
4312
|
+
app.addT<X86Test_MiscMultiRet>();
|
4313
|
+
app.addT<X86Test_MiscMultiFunc>();
|
4314
|
+
app.addT<X86Test_MiscUnfollow>();
|
4315
|
+
}
|
4316
|
+
|
4317
|
+
#endif // !ASMJIT_NO_X86 && ASMJIT_ARCH_X86
|