Added basic abstractions to CondCode, Gp, and Vec

* Each architecture now provides r32() and r64() functions for
    register casting
  * Each architecture now provides v128() function for register
    casting, returning just Vec to make writing cross platform
    code easier
  * Added some basic condition code abstractions so it can be used
    interchangeably across architectures
  * Added back unlicense to asmjit database (now it's dual licensed)
This commit is contained in:
kobalicek
2024-02-10 15:53:58 +01:00
parent a63d41e80b
commit 9e39b1e814
24 changed files with 253 additions and 65 deletions

View File

@@ -4,17 +4,17 @@
* Please use [Issues](https://github.com/asmjit/asmjit/issues) page to report bugs or create a [pull request](https://github.com/asmjit/asmjit/pulls) if you have already fixed it. * Please use [Issues](https://github.com/asmjit/asmjit/issues) page to report bugs or create a [pull request](https://github.com/asmjit/asmjit/pulls) if you have already fixed it.
* Make sure that when a bug is reported it provides as much information as possible to make it easy to either reproduce it locally or to at least guess where the problem could be. AsmJit is a low-level tool, which makes it very easy to emit code that would crash or not work as intended. Always use AsmJit's [Logging](https://asmjit.com/doc/group__asmjit__logging.html) and [Error Handling](https://asmjit.com/doc/group__asmjit__error__handling.html) features first to analyze whether there is not a simple to catch bug in your own code. * Make sure that when a bug is reported it provides as much information as possible to make it easy to either reproduce it locally or to at least guess where the problem could be. AsmJit is a low-level tool, which makes it very easy to emit code that would crash or not work as intended when executed. Always use AsmJit's [Logging](https://asmjit.com/doc/group__asmjit__logging.html) and [Error Handling](https://asmjit.com/doc/group__asmjit__error__handling.html) features first to analyze whether there is not a simple to catch bug in your own code.
* Don't be afraid to ask for help if you don't know how to solve a particular problem or in case it's unclear how to do it. The community would help if the problem is well described and has a solution. In general we always try to at least improve the documentation in case it doesn't provide enough information and users must ask for help. * Don't be afraid to ask for help if you don't know how to solve a particular problem or in case it's unclear how to do it. The community would help if the problem is well described and has a solution. In general we always try to at least improve the documentation in case it doesn't provide enough information and users must ask for help.
### Asking questions ### Asking questions
* We prefer GitHub issues to be used for reporting bugs or feature requests, but it's still okay to do that. Consider joining our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) to ask questions; it has an active community that can quickly. * We prefer GitHub issues to be used for reporting bugs or feature requests, but it's still okay to ask questions there as well. However, please consider joining our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im) to ask questions; it has an active community that can quickly respond.
### Suggesting feature requests ### Suggesting feature requests
* It's very likely that when using AsmJit you have found something that AsmJit doesn't provide and it would be handy to have it built-in. The [Issues](https://github.com/asmjit/asmjit/issues) page can be used to submit feature requests, but please keep in mind that AsmJit is a relatively small project and not all requested features will be accepted, especially if they are non-trivial, time consuming to implement, or the scope of the feature doesn't match AsmJit goals. * It's very likely that when using AsmJit you have found something that AsmJit doesn't provide, which would be handy to have as a built-in. The [Issues](https://github.com/asmjit/asmjit/issues) page can be used to submit feature requests, but please keep in mind that AsmJit is a relatively small project and not all requested features will be accepted, especially if they are non-trivial, time consuming to implement, or the scope of the feature doesn't match AsmJit goals.
* If you have already implemented the feature you are suggesting, please open a [pull request](https://github.com/asmjit/asmjit/pulls). * If you have already implemented the feature you are suggesting, please open a [pull request](https://github.com/asmjit/asmjit/pulls).
@@ -22,11 +22,11 @@
### Suggesting a documentation enhancement ### Suggesting a documentation enhancement
* [AsmJit's documentation](https://asmjit.com/doc/index.html) is auto-generated from source code, so if you would like to improve it just open a [pull request](https://github.com/asmjit/asmjit/pulls) with your changes. The documentation uses [Doxygen](https://www.doxygen.nl/) as a front-end, so please use `\ref`, etc... to create links in documentation when necessary. * [AsmJit's documentation](https://asmjit.com/doc/index.html) is auto-generated from source code, so if you would like to improve it just open a [pull request](https://github.com/asmjit/asmjit/pulls) with your changes. The documentation uses [Doxygen](https://www.doxygen.nl/) as a front-end, so you can use `\ref` keyword to create links and other Doxygen keywords to enhance the documentation.
### Suggesting a website content enhancement ### Suggesting a website content enhancement
* [AsmJit's website](https://asmjit.com) is also generated, but not from public sources at the moment. If you did find an issue on the website you can either use contact on the [support page](https://asmjit.com/support.html) or just discuss the change in our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im). Alternatively, opening a regular issue is also okay. * [AsmJit's website](https://asmjit.com) is also generated, but not from public sources at the moment. If you did find an issue on the website you can either use contact information on the [support page](https://asmjit.com/support.html) or to discuss the change on our [Gitter Chat](https://app.gitter.im/#/room/#asmjit:gitter.im). Alternatively, opening a regular issue is also okay.
## Coding Style & Consistency ## Coding Style & Consistency
@@ -47,7 +47,7 @@
* The code uses a soft limit of 120 characters per line (including documentation), but it's not enforced and it's okay to use more when it makes sense (for example defining tables, etc...). * The code uses a soft limit of 120 characters per line (including documentation), but it's not enforced and it's okay to use more when it makes sense (for example defining tables, etc...).
* Since AsmJit doesn't use Exceptions nor RTTI the code cannot use containers provided by the C++ standard library as they use exception handling by design. In general, we try to only use a bare minimum from the C++ standard library to make it viable to use AsmJit even in C code bases where JIT complier is implemented in C++ ([Erlang](https://www.erlang.org/) can be seen as a great example). * Since AsmJit doesn't use Exceptions nor RTTI the code cannot use containers provided by the C++ standard library. In general, we try to only use a bare minimum from the C++ standard library to make it viable to use AsmJit even in C code bases where JIT complier is implemented in C++ ([Erlang](https://www.erlang.org/) can be seen as a great example).
## Testing ## Testing
@@ -79,7 +79,7 @@
* ABI changes happen, but they are usually accumulated and committed within a short time window to not break it often. In general we prefer to break ABI once a year, or once 6 months if there is something that has a high priority. There are no hard rules though. * ABI changes happen, but they are usually accumulated and committed within a short time window to not break it often. In general we prefer to break ABI once a year, or once 6 months if there is something that has a high priority. There are no hard rules though.
* AsmJit uses an `inline namespace`, which should make it impossible to link to AsmJit library that is ABI incompatible. When ABI break happens AsmJit version and ABI namespace is changed, see [asmjit/core/api-config.h](./src/asmjit/core/api-config.h) for more details. * AsmJit uses an `inline namespace`, which should make it impossible to link to AsmJit library that is ABI incompatible. When ABI break happens both AsmJit version and ABI namespace are changed, see [asmjit/core/api-config.h](./src/asmjit/core/api-config.h) for more details.
* What is an ABI break? * What is an ABI break?
@@ -87,9 +87,9 @@
* Adding/removing virtual functions to/from classes, respectively * Adding/removing virtual functions to/from classes, respectively
* Changing a signature of a public function or a class member function. * Changing a signature of a public function or a class member function (for example adding a parameter).
* Changing the value of an enum or global constant (for example instructions are now sorted by name, so adding a new instruction is an ABI break) * Changing the value of an enum or global constant (for example instructions are now sorted by name, so adding a new instruction breaks ABI)
* Possibly more, but these were the most common... * Possibly more, but these were the most common...
@@ -97,4 +97,6 @@
* Extending the functionality by using reserved members of a struct/class * Extending the functionality by using reserved members of a struct/class
* Adding new API including new structs and classes
* Changing anything that is internal and that doesn't leak to public headers * Changing anything that is internal and that doesn't leak to public headers

26
db/LICENSE.md Normal file
View File

@@ -0,0 +1,26 @@
AsmJit database is dual licensed under Zlib and Unlicense (public domain)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>

View File

@@ -14,3 +14,8 @@ To Be Documented
---------------- ----------------
This project will be refactored and documented in the future. This project will be refactored and documented in the future.
License
-------
AsmJit database is dual licensed under Zlib (AsmJit license) or public domain. The database can be used for any purpose, not just by AsmJit.

View File

@@ -1,8 +1,7 @@
// This file is part of AsmJit project <https://asmjit.com> // This file is part of AsmJit project <https://asmjit.com>
// //
// See asmjit.h or LICENSE.md for license and copyright information // See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib // SPDX-License-Identifier: (Zlib or Unlicense)
(function($scope, $as) { (function($scope, $as) {
"use strict"; "use strict";

View File

@@ -1,8 +1,7 @@
// This file is part of AsmJit project <https://asmjit.com> // This file is part of AsmJit project <https://asmjit.com>
// //
// See asmjit.h or LICENSE.md for license and copyright information // See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib // SPDX-License-Identifier: (Zlib or Unlicense)
(function($scope, $as) { (function($scope, $as) {
"use strict"; "use strict";

View File

@@ -1,7 +1,7 @@
// This file is part of AsmJit project <https://asmjit.com> // This file is part of AsmJit project <https://asmjit.com>
// //
// See asmjit.h or LICENSE.md for license and copyright information // See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib // SPDX-License-Identifier: (Zlib or Unlicense)
(function($scope, $as) { (function($scope, $as) {
"use strict"; "use strict";

View File

@@ -1,7 +1,7 @@
// This file is part of AsmJit project <https://asmjit.com> // This file is part of AsmJit project <https://asmjit.com>
// //
// See asmjit.h or LICENSE.md for license and copyright information // See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib // SPDX-License-Identifier: (Zlib or Unlicense)
(function($scope, $as) { (function($scope, $as) {
"use strict"; "use strict";

View File

@@ -1,7 +1,7 @@
// This file is part of AsmJit project <https://asmjit.com> // This file is part of AsmJit project <https://asmjit.com>
// //
// See asmjit.h or LICENSE.md for license and copyright information // See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib // SPDX-License-Identifier: (Zlib or Unlicense)
"use strict"; "use strict";

View File

@@ -1,7 +1,7 @@
// This file is part of AsmJit project <https://asmjit.com> // This file is part of AsmJit project <https://asmjit.com>
// //
// See asmjit.h or LICENSE.md for license and copyright information // See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib // SPDX-License-Identifier: (Zlib or Unlicense)
(function($scope, $as) { (function($scope, $as) {
"use strict"; "use strict";

View File

@@ -31,7 +31,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction(
// Format instruction options and instruction mnemonic. // Format instruction options and instruction mnemonic.
InstId instId = inst.realId(); InstId instId = inst.realId();
if (instId < Inst::_kIdCount) if (instId != Inst::kIdNone && instId < Inst::_kIdCount)
ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb)); ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb));
else else
ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId)));

View File

@@ -47,7 +47,7 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Enviro
cc.setSaveRestoreRegSize(RegGroup::kVec, 8); cc.setSaveRestoreRegSize(RegGroup::kVec, 8);
cc.setSaveRestoreAlignment(RegGroup::kGp, 16); cc.setSaveRestoreAlignment(RegGroup::kGp, 16);
cc.setSaveRestoreAlignment(RegGroup::kVec, 16); cc.setSaveRestoreAlignment(RegGroup::kVec, 16);
cc.setSaveRestoreAlignment(RegGroup::kExtraVirt2, 1); cc.setSaveRestoreAlignment(RegGroup::kMask, 1);
cc.setSaveRestoreAlignment(RegGroup::kExtraVirt3, 1); cc.setSaveRestoreAlignment(RegGroup::kExtraVirt3, 1);
cc.setPassedOrder(RegGroup::kGp, 0, 1, 2, 3, 4, 5, 6, 7); cc.setPassedOrder(RegGroup::kGp, 0, 1, 2, 3, 4, 5, 6, 7);
cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7);

View File

@@ -55,8 +55,12 @@ public:
//! Cast this register to a 32-bit W register (returns a new operand). //! Cast this register to a 32-bit W register (returns a new operand).
ASMJIT_INLINE_NODEBUG GpW w() const noexcept; ASMJIT_INLINE_NODEBUG GpW w() const noexcept;
//! \overload
ASMJIT_INLINE_NODEBUG GpW r32() const noexcept;
//! Cast this register to a 64-bit X register (returns a new operand). //! Cast this register to a 64-bit X register (returns a new operand).
ASMJIT_INLINE_NODEBUG GpX x() const noexcept; ASMJIT_INLINE_NODEBUG GpX x() const noexcept;
//! \overload
ASMJIT_INLINE_NODEBUG GpX r64() const noexcept;
}; };
//! 32-bit general purpose W register (AArch64). //! 32-bit general purpose W register (AArch64).
@@ -67,6 +71,8 @@ class GpX : public Gp { ASMJIT_DEFINE_FINAL_REG(GpX, Gp, RegTraits<RegType::kARM
#ifndef _DOXYGEN #ifndef _DOXYGEN
ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); } ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); }
ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); } ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); }
ASMJIT_INLINE_NODEBUG GpW Gp::r32() const noexcept { return GpW(id()); }
ASMJIT_INLINE_NODEBUG GpX Gp::r64() const noexcept { return GpX(id()); }
#endif #endif
//! Vector element type (AArch64). //! Vector element type (AArch64).
@@ -153,6 +159,17 @@ public:
//! Cast this register to a 128-bit V register. //! Cast this register to a 128-bit V register.
ASMJIT_INLINE_NODEBUG VecV v() const noexcept; ASMJIT_INLINE_NODEBUG VecV v() const noexcept;
//! Casts this register to b (clone).
ASMJIT_INLINE_NODEBUG Vec v8() const noexcept;
//! Casts this register to h (clone).
ASMJIT_INLINE_NODEBUG Vec v16() const noexcept;
//! Casts this register to s (clone).
ASMJIT_INLINE_NODEBUG Vec v32() const noexcept;
//! Casts this register to d (clone).
ASMJIT_INLINE_NODEBUG Vec v64() const noexcept;
//! Casts this register to q (clone).
ASMJIT_INLINE_NODEBUG Vec v128() const noexcept;
//! Cast this register to a 128-bit V.B[elementIndex] register. //! Cast this register to a 128-bit V.B[elementIndex] register.
ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept; ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept;
//! Cast this register to a 128-bit V.H[elementIndex] register. //! Cast this register to a 128-bit V.H[elementIndex] register.
@@ -229,6 +246,12 @@ ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); } ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); } ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v8() const noexcept { return VecB(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v16() const noexcept { return VecH(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v32() const noexcept { return VecS(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v64() const noexcept { return VecD(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v128() const noexcept { return VecV(id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kB, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kH, elementIndex), id()); }
ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kS, elementIndex), id()); } ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(VecElementType::kS, elementIndex), id()); }

View File

@@ -595,14 +595,14 @@ void ARMRAPass::onInit() noexcept {
_archTraits = &ArchTraits::byArch(arch); _archTraits = &ArchTraits::byArch(arch);
_physRegCount.set(RegGroup::kGp, 32); _physRegCount.set(RegGroup::kGp, 32);
_physRegCount.set(RegGroup::kVec, 32); _physRegCount.set(RegGroup::kVec, 32);
_physRegCount.set(RegGroup::kExtraVirt2, 0); _physRegCount.set(RegGroup::kMask, 0);
_physRegCount.set(RegGroup::kExtraVirt3, 0); _physRegCount.set(RegGroup::kExtraVirt3, 0);
_buildPhysIndex(); _buildPhysIndex();
_availableRegCount = _physRegCount; _availableRegCount = _physRegCount;
_availableRegs[RegGroup::kGp] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kGp)); _availableRegs[RegGroup::kGp] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kGp));
_availableRegs[RegGroup::kVec] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kVec)); _availableRegs[RegGroup::kVec] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kVec));
_availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt2)); _availableRegs[RegGroup::kMask] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kMask));
_availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt3)); _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt3));
_scratchRegIndexes[0] = uint8_t(27); _scratchRegIndexes[0] = uint8_t(27);

