asmjit 0.2.0 → 0.2.1
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/asmjit.gemspec +1 -1
- 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 +18 -0
- data/lib/asmjit/version.rb +1 -1
- metadata +197 -2
|
@@ -0,0 +1,619 @@
|
|
|
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 "../core/api-build_p.h"
|
|
7
|
+
#if !defined(ASMJIT_NO_X86)
|
|
8
|
+
|
|
9
|
+
#include "../core/formatter.h"
|
|
10
|
+
#include "../core/funcargscontext_p.h"
|
|
11
|
+
#include "../core/string.h"
|
|
12
|
+
#include "../core/support.h"
|
|
13
|
+
#include "../core/type.h"
|
|
14
|
+
#include "../core/radefs_p.h"
|
|
15
|
+
#include "../x86/x86emithelper_p.h"
|
|
16
|
+
#include "../x86/x86emitter.h"
|
|
17
|
+
#include "../x86/x86formatter_p.h"
|
|
18
|
+
#include "../x86/x86instapi_p.h"
|
|
19
|
+
|
|
20
|
+
ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|
21
|
+
|
|
22
|
+
// x86::EmitHelper - Utilities
|
|
23
|
+
// ===========================
|
|
24
|
+
|
|
25
|
+
static inline uint32_t getXmmMovInst(const FuncFrame& frame) {
|
|
26
|
+
bool avx = frame.isAvxEnabled();
|
|
27
|
+
bool aligned = frame.hasAlignedVecSR();
|
|
28
|
+
|
|
29
|
+
return aligned ? (avx ? Inst::kIdVmovaps : Inst::kIdMovaps)
|
|
30
|
+
: (avx ? Inst::kIdVmovups : Inst::kIdMovups);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//! Converts `size` to a 'kmov?' instruction.
|
|
34
|
+
static inline uint32_t kmovInstFromSize(uint32_t size) noexcept {
|
|
35
|
+
switch (size) {
|
|
36
|
+
case 1: return Inst::kIdKmovb;
|
|
37
|
+
case 2: return Inst::kIdKmovw;
|
|
38
|
+
case 4: return Inst::kIdKmovd;
|
|
39
|
+
case 8: return Inst::kIdKmovq;
|
|
40
|
+
default: return Inst::kIdNone;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static inline uint32_t makeCastOp(TypeId dst, TypeId src) noexcept {
|
|
45
|
+
return (uint32_t(dst) << 8) | uint32_t(src);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// x86::EmitHelper - Emit Reg Move
|
|
49
|
+
// ===============================
|
|
50
|
+
|
|
51
|
+
ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove(
|
|
52
|
+
const Operand_& dst_,
|
|
53
|
+
const Operand_& src_, TypeId typeId, const char* comment) {
|
|
54
|
+
|
|
55
|
+
// Invalid or abstract TypeIds are not allowed.
|
|
56
|
+
ASMJIT_ASSERT(TypeUtils::isValid(typeId) && !TypeUtils::isAbstract(typeId));
|
|
57
|
+
|
|
58
|
+
Operand dst(dst_);
|
|
59
|
+
Operand src(src_);
|
|
60
|
+
|
|
61
|
+
InstId instId = Inst::kIdNone;
|
|
62
|
+
uint32_t memFlags = 0;
|
|
63
|
+
uint32_t overrideMemSize = 0;
|
|
64
|
+
|
|
65
|
+
enum MemFlags : uint32_t {
|
|
66
|
+
kDstMem = 0x1,
|
|
67
|
+
kSrcMem = 0x2
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Detect memory operands and patch them to have the same size as the register. BaseCompiler always sets memory size
|
|
71
|
+
// of allocs and spills, so it shouldn't be really necessary, however, after this function was separated from Compiler
|
|
72
|
+
// it's better to make sure that the size is always specified, as we can use 'movzx' and 'movsx' that rely on it.
|
|
73
|
+
if (dst.isMem()) { memFlags |= kDstMem; dst.as<Mem>().setSize(src.size()); }
|
|
74
|
+
if (src.isMem()) { memFlags |= kSrcMem; src.as<Mem>().setSize(dst.size()); }
|
|
75
|
+
|
|
76
|
+
switch (typeId) {
|
|
77
|
+
case TypeId::kInt8:
|
|
78
|
+
case TypeId::kUInt8:
|
|
79
|
+
case TypeId::kInt16:
|
|
80
|
+
case TypeId::kUInt16:
|
|
81
|
+
// Special case - 'movzx' load.
|
|
82
|
+
if (memFlags & kSrcMem) {
|
|
83
|
+
instId = Inst::kIdMovzx;
|
|
84
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!memFlags) {
|
|
89
|
+
// Change both destination and source registers to GPD (safer, no dependencies).
|
|
90
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
91
|
+
src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
92
|
+
}
|
|
93
|
+
ASMJIT_FALLTHROUGH;
|
|
94
|
+
|
|
95
|
+
case TypeId::kInt32:
|
|
96
|
+
case TypeId::kUInt32:
|
|
97
|
+
case TypeId::kInt64:
|
|
98
|
+
case TypeId::kUInt64:
|
|
99
|
+
instId = Inst::kIdMov;
|
|
100
|
+
break;
|
|
101
|
+
|
|
102
|
+
case TypeId::kMmx32:
|
|
103
|
+
instId = Inst::kIdMovd;
|
|
104
|
+
if (memFlags) break;
|
|
105
|
+
ASMJIT_FALLTHROUGH;
|
|
106
|
+
|
|
107
|
+
case TypeId::kMmx64 : instId = Inst::kIdMovq ; break;
|
|
108
|
+
case TypeId::kMask8 : instId = Inst::kIdKmovb; break;
|
|
109
|
+
case TypeId::kMask16: instId = Inst::kIdKmovw; break;
|
|
110
|
+
case TypeId::kMask32: instId = Inst::kIdKmovd; break;
|
|
111
|
+
case TypeId::kMask64: instId = Inst::kIdKmovq; break;
|
|
112
|
+
|
|
113
|
+
default: {
|
|
114
|
+
TypeId scalarTypeId = TypeUtils::scalarOf(typeId);
|
|
115
|
+
if (TypeUtils::isVec32(typeId) && memFlags) {
|
|
116
|
+
overrideMemSize = 4;
|
|
117
|
+
if (scalarTypeId == TypeId::kFloat32)
|
|
118
|
+
instId = _avxEnabled ? Inst::kIdVmovss : Inst::kIdMovss;
|
|
119
|
+
else
|
|
120
|
+
instId = _avxEnabled ? Inst::kIdVmovd : Inst::kIdMovd;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (TypeUtils::isVec64(typeId) && memFlags) {
|
|
125
|
+
overrideMemSize = 8;
|
|
126
|
+
if (scalarTypeId == TypeId::kFloat64)
|
|
127
|
+
instId = _avxEnabled ? Inst::kIdVmovsd : Inst::kIdMovsd;
|
|
128
|
+
else
|
|
129
|
+
instId = _avxEnabled ? Inst::kIdVmovq : Inst::kIdMovq;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (scalarTypeId == TypeId::kFloat32)
|
|
134
|
+
instId = _avxEnabled ? Inst::kIdVmovaps : Inst::kIdMovaps;
|
|
135
|
+
else if (scalarTypeId == TypeId::kFloat64)
|
|
136
|
+
instId = _avxEnabled ? Inst::kIdVmovapd : Inst::kIdMovapd;
|
|
137
|
+
else if (!_avx512Enabled)
|
|
138
|
+
instId = _avxEnabled ? Inst::kIdVmovdqa : Inst::kIdMovdqa;
|
|
139
|
+
else
|
|
140
|
+
instId = Inst::kIdVmovdqa32;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!instId)
|
|
146
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
147
|
+
|
|
148
|
+
if (overrideMemSize) {
|
|
149
|
+
if (dst.isMem()) dst.as<Mem>().setSize(overrideMemSize);
|
|
150
|
+
if (src.isMem()) src.as<Mem>().setSize(overrideMemSize);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
_emitter->setInlineComment(comment);
|
|
154
|
+
return _emitter->emit(instId, dst, src);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// x86::EmitHelper - Emit Arg Move
|
|
158
|
+
// ===============================
|
|
159
|
+
|
|
160
|
+
ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove(
|
|
161
|
+
const BaseReg& dst_, TypeId dstTypeId,
|
|
162
|
+
const Operand_& src_, TypeId srcTypeId, const char* comment) {
|
|
163
|
+
|
|
164
|
+
// Deduce optional `dstTypeId`, which may be `TypeId::kVoid` in some cases.
|
|
165
|
+
if (dstTypeId == TypeId::kVoid) {
|
|
166
|
+
const ArchTraits& archTraits = ArchTraits::byArch(_emitter->arch());
|
|
167
|
+
dstTypeId = archTraits.regTypeToTypeId(dst_.type());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Invalid or abstract TypeIds are not allowed.
|
|
171
|
+
ASMJIT_ASSERT(TypeUtils::isValid(dstTypeId) && !TypeUtils::isAbstract(dstTypeId));
|
|
172
|
+
ASMJIT_ASSERT(TypeUtils::isValid(srcTypeId) && !TypeUtils::isAbstract(srcTypeId));
|
|
173
|
+
|
|
174
|
+
Reg dst(dst_.as<Reg>());
|
|
175
|
+
Operand src(src_);
|
|
176
|
+
|
|
177
|
+
uint32_t dstSize = TypeUtils::sizeOf(dstTypeId);
|
|
178
|
+
uint32_t srcSize = TypeUtils::sizeOf(srcTypeId);
|
|
179
|
+
|
|
180
|
+
InstId instId = Inst::kIdNone;
|
|
181
|
+
|
|
182
|
+
// Not a real loop, just 'break' is nicer than 'goto'.
|
|
183
|
+
for (;;) {
|
|
184
|
+
if (TypeUtils::isInt(dstTypeId)) {
|
|
185
|
+
if (TypeUtils::isInt(srcTypeId)) {
|
|
186
|
+
instId = Inst::kIdMovsx;
|
|
187
|
+
uint32_t castOp = makeCastOp(dstTypeId, srcTypeId);
|
|
188
|
+
|
|
189
|
+
// Sign extend by using 'movsx'.
|
|
190
|
+
if (castOp == makeCastOp(TypeId::kInt16, TypeId::kInt8 ) ||
|
|
191
|
+
castOp == makeCastOp(TypeId::kInt32, TypeId::kInt8 ) ||
|
|
192
|
+
castOp == makeCastOp(TypeId::kInt32, TypeId::kInt16) ||
|
|
193
|
+
castOp == makeCastOp(TypeId::kInt64, TypeId::kInt8 ) ||
|
|
194
|
+
castOp == makeCastOp(TypeId::kInt64, TypeId::kInt16))
|
|
195
|
+
break;
|
|
196
|
+
|
|
197
|
+
// Sign extend by using 'movsxd'.
|
|
198
|
+
instId = Inst::kIdMovsxd;
|
|
199
|
+
if (castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32))
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (TypeUtils::isInt(srcTypeId) || src_.isMem()) {
|
|
204
|
+
// Zero extend by using 'movzx' or 'mov'.
|
|
205
|
+
if (dstSize <= 4 && srcSize < 4) {
|
|
206
|
+
instId = Inst::kIdMovzx;
|
|
207
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
// We should have caught all possibilities where `srcSize` is less than 4, so we don't have to worry
|
|
211
|
+
// about 'movzx' anymore. Minimum size is enough to determine if we want 32-bit or 64-bit move.
|
|
212
|
+
instId = Inst::kIdMov;
|
|
213
|
+
srcSize = Support::min(srcSize, dstSize);
|
|
214
|
+
|
|
215
|
+
dst.setSignature(srcSize == 4 ? Reg::signatureOfT<RegType::kX86_Gpd>()
|
|
216
|
+
: Reg::signatureOfT<RegType::kX86_Gpq>());
|
|
217
|
+
if (src.isReg())
|
|
218
|
+
src.setSignature(dst.signature());
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// NOTE: The previous branch caught all memory sources, from here it's always register to register conversion,
|
|
224
|
+
// so catch the remaining cases.
|
|
225
|
+
srcSize = Support::min(srcSize, dstSize);
|
|
226
|
+
|
|
227
|
+
if (TypeUtils::isMmx(srcTypeId)) {
|
|
228
|
+
// 64-bit move.
|
|
229
|
+
instId = Inst::kIdMovq;
|
|
230
|
+
if (srcSize == 8)
|
|
231
|
+
break;
|
|
232
|
+
|
|
233
|
+
// 32-bit move.
|
|
234
|
+
instId = Inst::kIdMovd;
|
|
235
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (TypeUtils::isMask(srcTypeId)) {
|
|
240
|
+
instId = kmovInstFromSize(srcSize);
|
|
241
|
+
dst.setSignature(srcSize <= 4 ? Reg::signatureOfT<RegType::kX86_Gpd>()
|
|
242
|
+
: Reg::signatureOfT<RegType::kX86_Gpq>());
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (TypeUtils::isVec(srcTypeId)) {
|
|
247
|
+
// 64-bit move.
|
|
248
|
+
instId = _avxEnabled ? Inst::kIdVmovq : Inst::kIdMovq;
|
|
249
|
+
if (srcSize == 8)
|
|
250
|
+
break;
|
|
251
|
+
|
|
252
|
+
// 32-bit move.
|
|
253
|
+
instId = _avxEnabled ? Inst::kIdVmovd : Inst::kIdMovd;
|
|
254
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (TypeUtils::isMmx(dstTypeId)) {
|
|
260
|
+
instId = Inst::kIdMovq;
|
|
261
|
+
srcSize = Support::min(srcSize, dstSize);
|
|
262
|
+
|
|
263
|
+
if (TypeUtils::isInt(srcTypeId) || src.isMem()) {
|
|
264
|
+
// 64-bit move.
|
|
265
|
+
if (srcSize == 8)
|
|
266
|
+
break;
|
|
267
|
+
|
|
268
|
+
// 32-bit move.
|
|
269
|
+
instId = Inst::kIdMovd;
|
|
270
|
+
if (src.isReg())
|
|
271
|
+
src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (TypeUtils::isMmx(srcTypeId))
|
|
276
|
+
break;
|
|
277
|
+
|
|
278
|
+
// This will hurt if AVX is enabled.
|
|
279
|
+
instId = Inst::kIdMovdq2q;
|
|
280
|
+
if (TypeUtils::isVec(srcTypeId))
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (TypeUtils::isMask(dstTypeId)) {
|
|
285
|
+
srcSize = Support::min(srcSize, dstSize);
|
|
286
|
+
|
|
287
|
+
if (TypeUtils::isInt(srcTypeId) || TypeUtils::isMask(srcTypeId) || src.isMem()) {
|
|
288
|
+
instId = kmovInstFromSize(srcSize);
|
|
289
|
+
if (Reg::isGp(src) && srcSize <= 4)
|
|
290
|
+
src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (TypeUtils::isVec(dstTypeId)) {
|
|
296
|
+
// By default set destination to XMM, will be set to YMM|ZMM if needed.
|
|
297
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Xmm>());
|
|
298
|
+
|
|
299
|
+
// This will hurt if AVX is enabled.
|
|
300
|
+
if (Reg::isMm(src)) {
|
|
301
|
+
// 64-bit move.
|
|
302
|
+
instId = Inst::kIdMovq2dq;
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Argument conversion.
|
|
307
|
+
TypeId dstScalarId = TypeUtils::scalarOf(dstTypeId);
|
|
308
|
+
TypeId srcScalarId = TypeUtils::scalarOf(srcTypeId);
|
|
309
|
+
|
|
310
|
+
if (dstScalarId == TypeId::kFloat32 && srcScalarId == TypeId::kFloat64) {
|
|
311
|
+
srcSize = Support::min(dstSize * 2, srcSize);
|
|
312
|
+
dstSize = srcSize / 2;
|
|
313
|
+
|
|
314
|
+
if (srcSize <= 8)
|
|
315
|
+
instId = _avxEnabled ? Inst::kIdVcvtss2sd : Inst::kIdCvtss2sd;
|
|
316
|
+
else
|
|
317
|
+
instId = _avxEnabled ? Inst::kIdVcvtps2pd : Inst::kIdCvtps2pd;
|
|
318
|
+
|
|
319
|
+
if (dstSize == 32)
|
|
320
|
+
dst.setSignature(Reg::signatureOfT<RegType::kX86_Ymm>());
|
|
321
|
+
if (src.isReg())
|
|
322
|
+
src.setSignature(Reg::signatureOfVecBySize(srcSize));
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (dstScalarId == TypeId::kFloat64 && srcScalarId == TypeId::kFloat32) {
|
|
327
|
+
srcSize = Support::min(dstSize, srcSize * 2) / 2;
|
|
328
|
+
dstSize = srcSize * 2;
|
|
329
|
+
|
|
330
|
+
if (srcSize <= 4)
|
|
331
|
+
instId = _avxEnabled ? Inst::kIdVcvtsd2ss : Inst::kIdCvtsd2ss;
|
|
332
|
+
else
|
|
333
|
+
instId = _avxEnabled ? Inst::kIdVcvtpd2ps : Inst::kIdCvtpd2ps;
|
|
334
|
+
|
|
335
|
+
dst.setSignature(Reg::signatureOfVecBySize(dstSize));
|
|
336
|
+
if (src.isReg() && srcSize >= 32)
|
|
337
|
+
src.setSignature(Reg::signatureOfT<RegType::kX86_Ymm>());
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
srcSize = Support::min(srcSize, dstSize);
|
|
342
|
+
if (Reg::isGp(src) || src.isMem()) {
|
|
343
|
+
// 32-bit move.
|
|
344
|
+
if (srcSize <= 4) {
|
|
345
|
+
instId = _avxEnabled ? Inst::kIdVmovd : Inst::kIdMovd;
|
|
346
|
+
if (src.isReg())
|
|
347
|
+
src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// 64-bit move.
|
|
352
|
+
if (srcSize == 8) {
|
|
353
|
+
instId = _avxEnabled ? Inst::kIdVmovq : Inst::kIdMovq;
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (Reg::isVec(src) || src.isMem()) {
|
|
359
|
+
instId = _avxEnabled ? Inst::kIdVmovaps : Inst::kIdMovaps;
|
|
360
|
+
|
|
361
|
+
if (src.isMem() && srcSize < _emitter->environment().stackAlignment())
|
|
362
|
+
instId = _avxEnabled ? Inst::kIdVmovups : Inst::kIdMovups;
|
|
363
|
+
|
|
364
|
+
OperandSignature signature = Reg::signatureOfVecBySize(srcSize);
|
|
365
|
+
dst.setSignature(signature);
|
|
366
|
+
if (src.isReg())
|
|
367
|
+
src.setSignature(signature);
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (src.isMem())
|
|
376
|
+
src.as<Mem>().setSize(srcSize);
|
|
377
|
+
|
|
378
|
+
_emitter->setInlineComment(comment);
|
|
379
|
+
return _emitter->emit(instId, dst, src);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
Error EmitHelper::emitRegSwap(
|
|
383
|
+
const BaseReg& a,
|
|
384
|
+
const BaseReg& b, const char* comment) {
|
|
385
|
+
|
|
386
|
+
if (a.isGp() && b.isGp()) {
|
|
387
|
+
_emitter->setInlineComment(comment);
|
|
388
|
+
return _emitter->emit(Inst::kIdXchg, a, b);
|
|
389
|
+
}
|
|
390
|
+
else
|
|
391
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// x86::EmitHelper - Emit Prolog & Epilog
|
|
395
|
+
// ======================================
|
|
396
|
+
|
|
397
|
+
static inline void X86Internal_setupSaveRestoreInfo(RegGroup group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept {
|
|
398
|
+
switch (group) {
|
|
399
|
+
case RegGroup::kVec:
|
|
400
|
+
xReg = xmm(0);
|
|
401
|
+
xInst = getXmmMovInst(frame);
|
|
402
|
+
xSize = xReg.size();
|
|
403
|
+
break;
|
|
404
|
+
case RegGroup::kX86_K:
|
|
405
|
+
xReg = k(0);
|
|
406
|
+
xInst = Inst::kIdKmovq;
|
|
407
|
+
xSize = xReg.size();
|
|
408
|
+
break;
|
|
409
|
+
case RegGroup::kX86_MM:
|
|
410
|
+
xReg = mm(0);
|
|
411
|
+
xInst = Inst::kIdMovq;
|
|
412
|
+
xSize = xReg.size();
|
|
413
|
+
break;
|
|
414
|
+
default:
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) {
|
|
420
|
+
Emitter* emitter = _emitter->as<Emitter>();
|
|
421
|
+
uint32_t gpSaved = frame.savedRegs(RegGroup::kGp);
|
|
422
|
+
|
|
423
|
+
Gp zsp = emitter->zsp(); // ESP|RSP register.
|
|
424
|
+
Gp zbp = emitter->zbp(); // EBP|RBP register.
|
|
425
|
+
Gp gpReg = zsp; // General purpose register (temporary).
|
|
426
|
+
Gp saReg = zsp; // Stack-arguments base pointer.
|
|
427
|
+
|
|
428
|
+
// Emit: 'push zbp'
|
|
429
|
+
// 'mov zbp, zsp'.
|
|
430
|
+
if (frame.hasPreservedFP()) {
|
|
431
|
+
gpSaved &= ~Support::bitMask(Gp::kIdBp);
|
|
432
|
+
ASMJIT_PROPAGATE(emitter->push(zbp));
|
|
433
|
+
ASMJIT_PROPAGATE(emitter->mov(zbp, zsp));
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Emit: 'push gp' sequence.
|
|
437
|
+
{
|
|
438
|
+
Support::BitWordIterator<RegMask> it(gpSaved);
|
|
439
|
+
while (it.hasNext()) {
|
|
440
|
+
gpReg.setId(it.next());
|
|
441
|
+
ASMJIT_PROPAGATE(emitter->push(gpReg));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Emit: 'mov saReg, zsp'.
|
|
446
|
+
uint32_t saRegId = frame.saRegId();
|
|
447
|
+
if (saRegId != BaseReg::kIdBad && saRegId != Gp::kIdSp) {
|
|
448
|
+
saReg.setId(saRegId);
|
|
449
|
+
if (frame.hasPreservedFP()) {
|
|
450
|
+
if (saRegId != Gp::kIdBp)
|
|
451
|
+
ASMJIT_PROPAGATE(emitter->mov(saReg, zbp));
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
ASMJIT_PROPAGATE(emitter->mov(saReg, zsp));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Emit: 'and zsp, StackAlignment'.
|
|
459
|
+
if (frame.hasDynamicAlignment()) {
|
|
460
|
+
ASMJIT_PROPAGATE(emitter->and_(zsp, -int32_t(frame.finalStackAlignment())));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Emit: 'sub zsp, StackAdjustment'.
|
|
464
|
+
if (frame.hasStackAdjustment()) {
|
|
465
|
+
ASMJIT_PROPAGATE(emitter->sub(zsp, frame.stackAdjustment()));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Emit: 'mov [zsp + DAOffset], saReg'.
|
|
469
|
+
if (frame.hasDynamicAlignment() && frame.hasDAOffset()) {
|
|
470
|
+
Mem saMem = ptr(zsp, int32_t(frame.daOffset()));
|
|
471
|
+
ASMJIT_PROPAGATE(emitter->mov(saMem, saReg));
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Emit 'movxxx [zsp + X], {[x|y|z]mm, k}'.
|
|
475
|
+
{
|
|
476
|
+
Reg xReg;
|
|
477
|
+
Mem xBase = ptr(zsp, int32_t(frame.extraRegSaveOffset()));
|
|
478
|
+
|
|
479
|
+
uint32_t xInst;
|
|
480
|
+
uint32_t xSize;
|
|
481
|
+
|
|
482
|
+
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup(1), RegGroup::kMaxVirt>{}) {
|
|
483
|
+
Support::BitWordIterator<RegMask> it(frame.savedRegs(group));
|
|
484
|
+
if (it.hasNext()) {
|
|
485
|
+
X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize);
|
|
486
|
+
do {
|
|
487
|
+
xReg.setId(it.next());
|
|
488
|
+
ASMJIT_PROPAGATE(emitter->emit(xInst, xBase, xReg));
|
|
489
|
+
xBase.addOffsetLo32(int32_t(xSize));
|
|
490
|
+
} while (it.hasNext());
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return kErrorOk;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) {
|
|
499
|
+
Emitter* emitter = _emitter->as<Emitter>();
|
|
500
|
+
|
|
501
|
+
uint32_t i;
|
|
502
|
+
uint32_t regId;
|
|
503
|
+
|
|
504
|
+
uint32_t registerSize = emitter->registerSize();
|
|
505
|
+
uint32_t gpSaved = frame.savedRegs(RegGroup::kGp);
|
|
506
|
+
|
|
507
|
+
Gp zsp = emitter->zsp(); // ESP|RSP register.
|
|
508
|
+
Gp zbp = emitter->zbp(); // EBP|RBP register.
|
|
509
|
+
Gp gpReg = emitter->zsp(); // General purpose register (temporary).
|
|
510
|
+
|
|
511
|
+
// Don't emit 'pop zbp' in the pop sequence, this case is handled separately.
|
|
512
|
+
if (frame.hasPreservedFP())
|
|
513
|
+
gpSaved &= ~Support::bitMask(Gp::kIdBp);
|
|
514
|
+
|
|
515
|
+
// Emit 'movxxx {[x|y|z]mm, k}, [zsp + X]'.
|
|
516
|
+
{
|
|
517
|
+
Reg xReg;
|
|
518
|
+
Mem xBase = ptr(zsp, int32_t(frame.extraRegSaveOffset()));
|
|
519
|
+
|
|
520
|
+
uint32_t xInst;
|
|
521
|
+
uint32_t xSize;
|
|
522
|
+
|
|
523
|
+
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup(1), RegGroup::kMaxVirt>{}) {
|
|
524
|
+
Support::BitWordIterator<RegMask> it(frame.savedRegs(group));
|
|
525
|
+
if (it.hasNext()) {
|
|
526
|
+
X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize);
|
|
527
|
+
do {
|
|
528
|
+
xReg.setId(it.next());
|
|
529
|
+
ASMJIT_PROPAGATE(emitter->emit(xInst, xReg, xBase));
|
|
530
|
+
xBase.addOffsetLo32(int32_t(xSize));
|
|
531
|
+
} while (it.hasNext());
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Emit 'emms' and/or 'vzeroupper'.
|
|
537
|
+
if (frame.hasMmxCleanup()) ASMJIT_PROPAGATE(emitter->emms());
|
|
538
|
+
if (frame.hasAvxCleanup()) ASMJIT_PROPAGATE(emitter->vzeroupper());
|
|
539
|
+
|
|
540
|
+
if (frame.hasPreservedFP()) {
|
|
541
|
+
// Emit 'mov zsp, zbp' or 'lea zsp, [zbp - x]'
|
|
542
|
+
int32_t count = int32_t(frame.pushPopSaveSize() - registerSize);
|
|
543
|
+
if (!count)
|
|
544
|
+
ASMJIT_PROPAGATE(emitter->mov(zsp, zbp));
|
|
545
|
+
else
|
|
546
|
+
ASMJIT_PROPAGATE(emitter->lea(zsp, ptr(zbp, -count)));
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
if (frame.hasDynamicAlignment() && frame.hasDAOffset()) {
|
|
550
|
+
// Emit 'mov zsp, [zsp + DsaSlot]'.
|
|
551
|
+
Mem saMem = ptr(zsp, int32_t(frame.daOffset()));
|
|
552
|
+
ASMJIT_PROPAGATE(emitter->mov(zsp, saMem));
|
|
553
|
+
}
|
|
554
|
+
else if (frame.hasStackAdjustment()) {
|
|
555
|
+
// Emit 'add zsp, StackAdjustment'.
|
|
556
|
+
ASMJIT_PROPAGATE(emitter->add(zsp, int32_t(frame.stackAdjustment())));
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Emit 'pop gp' sequence.
|
|
561
|
+
if (gpSaved) {
|
|
562
|
+
i = gpSaved;
|
|
563
|
+
regId = 16;
|
|
564
|
+
|
|
565
|
+
do {
|
|
566
|
+
regId--;
|
|
567
|
+
if (i & 0x8000) {
|
|
568
|
+
gpReg.setId(regId);
|
|
569
|
+
ASMJIT_PROPAGATE(emitter->pop(gpReg));
|
|
570
|
+
}
|
|
571
|
+
i <<= 1;
|
|
572
|
+
} while (regId != 0);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Emit 'pop zbp'.
|
|
576
|
+
if (frame.hasPreservedFP())
|
|
577
|
+
ASMJIT_PROPAGATE(emitter->pop(zbp));
|
|
578
|
+
|
|
579
|
+
// Emit 'ret' or 'ret x'.
|
|
580
|
+
if (frame.hasCalleeStackCleanup())
|
|
581
|
+
ASMJIT_PROPAGATE(emitter->emit(Inst::kIdRet, int(frame.calleeStackCleanup())));
|
|
582
|
+
else
|
|
583
|
+
ASMJIT_PROPAGATE(emitter->emit(Inst::kIdRet));
|
|
584
|
+
|
|
585
|
+
return kErrorOk;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
static Error ASMJIT_CDECL Emitter_emitProlog(BaseEmitter* emitter, const FuncFrame& frame) {
|
|
589
|
+
EmitHelper emitHelper(emitter, frame.isAvxEnabled(), frame.isAvx512Enabled());
|
|
590
|
+
return emitHelper.emitProlog(frame);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
static Error ASMJIT_CDECL Emitter_emitEpilog(BaseEmitter* emitter, const FuncFrame& frame) {
|
|
594
|
+
EmitHelper emitHelper(emitter, frame.isAvxEnabled(), frame.isAvx512Enabled());
|
|
595
|
+
return emitHelper.emitEpilog(frame);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
static Error ASMJIT_CDECL Emitter_emitArgsAssignment(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args) {
|
|
599
|
+
EmitHelper emitHelper(emitter, frame.isAvxEnabled(), frame.isAvx512Enabled());
|
|
600
|
+
return emitHelper.emitArgsAssignment(frame, args);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
void assignEmitterFuncs(BaseEmitter* emitter) {
|
|
604
|
+
emitter->_funcs.emitProlog = Emitter_emitProlog;
|
|
605
|
+
emitter->_funcs.emitEpilog = Emitter_emitEpilog;
|
|
606
|
+
emitter->_funcs.emitArgsAssignment = Emitter_emitArgsAssignment;
|
|
607
|
+
|
|
608
|
+
#ifndef ASMJIT_NO_LOGGING
|
|
609
|
+
emitter->_funcs.formatInstruction = FormatterInternal::formatInstruction;
|
|
610
|
+
#endif
|
|
611
|
+
|
|
612
|
+
#ifndef ASMJIT_NO_VALIDATION
|
|
613
|
+
emitter->_funcs.validate = InstInternal::validate;
|
|
614
|
+
#endif
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
ASMJIT_END_SUB_NAMESPACE
|
|
618
|
+
|
|
619
|
+
#endif // !ASMJIT_NO_X86
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
#ifndef ASMJIT_X86_X86EMITHELPER_P_H_INCLUDED
|
|
7
|
+
#define ASMJIT_X86_X86EMITHELPER_P_H_INCLUDED
|
|
8
|
+
|
|
9
|
+
#include "../core/api-config.h"
|
|
10
|
+
|
|
11
|
+
#include "../core/emithelper_p.h"
|
|
12
|
+
#include "../core/func.h"
|
|
13
|
+
#include "../x86/x86emitter.h"
|
|
14
|
+
#include "../x86/x86operand.h"
|
|
15
|
+
|
|
16
|
+
ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|
17
|
+
|
|
18
|
+
//! \cond INTERNAL
|
|
19
|
+
//! \addtogroup asmjit_x86
|
|
20
|
+
//! \{
|
|
21
|
+
|
|
22
|
+
static inline RegType vecTypeIdToRegType(TypeId typeId) noexcept {
|
|
23
|
+
return uint32_t(typeId) <= uint32_t(TypeId::_kVec128End) ? RegType::kX86_Xmm :
|
|
24
|
+
uint32_t(typeId) <= uint32_t(TypeId::_kVec256End) ? RegType::kX86_Ymm : RegType::kX86_Zmm;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class EmitHelper : public BaseEmitHelper {
|
|
28
|
+
public:
|
|
29
|
+
bool _avxEnabled;
|
|
30
|
+
bool _avx512Enabled;
|
|
31
|
+
|
|
32
|
+
inline explicit EmitHelper(BaseEmitter* emitter = nullptr, bool avxEnabled = false, bool avx512Enabled = false) noexcept
|
|
33
|
+
: BaseEmitHelper(emitter),
|
|
34
|
+
_avxEnabled(avxEnabled || avx512Enabled),
|
|
35
|
+
_avx512Enabled(avx512Enabled) {}
|
|
36
|
+
|
|
37
|
+
Error emitRegMove(
|
|
38
|
+
const Operand_& dst_,
|
|
39
|
+
const Operand_& src_, TypeId typeId, const char* comment = nullptr) override;
|
|
40
|
+
|
|
41
|
+
Error emitArgMove(
|
|
42
|
+
const BaseReg& dst_, TypeId dstTypeId,
|
|
43
|
+
const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) override;
|
|
44
|
+
|
|
45
|
+
Error emitRegSwap(
|
|
46
|
+
const BaseReg& a,
|
|
47
|
+
const BaseReg& b, const char* comment = nullptr) override;
|
|
48
|
+
|
|
49
|
+
Error emitProlog(const FuncFrame& frame);
|
|
50
|
+
Error emitEpilog(const FuncFrame& frame);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
void assignEmitterFuncs(BaseEmitter* emitter);
|
|
54
|
+
|
|
55
|
+
//! \}
|
|
56
|
+
//! \endcond
|
|
57
|
+
|
|
58
|
+
ASMJIT_END_SUB_NAMESPACE
|
|
59
|
+
|
|
60
|
+
#endif // ASMJIT_X86_X86EMITHELPER_P_H_INCLUDED
|