View File

@@ -555,6 +555,12 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand(
if (op.isImm()) { if (op.isImm()) {
const Imm& i = op.as<Imm>(); const Imm& i = op.as<Imm>();
int64_t val = i.value(); int64_t val = i.value();
uint32_t predicate = i.predicate();
if (predicate) {
ASMJIT_PROPAGATE(formatShiftOp(sb, ShiftOp(predicate)));
ASMJIT_PROPAGATE(sb.append(' '));
}
if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) { if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) {
ASMJIT_PROPAGATE(sb.append("0x")); ASMJIT_PROPAGATE(sb.append("0x"));

View File

@@ -68,6 +68,17 @@ public:
//! Gets whether the register is a VEC-V register (128-bit). //! Gets whether the register is a VEC-V register (128-bit).
ASMJIT_INLINE_NODEBUG constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } ASMJIT_INLINE_NODEBUG constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; }
//! Gets whether the register is an 8-bit vector register or view, alias if \ref isVecB().
ASMJIT_INLINE_NODEBUG constexpr bool isVec8() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; }
//! Gets whether the register is a 16-bit vector register or view, alias if \ref isVecH().
ASMJIT_INLINE_NODEBUG constexpr bool isVec16() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; }
//! Gets whether the register is a 32-bit vector register or view, alias if \ref isVecS().
ASMJIT_INLINE_NODEBUG constexpr bool isVec32() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; }
//! Gets whether the register is a 64-bit vector register or view, alias if \ref isVecD().
ASMJIT_INLINE_NODEBUG constexpr bool isVec64() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; }
//! Gets whether the register is a 128-bit vector register or view, alias if \ref isVecQ().
ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; }
template<RegType kRegType> template<RegType kRegType>
ASMJIT_INLINE_NODEBUG void setRegT(uint32_t id) noexcept { ASMJIT_INLINE_NODEBUG void setRegT(uint32_t id) noexcept {
setSignature(RegTraits<kRegType>::kSignature); setSignature(RegTraits<kRegType>::kSignature);
@@ -212,7 +223,7 @@ public:
Signature::fromValue<kSignatureMemShiftValueMask>(shift.value()) | Signature::fromValue<kSignatureMemShiftValueMask>(shift.value()) |
signature, base.id(), index.id(), 0) {} signature, base.id(), index.id(), 0) {}
ASMJIT_INLINE_NODEBUG constexpr Mem(uint64_t base, Signature signature = Signature{0}) noexcept ASMJIT_INLINE_NODEBUG constexpr explicit Mem(uint64_t base, Signature signature = Signature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) | : BaseMem(Signature::fromOpType(OperandType::kMem) |
signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {} signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {}

View File

@@ -127,6 +127,13 @@ static ASMJIT_INLINE_NODEBUG bool isLogicalImm(uint64_t imm, uint32_t width) noe
return encodeLogicalImm(imm, width, &dummy); return encodeLogicalImm(imm, width, &dummy);
} }
//! Returns true if the given `imm` value is encodable as an immediate with `add` and `sub` instructions on AArch64.
//! These two instructions can encode 12-bit immediate value optionally shifted left by 12 bits.
ASMJIT_MAYBE_UNUSED
static ASMJIT_INLINE_NODEBUG bool isAddSubImm(uint64_t imm) noexcept {
return imm <= 0xFFFu || (imm & ~uint64_t(0xFFFu << 12)) == 0;
}
//! Returns true if the given `imm` value is a byte mask. Byte mask has each byte part of the value set to either //! Returns true if the given `imm` value is a byte mask. Byte mask has each byte part of the value set to either
//! 0x00 or 0xFF. Some ARM instructions accept immediates that form a byte-mask and this function can be used to //! 0x00 or 0xFF. Some ARM instructions accept immediates that form a byte-mask and this function can be used to
//! verify that the immediate is encodable before using the value. //! verify that the immediate is encodable before using the value.

View File

@@ -42,21 +42,24 @@ enum class CondCode : uint8_t {
kGT = 0x0Eu, //!< Z==0 & N==V (signed > ) kGT = 0x0Eu, //!< Z==0 & N==V (signed > )
kLE = 0x0Fu, //!< Z==1 | N!=V (signed <=) kLE = 0x0Fu, //!< Z==1 | N!=V (signed <=)
kSign = kMI, //!< Sign. kZero = kEQ, //!< Zero flag (alias to equal).
kNotSign = kPL, //!< Not sign. kNotZero = kNE, //!< Not zero (alias to Not Equal).
kOverflow = kVS, //!< Signed overflow.
kNotOverflow = kVC, //!< Not signed overflow.
kEqual = kEQ, //!< Equal `a == b`. kEqual = kEQ, //!< Equal `a == b`.
kNotEqual = kNE, //!< Not Equal `a != b`. kNotEqual = kNE, //!< Not Equal `a != b`.
kZero = kEQ, //!< Zero (alias to equal). kCarry = kCS, //!< Carry flag.
kNotZero = kNE, //!< Not Zero (alias to Not Equal). kNotCarry = kCC, //!< Not carry.
kSign = kMI, //!< Sign flag.
kNotSign = kPL, //!< Not sign.
kNegative = kMI, //!< Negative. kNegative = kMI, //!< Negative.
kPositive = kPL, //!< Positive or zero. kPositive = kPL, //!< Positive or zero.
kOverflow = kVS, //!< Signed overflow.
kNotOverflow = kVC, //!< Not signed overflow.
kSignedLT = kLT, //!< Signed `a < b`. kSignedLT = kLT, //!< Signed `a < b`.
kSignedLE = kLE, //!< Signed `a <= b`. kSignedLE = kLE, //!< Signed `a <= b`.
kSignedGT = kGT, //!< Signed `a > b`. kSignedGT = kGT, //!< Signed `a > b`.
@@ -67,11 +70,38 @@ enum class CondCode : uint8_t {
kUnsignedGT = kHI, //!< Unsigned `a > b`. kUnsignedGT = kHI, //!< Unsigned `a > b`.
kUnsignedGE = kHS, //!< Unsigned `a >= b`. kUnsignedGE = kHS, //!< Unsigned `a >= b`.
kBTZero = kZero, //!< Tested bit is zero.
kBTNotZero = kNotZero, //!< Tested bit is not zero.
kAlways = kAL, //!< No condition code (always). kAlways = kAL, //!< No condition code (always).
kMaxValue = 0x0Fu //!< Maximum value of `CondCode`. kMaxValue = 0x0Fu //!< Maximum value of `CondCode`.
}; };
//! \cond
static constexpr CondCode _reverseCondTable[] = {
CondCode::kAL, // AL <- AL
CondCode::kNA, // NA <- NA
CondCode::kEQ, // EQ <- EQ
CondCode::kNE, // NE <- NE
CondCode::kLS, // LS <- CS
CondCode::kHI, // HI <- LO
CondCode::kMI, // MI <- MI
CondCode::kPL, // PL <- PL
CondCode::kVS, // VS <- VS
CondCode::kVC, // VC <- VC
CondCode::kLO, // LO <- HI
CondCode::kCS, // CS <- LS
CondCode::kLE, // LE <- GE
CondCode::kGT, // GT <- LT
CondCode::kLT, // LT <- GT
CondCode::kGE // GE <- LE
};
//! \endcond
//! Reverses a condition code (reverses the corresponding operands of a comparison).
static ASMJIT_INLINE_NODEBUG constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; }
//! Negates a condition code. //! Negates a condition code.
static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); } static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); }

View File

@@ -163,6 +163,8 @@ public:
//! //!
//! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* fmt, ...); ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* fmt, ...);
//! \overload
inline Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId) { return _newRegFmt(out, typeId, nullptr); }
//! Creates a new virtual register compatible with the provided reference register `ref`. //! Creates a new virtual register compatible with the provided reference register `ref`.
ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* name = nullptr); ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* name = nullptr);

View File

@@ -173,8 +173,8 @@ enum class RegGroup : uint8_t {
//! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers. //! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers.
kVec = 1, kVec = 1,
//! Extra virtual group #2 that can be used by Compiler for register allocation. //! Mask register group compatible with all backends that can use masking.
kExtraVirt2 = 2, kMask = 2,
//! Extra virtual group #3 that can be used by Compiler for register allocation. //! Extra virtual group #3 that can be used by Compiler for register allocation.
kExtraVirt3 = 3, kExtraVirt3 = 3,
@@ -187,8 +187,8 @@ enum class RegGroup : uint8_t {
// X86 Specific Register Groups // X86 Specific Register Groups
// ---------------------------- // ----------------------------
//! K register group (KReg) - maps to \ref RegGroup::kExtraVirt2 (X86, X86_64). //! K register group (KReg) - maps to \ref RegGroup::kMask (X86, X86_64).
kX86_K = kExtraVirt2, kX86_K = kMask,
//! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64). //! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64).
kX86_MM = kExtraVirt3, kX86_MM = kExtraVirt3,
@@ -591,6 +591,22 @@ struct Operand_ {
//! \} //! \}
//! \name Equality
//! \{
//! Tests whether the operand is 100% equal to `other` operand.
//!
//! \note This basically performs a binary comparison, if aby bit is
//! different the operands are not equal.
ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept {
return bool(unsigned(_signature == other._signature) &
unsigned(_baseId == other._baseId ) &
unsigned(_data[0] == other._data[0] ) &
unsigned(_data[1] == other._data[1] ));
}
//! \}
//! \name Accessors //! \name Accessors
//! \{ //! \{
@@ -609,6 +625,8 @@ struct Operand_ {
//! //!
//! \note Improper use of `setSignature()` can lead to hard-to-debug errors. //! \note Improper use of `setSignature()` can lead to hard-to-debug errors.
ASMJIT_INLINE_NODEBUG void setSignature(const Signature& signature) noexcept { _signature = signature; } ASMJIT_INLINE_NODEBUG void setSignature(const Signature& signature) noexcept { _signature = signature; }
//! \overload
ASMJIT_INLINE_NODEBUG void setSignature(uint32_t signature) noexcept { _signature._bits = signature; }
//! Returns the type of the operand, see `OpType`. //! Returns the type of the operand, see `OpType`.
ASMJIT_INLINE_NODEBUG constexpr OperandType opType() const noexcept { return _signature.opType(); } ASMJIT_INLINE_NODEBUG constexpr OperandType opType() const noexcept { return _signature.opType(); }
@@ -643,32 +661,53 @@ struct Operand_ {
//! not initialized. //! not initialized.
ASMJIT_INLINE_NODEBUG constexpr uint32_t id() const noexcept { return _baseId; } ASMJIT_INLINE_NODEBUG constexpr uint32_t id() const noexcept { return _baseId; }
//! Tests whether the operand is 100% equal to `other` operand.
//!
//! \note This basically performs a binary comparison, if aby bit is
//! different the operands are not equal.
ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept {
return bool(unsigned(_signature == other._signature) &
unsigned(_baseId == other._baseId ) &
unsigned(_data[0] == other._data[0] ) &
unsigned(_data[1] == other._data[1] ));
}
//! Tests whether the operand is a register matching the given register `type`. //! Tests whether the operand is a register matching the given register `type`.
ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType type) const noexcept { ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType type) const noexcept {
return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type)); return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type));
} }
//! Tests whether the operand is a register of the provided register group `regGroup`.
ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegGroup regGroup) const noexcept {
return _signature.subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(regGroup));
}
//! Tests whether the operand is register and of register type `regType` and `regId`.
ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType regType, uint32_t regId) const noexcept { return isReg(regType) && _baseId == regId; }
//! Tests whether the operand is register and of register group `regGroup` and `regId`.
ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegGroup regGroup, uint32_t regId) const noexcept { return isReg(regGroup) && _baseId == regId; }
//! Tests whether the register is a general purpose register (any size).
ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isReg(RegGroup::kGp); }
//! Tests whether the register is a 32-bit general purpose register.
ASMJIT_INLINE_NODEBUG constexpr bool isGp32() const noexcept { return isReg(RegType::kGp32); }
//! Tests whether the register is a 64-bit general purpose register.
ASMJIT_INLINE_NODEBUG constexpr bool isGp64() const noexcept { return isReg(RegType::kGp64); }
//! Tests whether the register is a vector register of any size.
ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isReg(RegGroup::kVec); }
//! Tests whether the register is an 8-bit vector register or view (AArch64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec8() const noexcept { return isReg(RegType::kVec8); }
//! Tests whether the register is a 16-bit vector register or view (AArch64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec16() const noexcept { return isReg(RegType::kVec16); }
//! Tests whether the register is a 32-bit vector register or view (AArch32, AArch64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec32() const noexcept { return isReg(RegType::kVec32); }
//! Tests whether the register is a 64-bit vector register or view (AArch32, AArch64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec64() const noexcept { return isReg(RegType::kVec64); }
//! Tests whether the register is a 128-bit vector register or view (AArch32, AArch64, X86, X86_64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return isReg(RegType::kVec128); }
//! Tests whether the register is a 256-bit vector register or view (X86, X86_64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec256() const noexcept { return isReg(RegType::kVec256); }
//! Tests whether the register is a 512-bit vector register or view (X86, X86_64).
ASMJIT_INLINE_NODEBUG constexpr bool isVec512() const noexcept { return isReg(RegType::kVec512); }
//! Tests whether the register is a mask register of any size.
ASMJIT_INLINE_NODEBUG constexpr bool isMask() const noexcept { return isReg(RegGroup::kMask); }
//! Tests whether the operand is a register matching the given register `type`. //! Tests whether the operand is a register matching the given register `type`.
ASMJIT_INLINE_NODEBUG constexpr bool isRegList(RegType type) const noexcept { ASMJIT_INLINE_NODEBUG constexpr bool isRegList(RegType type) const noexcept {
return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kRegList) | Signature::fromRegType(type)); return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kRegList) | Signature::fromRegType(type));
} }
//! Tests whether the operand is register and of register `type` and `id`.
ASMJIT_INLINE_NODEBUG constexpr bool isReg(RegType type, uint32_t regId) const noexcept {
return isReg(type) && _baseId == regId;
}
//! Tests whether the operand is a register or memory. //! Tests whether the operand is a register or memory.
//! //!
//! \note This is useful on X86 and X86_64 architectures as many instructions support Reg/Mem operand combination. //! \note This is useful on X86 and X86_64 architectures as many instructions support Reg/Mem operand combination.
@@ -951,8 +990,10 @@ public:
//! Tests whether the register is a general purpose register (any size). //! Tests whether the register is a general purpose register (any size).
ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } ASMJIT_INLINE_NODEBUG constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); }
//! Tests whether the register is a vector register. //! Tests whether the register is a vector register of any size.
ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } ASMJIT_INLINE_NODEBUG constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); }
//! Tests whether the register is a mask register of any size.
ASMJIT_INLINE_NODEBUG constexpr bool isMask() const noexcept { return isGroup(RegGroup::kMask); }
using Operand_::isReg; using Operand_::isReg;

View File

@@ -67,7 +67,7 @@ public:
uint32_t registerCount = arch == Arch::kX86 ? 8 : 16; uint32_t registerCount = arch == Arch::kX86 ? 8 : 16;
_availableRegs[RegGroup::kGp] = Support::lsbMask<RegMask>(registerCount) & ~Support::bitMask(4u); _availableRegs[RegGroup::kGp] = Support::lsbMask<RegMask>(registerCount) & ~Support::bitMask(4u);
_availableRegs[RegGroup::kVec] = Support::lsbMask<RegMask>(registerCount); _availableRegs[RegGroup::kVec] = Support::lsbMask<RegMask>(registerCount);
_availableRegs[RegGroup::kExtraVirt2] = Support::lsbMask<RegMask>(8); _availableRegs[RegGroup::kMask] = Support::lsbMask<RegMask>(8);
_availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<RegMask>(8); _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<RegMask>(8);
return kErrorOk; return kErrorOk;
} }
@@ -75,7 +75,7 @@ public:
case Arch::kAArch64: { case Arch::kAArch64: {
_availableRegs[RegGroup::kGp] = 0xFFFFFFFFu & ~Support::bitMask(18, 31u); _availableRegs[RegGroup::kGp] = 0xFFFFFFFFu & ~Support::bitMask(18, 31u);
_availableRegs[RegGroup::kVec] = 0xFFFFFFFFu; _availableRegs[RegGroup::kVec] = 0xFFFFFFFFu;
_availableRegs[RegGroup::kExtraVirt2] = 0; _availableRegs[RegGroup::kMask] = 0;
_availableRegs[RegGroup::kExtraVirt3] = 0; _availableRegs[RegGroup::kExtraVirt3] = 0;
return kErrorOk; return kErrorOk;
} }

View File

@@ -542,7 +542,7 @@ public:
template<typename RegT> template<typename RegT>
ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref) { ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref) {
RegT reg(Globals::NoInit); RegT reg(Globals::NoInit);
_newReg(reg, ref); _newReg(&reg, ref);
return reg; return reg;
} }

View File

@@ -53,20 +53,23 @@ enum class CondCode : uint8_t {
kNLE = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) kNLE = 0x0Fu, //!< ZF==0 & SF==OF (signed > )
kZero = kZ, //!< Zero flag. kZero = kZ, //!< Zero flag.
kNotZero = kNZ, //!< Non-zero flag. kNotZero = kNZ, //!< Not zero.
kSign = kS, //!< Sign flag.
kNotSign = kNS, //!< No sign flag.
kNegative = kS, //!< Sign flag.
kPositive = kNS, //!< No sign flag.
kOverflow = kO, //!< Overflow (signed).
kNotOverflow = kNO, //!< Not overflow (signed).
kEqual = kE, //!< `a == b` (equal). kEqual = kE, //!< `a == b` (equal).
kNotEqual = kNE, //!< `a != b` (not equal). kNotEqual = kNE, //!< `a != b` (not equal).
kCarry = kC, //!< Carry flag.
kNotCarry = kNC, //!< Not carry.
kSign = kS, //!< Sign flag.
kNotSign = kNS, //!< Not sign.
kNegative = kS, //!< Sign flag.
kPositive = kNS, //!< Not sign.
kOverflow = kO, //!< Overflow (signed).
kNotOverflow = kNO, //!< Not overflow (signed).
kSignedLT = kL, //!< `a < b` (signed). kSignedLT = kL, //!< `a < b` (signed).
kSignedLE = kLE, //!< `a <= b` (signed). kSignedLE = kLE, //!< `a <= b` (signed).
kSignedGT = kG, //!< `a > b` (signed). kSignedGT = kG, //!< `a > b` (signed).
@@ -77,6 +80,9 @@ enum class CondCode : uint8_t {
kUnsignedGT = kA, //!< `a > b` (unsigned). kUnsignedGT = kA, //!< `a > b` (unsigned).
kUnsignedGE = kAE, //!< `a >= b` (unsigned). kUnsignedGE = kAE, //!< `a >= b` (unsigned).
kBTZero = kNC, //!< Tested bit is zero.
kBTNotZero = kC, //!< Tested bit is non-zero.
kParityEven = kP, //!< Even parity flag. kParityEven = kP, //!< Even parity flag.
kParityOdd = kPO, //!< Odd parity flag. kParityOdd = kPO, //!< Odd parity flag.

View File

@@ -1315,6 +1315,10 @@ Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, siz
out->_operands[0].reset(W, size0); out->_operands[0].reset(W, size0);
out->_operands[1].reset(R | MibRead, size1); out->_operands[1].reset(R | MibRead, size1);
if (BaseReg::isVec(operands[0]))
rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>());
return kErrorOk; return kErrorOk;
} }
@@ -1366,6 +1370,9 @@ Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, siz
out->_operands[0].reset(W, size0); out->_operands[0].reset(W, size0);
out->_operands[1].reset(R, size1); out->_operands[1].reset(R, size1);
if (BaseReg::isVec(operands[0]))
rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>());
if (operands[0].isReg() && operands[1].isReg()) { if (operands[0].isReg() && operands[1].isReg()) {
if (instRmInfo.rmOpsMask & 0x1) { if (instRmInfo.rmOpsMask & 0x1) {
out->_operands[0].addOpFlags(RegM); out->_operands[0].addOpFlags(RegM);

View File

@@ -88,12 +88,26 @@ public:
ASMJIT_INLINE_NODEBUG constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); } ASMJIT_INLINE_NODEBUG constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); }
//! Tests whether the register is a GPQ register (64-bit). //! Tests whether the register is a GPQ register (64-bit).
ASMJIT_INLINE_NODEBUG constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); } ASMJIT_INLINE_NODEBUG constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); }
//! Tests whether the register is a 32-bit general purpose register, alias of \ref isGpd().
ASMJIT_INLINE_NODEBUG constexpr bool isGp32() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); }
//! Tests whether the register is a 64-bit general purpose register, alias of \ref isGpq()
ASMJIT_INLINE_NODEBUG constexpr bool isGp64() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); }
//! Tests whether the register is an XMM register (128-bit). //! Tests whether the register is an XMM register (128-bit).
ASMJIT_INLINE_NODEBUG constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); } ASMJIT_INLINE_NODEBUG constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); }
//! Tests whether the register is a YMM register (256-bit). //! Tests whether the register is a YMM register (256-bit).
ASMJIT_INLINE_NODEBUG constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); } ASMJIT_INLINE_NODEBUG constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); }
//! Tests whether the register is a ZMM register (512-bit). //! Tests whether the register is a ZMM register (512-bit).
ASMJIT_INLINE_NODEBUG constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); } ASMJIT_INLINE_NODEBUG constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); }
//! Tests whether the register is a 128-bit vector register, alias of \ref isXmm().
ASMJIT_INLINE_NODEBUG constexpr bool isVec128() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); }
//! Tests whether the register is a 256-bit vector register, alias of \ref isYmm().
ASMJIT_INLINE_NODEBUG constexpr bool isVec256() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); }
//! Tests whether the register is a 512-bit vector register, alias of \ref isZmm().
ASMJIT_INLINE_NODEBUG constexpr bool isVec512() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); }
//! Tests whether the register is an MMX register (64-bit). //! Tests whether the register is an MMX register (64-bit).
ASMJIT_INLINE_NODEBUG constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); } ASMJIT_INLINE_NODEBUG constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); }
//! Tests whether the register is a K register (64-bit). //! Tests whether the register is a K register (64-bit).
@@ -242,11 +256,18 @@ class Vec : public Reg {
//! Casts this register to XMM (clone). //! Casts this register to XMM (clone).
ASMJIT_INLINE_NODEBUG Xmm xmm() const noexcept; ASMJIT_INLINE_NODEBUG Xmm xmm() const noexcept;
//! Casts this register to YMM. //! Casts this register to YMM (clone).
ASMJIT_INLINE_NODEBUG Ymm ymm() const noexcept; ASMJIT_INLINE_NODEBUG Ymm ymm() const noexcept;
//! Casts this register to ZMM. //! Casts this register to ZMM (clone).
ASMJIT_INLINE_NODEBUG Zmm zmm() const noexcept; ASMJIT_INLINE_NODEBUG Zmm zmm() const noexcept;
//! Casts this register to XMM (clone).
ASMJIT_INLINE_NODEBUG Vec v128() const noexcept;
//! Casts this register to YMM (clone).
ASMJIT_INLINE_NODEBUG Vec v256() const noexcept;
//! Casts this register to ZMM (clone).
ASMJIT_INLINE_NODEBUG Vec v512() const noexcept;
//! Casts this register to a register that has half the size (or XMM if it's already XMM). //! Casts this register to a register that has half the size (or XMM if it's already XMM).
ASMJIT_INLINE_NODEBUG Vec half() const noexcept { ASMJIT_INLINE_NODEBUG Vec half() const noexcept {
return Vec(type() == RegType::kX86_Zmm ? signatureOfT<RegType::kX86_Ymm>() : signatureOfT<RegType::kX86_Xmm>(), id()); return Vec(type() == RegType::kX86_Zmm ? signatureOfT<RegType::kX86_Ymm>() : signatureOfT<RegType::kX86_Xmm>(), id());
@@ -344,6 +365,9 @@ ASMJIT_INLINE_NODEBUG Gpq Gp::r64() const noexcept { return Gpq(id()); }
ASMJIT_INLINE_NODEBUG Xmm Vec::xmm() const noexcept { return Xmm(id()); } ASMJIT_INLINE_NODEBUG Xmm Vec::xmm() const noexcept { return Xmm(id()); }
ASMJIT_INLINE_NODEBUG Ymm Vec::ymm() const noexcept { return Ymm(id()); } ASMJIT_INLINE_NODEBUG Ymm Vec::ymm() const noexcept { return Ymm(id()); }
ASMJIT_INLINE_NODEBUG Zmm Vec::zmm() const noexcept { return Zmm(id()); } ASMJIT_INLINE_NODEBUG Zmm Vec::zmm() const noexcept { return Zmm(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v128() const noexcept { return Xmm(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v256() const noexcept { return Ymm(id()); }
ASMJIT_INLINE_NODEBUG Vec Vec::v512() const noexcept { return Zmm(id()); }
//! \endcond //! \endcond
//! \namespace asmjit::x86::regs //! \namespace asmjit::x86::regs