From 497ec443d58f7492eda84b9856ee51cf9bd39c04 Mon Sep 17 00:00:00 2001 From: notcpuid Date: Thu, 3 Jul 2025 13:51:23 +0300 Subject: [PATCH] refactor(asmjit): removed library for something changes --- pe-packer/asmjit/a64.h | 55 - pe-packer/asmjit/arm.h | 77 - pe-packer/asmjit/arm/a64archtraits_p.h | 82 - pe-packer/asmjit/arm/a64assembler.cpp | 5337 ------------------ pe-packer/asmjit/arm/a64assembler.h | 61 - pe-packer/asmjit/arm/a64builder.cpp | 57 - pe-packer/asmjit/arm/a64builder.h | 57 - pe-packer/asmjit/arm/a64compiler.cpp | 72 - pe-packer/asmjit/arm/a64compiler.h | 260 - pe-packer/asmjit/arm/a64emithelper.cpp | 481 -- pe-packer/asmjit/arm/a64emithelper_p.h | 55 - pe-packer/asmjit/arm/a64emitter.h | 1299 ----- pe-packer/asmjit/arm/a64formatter.cpp | 66 - pe-packer/asmjit/arm/a64formatter_p.h | 42 - pe-packer/asmjit/arm/a64func.cpp | 214 - pe-packer/asmjit/arm/a64func_p.h | 33 - pe-packer/asmjit/arm/a64globals.h | 1917 ------- pe-packer/asmjit/arm/a64instapi.cpp | 252 - pe-packer/asmjit/arm/a64instapi_p.h | 41 - pe-packer/asmjit/arm/a64instdb.cpp | 2707 --------- pe-packer/asmjit/arm/a64instdb.h | 77 - pe-packer/asmjit/arm/a64instdb_p.h | 885 --- pe-packer/asmjit/arm/a64operand.cpp | 85 - pe-packer/asmjit/arm/a64operand.h | 1099 ---- pe-packer/asmjit/arm/a64rapass.cpp | 914 --- pe-packer/asmjit/arm/a64rapass_p.h | 112 - pe-packer/asmjit/arm/armformatter.cpp | 620 --- pe-packer/asmjit/arm/armformatter_p.h | 69 - pe-packer/asmjit/arm/armglobals.h | 17 - pe-packer/asmjit/arm/armutils.h | 226 - pe-packer/asmjit/asmjit-scope-begin.h | 17 - pe-packer/asmjit/asmjit-scope-end.h | 9 - pe-packer/asmjit/asmjit.h | 35 - pe-packer/asmjit/core.h | 2152 ------- pe-packer/asmjit/core/api-build_p.h | 74 - pe-packer/asmjit/core/api-config.h | 697 --- pe-packer/asmjit/core/archcommons.h | 268 - pe-packer/asmjit/core/archtraits.cpp | 167 - pe-packer/asmjit/core/archtraits.h | 309 - pe-packer/asmjit/core/assembler.cpp | 444 -- pe-packer/asmjit/core/assembler.h | 139 - pe-packer/asmjit/core/builder.cpp | 946 ---- pe-packer/asmjit/core/builder.h | 1653 ------ pe-packer/asmjit/core/builder_p.h | 38 - pe-packer/asmjit/core/codebuffer.h | 135 - pe-packer/asmjit/core/codeholder.cpp | 1437 ----- pe-packer/asmjit/core/codeholder.h | 1205 ---- pe-packer/asmjit/core/codewriter.cpp | 300 - pe-packer/asmjit/core/codewriter_p.h | 187 - pe-packer/asmjit/core/compiler.cpp | 621 --- pe-packer/asmjit/core/compiler.h | 780 --- pe-packer/asmjit/core/compilerdefs.h | 221 - pe-packer/asmjit/core/constpool.cpp | 369 -- pe-packer/asmjit/core/constpool.h | 281 - pe-packer/asmjit/core/cpuinfo.cpp | 2273 -------- pe-packer/asmjit/core/cpuinfo.h | 1308 ----- pe-packer/asmjit/core/emithelper.cpp | 365 -- pe-packer/asmjit/core/emithelper_p.h | 62 - pe-packer/asmjit/core/emitter.cpp | 443 -- pe-packer/asmjit/core/emitter.h | 909 --- pe-packer/asmjit/core/emitterutils.cpp | 129 - pe-packer/asmjit/core/emitterutils_p.h | 90 - pe-packer/asmjit/core/environment.cpp | 47 - pe-packer/asmjit/core/environment.h | 622 --- pe-packer/asmjit/core/errorhandler.cpp | 18 - pe-packer/asmjit/core/errorhandler.h | 228 - pe-packer/asmjit/core/fixup.h | 282 - pe-packer/asmjit/core/formatter.cpp | 641 --- pe-packer/asmjit/core/formatter.h | 265 - pe-packer/asmjit/core/formatter_p.h | 40 - pe-packer/asmjit/core/func.cpp | 316 -- pe-packer/asmjit/core/func.h | 1854 ------ pe-packer/asmjit/core/funcargscontext.cpp | 338 -- pe-packer/asmjit/core/funcargscontext_p.h | 226 - pe-packer/asmjit/core/globals.cpp | 135 - pe-packer/asmjit/core/globals.h | 446 -- pe-packer/asmjit/core/inst.cpp | 129 - pe-packer/asmjit/core/inst.h | 932 ---- pe-packer/asmjit/core/instdb.cpp | 142 - pe-packer/asmjit/core/instdb_p.h | 41 - pe-packer/asmjit/core/jitallocator.cpp | 1665 ------ pe-packer/asmjit/core/jitallocator.h | 576 -- pe-packer/asmjit/core/jitruntime.cpp | 83 - pe-packer/asmjit/core/jitruntime.h | 107 - pe-packer/asmjit/core/logger.cpp | 79 - pe-packer/asmjit/core/logger.h | 222 - pe-packer/asmjit/core/misc_p.h | 33 - pe-packer/asmjit/core/operand.cpp | 132 - pe-packer/asmjit/core/operand.h | 2688 --------- pe-packer/asmjit/core/osutils.cpp | 41 - pe-packer/asmjit/core/osutils.h | 54 - pe-packer/asmjit/core/osutils_p.h | 78 - pe-packer/asmjit/core/raassignment_p.h | 444 -- pe-packer/asmjit/core/rabuilders_p.h | 653 --- pe-packer/asmjit/core/radefs_p.h | 1475 ----- pe-packer/asmjit/core/ralocal.cpp | 1244 ----- pe-packer/asmjit/core/ralocal_p.h | 307 - pe-packer/asmjit/core/rapass.cpp | 2171 -------- pe-packer/asmjit/core/rapass_p.h | 1461 ----- pe-packer/asmjit/core/rastack.cpp | 193 - pe-packer/asmjit/core/rastack_p.h | 206 - pe-packer/asmjit/core/string.cpp | 658 --- pe-packer/asmjit/core/string.h | 393 -- pe-packer/asmjit/core/support.cpp | 578 -- pe-packer/asmjit/core/support.h | 2029 ------- pe-packer/asmjit/core/support_p.h | 27 - pe-packer/asmjit/core/target.cpp | 16 - pe-packer/asmjit/core/target.h | 65 - pe-packer/asmjit/core/type.cpp | 70 - pe-packer/asmjit/core/type.h | 512 -- pe-packer/asmjit/core/virtmem.cpp | 1258 ----- pe-packer/asmjit/core/virtmem.h | 338 -- pe-packer/asmjit/core/zone.cpp | 453 -- pe-packer/asmjit/core/zone.h | 593 -- pe-packer/asmjit/core/zonehash.cpp | 311 -- pe-packer/asmjit/core/zonehash.h | 199 - pe-packer/asmjit/core/zonelist.cpp | 163 - pe-packer/asmjit/core/zonelist.h | 221 - pe-packer/asmjit/core/zonestack.cpp | 193 - pe-packer/asmjit/core/zonestack.h | 255 - pe-packer/asmjit/core/zonestring.h | 123 - pe-packer/asmjit/core/zonetree.cpp | 98 - pe-packer/asmjit/core/zonetree.h | 407 -- pe-packer/asmjit/core/zonevector.cpp | 457 -- pe-packer/asmjit/core/zonevector.h | 877 --- pe-packer/asmjit/host.h | 33 - pe-packer/asmjit/x86.h | 84 - pe-packer/asmjit/x86/x86archtraits_p.h | 165 - pe-packer/asmjit/x86/x86assembler.cpp | 5133 ----------------- pe-packer/asmjit/x86/x86assembler.h | 695 --- pe-packer/asmjit/x86/x86builder.cpp | 58 - pe-packer/asmjit/x86/x86builder.h | 357 -- pe-packer/asmjit/x86/x86compiler.cpp | 73 - pe-packer/asmjit/x86/x86compiler.h | 732 --- pe-packer/asmjit/x86/x86emithelper.cpp | 682 --- pe-packer/asmjit/x86/x86emithelper_p.h | 72 - pe-packer/asmjit/x86/x86emitter.h | 4454 --------------- pe-packer/asmjit/x86/x86formatter.cpp | 1041 ---- pe-packer/asmjit/x86/x86formatter_p.h | 58 - pe-packer/asmjit/x86/x86func.cpp | 523 -- pe-packer/asmjit/x86/x86func_p.h | 33 - pe-packer/asmjit/x86/x86globals.h | 2206 -------- pe-packer/asmjit/x86/x86instapi.cpp | 1940 ------- pe-packer/asmjit/x86/x86instapi_p.h | 42 - pe-packer/asmjit/x86/x86instdb.cpp | 6183 --------------------- pe-packer/asmjit/x86/x86instdb.h | 721 --- pe-packer/asmjit/x86/x86instdb_p.h | 315 -- pe-packer/asmjit/x86/x86opcode_p.h | 434 -- pe-packer/asmjit/x86/x86operand.cpp | 245 - pe-packer/asmjit/x86/x86operand.h | 1180 ---- pe-packer/asmjit/x86/x86rapass.cpp | 1666 ------ pe-packer/asmjit/x86/x86rapass_p.h | 105 - 152 files changed, 95470 deletions(-) delete mode 100644 pe-packer/asmjit/a64.h delete mode 100644 pe-packer/asmjit/arm.h delete mode 100644 pe-packer/asmjit/arm/a64archtraits_p.h delete mode 100644 pe-packer/asmjit/arm/a64assembler.cpp delete mode 100644 pe-packer/asmjit/arm/a64assembler.h delete mode 100644 pe-packer/asmjit/arm/a64builder.cpp delete mode 100644 pe-packer/asmjit/arm/a64builder.h delete mode 100644 pe-packer/asmjit/arm/a64compiler.cpp delete mode 100644 pe-packer/asmjit/arm/a64compiler.h delete mode 100644 pe-packer/asmjit/arm/a64emithelper.cpp delete mode 100644 pe-packer/asmjit/arm/a64emithelper_p.h delete mode 100644 pe-packer/asmjit/arm/a64emitter.h delete mode 100644 pe-packer/asmjit/arm/a64formatter.cpp delete mode 100644 pe-packer/asmjit/arm/a64formatter_p.h delete mode 100644 pe-packer/asmjit/arm/a64func.cpp delete mode 100644 pe-packer/asmjit/arm/a64func_p.h delete mode 100644 pe-packer/asmjit/arm/a64globals.h delete mode 100644 pe-packer/asmjit/arm/a64instapi.cpp delete mode 100644 pe-packer/asmjit/arm/a64instapi_p.h delete mode 100644 pe-packer/asmjit/arm/a64instdb.cpp delete mode 100644 pe-packer/asmjit/arm/a64instdb.h delete mode 100644 pe-packer/asmjit/arm/a64instdb_p.h delete mode 100644 pe-packer/asmjit/arm/a64operand.cpp delete mode 100644 pe-packer/asmjit/arm/a64operand.h delete mode 100644 pe-packer/asmjit/arm/a64rapass.cpp delete mode 100644 pe-packer/asmjit/arm/a64rapass_p.h delete mode 100644 pe-packer/asmjit/arm/armformatter.cpp delete mode 100644 pe-packer/asmjit/arm/armformatter_p.h delete mode 100644 pe-packer/asmjit/arm/armglobals.h delete mode 100644 pe-packer/asmjit/arm/armutils.h delete mode 100644 pe-packer/asmjit/asmjit-scope-begin.h delete mode 100644 pe-packer/asmjit/asmjit-scope-end.h delete mode 100644 pe-packer/asmjit/asmjit.h delete mode 100644 pe-packer/asmjit/core.h delete mode 100644 pe-packer/asmjit/core/api-build_p.h delete mode 100644 pe-packer/asmjit/core/api-config.h delete mode 100644 pe-packer/asmjit/core/archcommons.h delete mode 100644 pe-packer/asmjit/core/archtraits.cpp delete mode 100644 pe-packer/asmjit/core/archtraits.h delete mode 100644 pe-packer/asmjit/core/assembler.cpp delete mode 100644 pe-packer/asmjit/core/assembler.h delete mode 100644 pe-packer/asmjit/core/builder.cpp delete mode 100644 pe-packer/asmjit/core/builder.h delete mode 100644 pe-packer/asmjit/core/builder_p.h delete mode 100644 pe-packer/asmjit/core/codebuffer.h delete mode 100644 pe-packer/asmjit/core/codeholder.cpp delete mode 100644 pe-packer/asmjit/core/codeholder.h delete mode 100644 pe-packer/asmjit/core/codewriter.cpp delete mode 100644 pe-packer/asmjit/core/codewriter_p.h delete mode 100644 pe-packer/asmjit/core/compiler.cpp delete mode 100644 pe-packer/asmjit/core/compiler.h delete mode 100644 pe-packer/asmjit/core/compilerdefs.h delete mode 100644 pe-packer/asmjit/core/constpool.cpp delete mode 100644 pe-packer/asmjit/core/constpool.h delete mode 100644 pe-packer/asmjit/core/cpuinfo.cpp delete mode 100644 pe-packer/asmjit/core/cpuinfo.h delete mode 100644 pe-packer/asmjit/core/emithelper.cpp delete mode 100644 pe-packer/asmjit/core/emithelper_p.h delete mode 100644 pe-packer/asmjit/core/emitter.cpp delete mode 100644 pe-packer/asmjit/core/emitter.h delete mode 100644 pe-packer/asmjit/core/emitterutils.cpp delete mode 100644 pe-packer/asmjit/core/emitterutils_p.h delete mode 100644 pe-packer/asmjit/core/environment.cpp delete mode 100644 pe-packer/asmjit/core/environment.h delete mode 100644 pe-packer/asmjit/core/errorhandler.cpp delete mode 100644 pe-packer/asmjit/core/errorhandler.h delete mode 100644 pe-packer/asmjit/core/fixup.h delete mode 100644 pe-packer/asmjit/core/formatter.cpp delete mode 100644 pe-packer/asmjit/core/formatter.h delete mode 100644 pe-packer/asmjit/core/formatter_p.h delete mode 100644 pe-packer/asmjit/core/func.cpp delete mode 100644 pe-packer/asmjit/core/func.h delete mode 100644 pe-packer/asmjit/core/funcargscontext.cpp delete mode 100644 pe-packer/asmjit/core/funcargscontext_p.h delete mode 100644 pe-packer/asmjit/core/globals.cpp delete mode 100644 pe-packer/asmjit/core/globals.h delete mode 100644 pe-packer/asmjit/core/inst.cpp delete mode 100644 pe-packer/asmjit/core/inst.h delete mode 100644 pe-packer/asmjit/core/instdb.cpp delete mode 100644 pe-packer/asmjit/core/instdb_p.h delete mode 100644 pe-packer/asmjit/core/jitallocator.cpp delete mode 100644 pe-packer/asmjit/core/jitallocator.h delete mode 100644 pe-packer/asmjit/core/jitruntime.cpp delete mode 100644 pe-packer/asmjit/core/jitruntime.h delete mode 100644 pe-packer/asmjit/core/logger.cpp delete mode 100644 pe-packer/asmjit/core/logger.h delete mode 100644 pe-packer/asmjit/core/misc_p.h delete mode 100644 pe-packer/asmjit/core/operand.cpp delete mode 100644 pe-packer/asmjit/core/operand.h delete mode 100644 pe-packer/asmjit/core/osutils.cpp delete mode 100644 pe-packer/asmjit/core/osutils.h delete mode 100644 pe-packer/asmjit/core/osutils_p.h delete mode 100644 pe-packer/asmjit/core/raassignment_p.h delete mode 100644 pe-packer/asmjit/core/rabuilders_p.h delete mode 100644 pe-packer/asmjit/core/radefs_p.h delete mode 100644 pe-packer/asmjit/core/ralocal.cpp delete mode 100644 pe-packer/asmjit/core/ralocal_p.h delete mode 100644 pe-packer/asmjit/core/rapass.cpp delete mode 100644 pe-packer/asmjit/core/rapass_p.h delete mode 100644 pe-packer/asmjit/core/rastack.cpp delete mode 100644 pe-packer/asmjit/core/rastack_p.h delete mode 100644 pe-packer/asmjit/core/string.cpp delete mode 100644 pe-packer/asmjit/core/string.h delete mode 100644 pe-packer/asmjit/core/support.cpp delete mode 100644 pe-packer/asmjit/core/support.h delete mode 100644 pe-packer/asmjit/core/support_p.h delete mode 100644 pe-packer/asmjit/core/target.cpp delete mode 100644 pe-packer/asmjit/core/target.h delete mode 100644 pe-packer/asmjit/core/type.cpp delete mode 100644 pe-packer/asmjit/core/type.h delete mode 100644 pe-packer/asmjit/core/virtmem.cpp delete mode 100644 pe-packer/asmjit/core/virtmem.h delete mode 100644 pe-packer/asmjit/core/zone.cpp delete mode 100644 pe-packer/asmjit/core/zone.h delete mode 100644 pe-packer/asmjit/core/zonehash.cpp delete mode 100644 pe-packer/asmjit/core/zonehash.h delete mode 100644 pe-packer/asmjit/core/zonelist.cpp delete mode 100644 pe-packer/asmjit/core/zonelist.h delete mode 100644 pe-packer/asmjit/core/zonestack.cpp delete mode 100644 pe-packer/asmjit/core/zonestack.h delete mode 100644 pe-packer/asmjit/core/zonestring.h delete mode 100644 pe-packer/asmjit/core/zonetree.cpp delete mode 100644 pe-packer/asmjit/core/zonetree.h delete mode 100644 pe-packer/asmjit/core/zonevector.cpp delete mode 100644 pe-packer/asmjit/core/zonevector.h delete mode 100644 pe-packer/asmjit/host.h delete mode 100644 pe-packer/asmjit/x86.h delete mode 100644 pe-packer/asmjit/x86/x86archtraits_p.h delete mode 100644 pe-packer/asmjit/x86/x86assembler.cpp delete mode 100644 pe-packer/asmjit/x86/x86assembler.h delete mode 100644 pe-packer/asmjit/x86/x86builder.cpp delete mode 100644 pe-packer/asmjit/x86/x86builder.h delete mode 100644 pe-packer/asmjit/x86/x86compiler.cpp delete mode 100644 pe-packer/asmjit/x86/x86compiler.h delete mode 100644 pe-packer/asmjit/x86/x86emithelper.cpp delete mode 100644 pe-packer/asmjit/x86/x86emithelper_p.h delete mode 100644 pe-packer/asmjit/x86/x86emitter.h delete mode 100644 pe-packer/asmjit/x86/x86formatter.cpp delete mode 100644 pe-packer/asmjit/x86/x86formatter_p.h delete mode 100644 pe-packer/asmjit/x86/x86func.cpp delete mode 100644 pe-packer/asmjit/x86/x86func_p.h delete mode 100644 pe-packer/asmjit/x86/x86globals.h delete mode 100644 pe-packer/asmjit/x86/x86instapi.cpp delete mode 100644 pe-packer/asmjit/x86/x86instapi_p.h delete mode 100644 pe-packer/asmjit/x86/x86instdb.cpp delete mode 100644 pe-packer/asmjit/x86/x86instdb.h delete mode 100644 pe-packer/asmjit/x86/x86instdb_p.h delete mode 100644 pe-packer/asmjit/x86/x86opcode_p.h delete mode 100644 pe-packer/asmjit/x86/x86operand.cpp delete mode 100644 pe-packer/asmjit/x86/x86operand.h delete mode 100644 pe-packer/asmjit/x86/x86rapass.cpp delete mode 100644 pe-packer/asmjit/x86/x86rapass_p.h diff --git a/pe-packer/asmjit/a64.h b/pe-packer/asmjit/a64.h deleted file mode 100644 index a2fd47b..0000000 --- a/pe-packer/asmjit/a64.h +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of AsmJit project -// -// See or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - -#ifndef ASMJIT_A64_H_INCLUDED -#define ASMJIT_A64_H_INCLUDED - -//! \addtogroup asmjit_a64 -//! -//! ### Emitters -//! -//! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). -//! - \ref a64::Builder - AArch64 builder. -//! - \ref a64::Compiler - AArch64 compiler. -//! - \ref a64::Emitter - AArch64 emitter (abstract). -//! -//! ### Supported Instructions -//! -//! - Emitters: -//! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit operands, provides also utility -//! functions. The member functions provided are part of all AArch64 emitters. -//! -//! - Instruction representation: -//! - \ref a64::Inst::Id - instruction identifiers. -//! -//! ### Register Operands -//! -//! - \ref a64::Gp - General purpose register (abstracts 32-bit and 64-bit general purpose registers). -//! - \ref a64::Vec - Vector register (abstracts B, H, S, D, and Q NEON register with possible element type and index). -//! -//! ### Memory Operands -//! -//! - \ref a64::Mem - AArch64 memory operand that provides support for all ARM addressing features including base, -//! index, pre/post increment, and ARM-specific shift addressing + index extending. -//! -//! ### Other -//! -//! - \ref arm::Shift - Shift operation and value. -//! - \ref arm::Utils - Utilities that can help during code generation for AArch32 and AArch64. - -#include "./arm.h" - -#include "asmjit-scope-begin.h" -#include "arm/a64assembler.h" -#include "arm/a64builder.h" -#include "arm/a64compiler.h" -#include "arm/a64emitter.h" -#include "arm/a64globals.h" -#include "arm/a64instdb.h" -#include "arm/a64operand.h" -#include "asmjit-scope-end.h" - -#endif // ASMJIT_A64_H_INCLUDED - diff --git a/pe-packer/asmjit/arm.h b/pe-packer/asmjit/arm.h deleted file mode 100644 index ddc1e4f..0000000 --- a/pe-packer/asmjit/arm.h +++ /dev/null @@ -1,77 +0,0 @@ -// This file is part of AsmJit project -// -// See or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - -#ifndef ASMJIT_ARM_H_INCLUDED -#define ASMJIT_ARM_H_INCLUDED - -//! \addtogroup asmjit_arm -//! -//! ### Namespaces -//! -//! - \ref arm - arm namespace provides common functionality for both AArch32 and AArch64 backends. -//! - \ref a32 - a32 namespace provides support for AArch32 architecture. In addition it includes -//! \ref arm namespace, so you can only use a single namespace when targeting AArch32 architecture. -//! - \ref a64 - a64 namespace provides support for AArch64 architecture. In addition it includes -//! \ref arm namespace, so you can only use a single namespace when targeting AArch64 architecture. -//! -//! ### Emitters -//! -//! - AArch32 -//! - \ref a32::Assembler - AArch32 assembler (must read, provides examples). -//! - \ref a32::Builder - AArch32 builder. -//! - \ref a32::Compiler - AArch32 compiler. -//! - \ref a32::Emitter - AArch32 emitter (abstract). -//! -//! - AArch64 -//! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). -//! - \ref a64::Builder - AArch64 builder. -//! - \ref a64::Compiler - AArch64 compiler. -//! - \ref a64::Emitter - AArch64 emitter (abstract). -//! -//! ### Supported Instructions -//! -//! - AArch32: -//! - Emitters: -//! - \ref a32::EmitterExplicitT - Provides all instructions that use explicit operands, provides also -//! utility functions. The member functions provided are part of all AArch32 emitters. -//! - Instruction representation: -//! - \ref a32::Inst::Id - instruction identifiers. -//! -//! - AArch64: -//! - Emitters: -//! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit operands, provides also -//! utility functions. The member functions provided are part of all AArch64 emitters. -//! - Instruction representation: -//! - \ref a64::Inst::Id - instruction identifiers. -//! -//! ### Register Operands -//! -//! - AArch32: -//! - \ref a32::Gp - 32-bit general purpose register used by AArch32: -//! - \ref a32::Vec - Vector (SIMD) register. -//! -//! - AArch64: -//! - \ref a64::Gp - 32-bit or 64-bit general purpose register used by AArch64: -//! - \ref a64::Vec - Vector (SIMD) register. -//! -//! ### Memory Operands -//! -//! - \ref arm::Mem - AArch32/AArch64 memory operand that provides support for all ARM addressing features -//! including base, index, pre/post increment, and ARM-specific shift addressing and index extending. -//! -//! ### Other -//! -//! - \ref arm::Shift - Shift operation and value (both AArch32 and AArch64). -//! - \ref arm::DataType - Data type that is part of an instruction in AArch32 mode. -//! - \ref arm::Utils - Utilities that can help during code generation for AArch32 and AArch64. - -#include "core.h" - -#include "asmjit-scope-begin.h" -#include "arm/armglobals.h" -#include "arm/armutils.h" -#include "asmjit-scope-end.h" - -#endif // ASMJIT_ARM_H_INCLUDED diff --git a/pe-packer/asmjit/arm/a64archtraits_p.h b/pe-packer/asmjit/arm/a64archtraits_p.h deleted file mode 100644 index f5dea59..0000000 --- a/pe-packer/asmjit/arm/a64archtraits_p.h +++ /dev/null @@ -1,82 +0,0 @@ -// This file is part of AsmJit project -// -// See or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - -#ifndef ASMJIT_ARM_A64ARCHTRAITS_P_H_INCLUDED -#define ASMJIT_ARM_A64ARCHTRAITS_P_H_INCLUDED - -#include "../core/archtraits.h" -#include "../core/misc_p.h" -#include "../core/type.h" -#include "../arm/a64globals.h" -#include "../arm/a64operand.h" - -ASMJIT_BEGIN_SUB_NAMESPACE(a64) - -//! \cond INTERNAL -//! \addtogroup asmjit_a64 -//! \{ - -static const constexpr ArchTraits a64ArchTraits = { - // SP/FP/LR/PC. - Gp::kIdSp, Gp::kIdFp, Gp::kIdLr, 0xFFu, - - // Reserved. - { 0u, 0u, 0u }, - - // HW stack alignment (AArch64 requires stack aligned to 16 bytes at HW level). - 16u, - - // Min/max stack offset - byte addressing is the worst, vec.q addressing the best. - 4095, 65520, - - // Supported register types. - 0u | (1u << uint32_t(RegType::kGp32 )) - | (1u << uint32_t(RegType::kGp64 )) - | (1u << uint32_t(RegType::kVec8 )) - | (1u << uint32_t(RegType::kVec16 )) - | (1u << uint32_t(RegType::kVec32 )) - | (1u << uint32_t(RegType::kVec64 )) - | (1u << uint32_t(RegType::kVec128)) - | (1u << uint32_t(RegType::kMask )), - - // Instruction hints [Gp, Vec, Mask, Extra]. - {{ - InstHints::kPushPop, - InstHints::kPushPop, - InstHints::kNoHints, - InstHints::kNoHints - }}, - - // TypeIdToRegType. - #define V(index) (index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt8) ? RegType::kGp32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt8) ? RegType::kGp32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt16) ? RegType::kGp32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt16) ? RegType::kGp32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt32) ? RegType::kGp32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt32) ? RegType::kGp32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt64) ? RegType::kGp64 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt64) ? RegType::kGp64 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kIntPtr) ? RegType::kGp64 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUIntPtr) ? RegType::kGp64 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat32) ? RegType::kVec32 : \ - index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat64) ? RegType::kVec64 : RegType::kNone) - {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, - #undef V - - // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities. - { - ArchTypeNameId::kByte, - ArchTypeNameId::kHWord, - ArchTypeNameId::kWord, - ArchTypeNameId::kXWord - } -}; - -//! \} -//! \endcond - -ASMJIT_END_SUB_NAMESPACE - -#endif // ASMJIT_ARM_A64ARCHTRAITS_P_H_INCLUDED diff --git a/pe-packer/asmjit/arm/a64assembler.cpp b/pe-packer/asmjit/arm/a64assembler.cpp deleted file mode 100644 index 69a4422..0000000 --- a/pe-packer/asmjit/arm/a64assembler.cpp +++ /dev/null @@ -1,5337 +0,0 @@ -// This file is part of AsmJit project -// -// See or LICENSE.md for license and copyright information -// SPDX-License-Identifier: Zlib - -#include "../core/api-build_p.h" -#if !defined(ASMJIT_NO_AARCH64) - -#include "../core/codewriter_p.h" -#include "../core/cpuinfo.h" -#include "../core/emitterutils_p.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/misc_p.h" -#include "../core/support.h" -#include "../arm/armformatter_p.h" -#include "../arm/armutils.h" -#include "../arm/a64assembler.h" -#include "../arm/a64emithelper_p.h" -#include "../arm/a64instdb_p.h" - -ASMJIT_BEGIN_SUB_NAMESPACE(a64) - -// a64::Assembler - Utils -// ====================== - -static ASMJIT_INLINE_CONSTEXPR uint32_t diff(RegType a, RegType b) noexcept { return uint32_t(a) - uint32_t(b); } -static ASMJIT_INLINE_CONSTEXPR uint32_t diff(VecElementType elementType, VecElementType baseType) noexcept { return uint32_t(elementType) - uint32_t(baseType); } - -// a64::Assembler - Cond -// ===================== - -static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { return (uint32_t(cond) - 2u) & 0xFu; } - -// a64::Assembler - Bits -// ===================== - -template -static inline constexpr uint32_t B(const T& index) noexcept { return uint32_t(1u) << uint32_t(index); } - -static constexpr uint32_t kSP = Gp::kIdSp; -static constexpr uint32_t kZR = Gp::kIdZr; -static constexpr uint32_t kWX = InstDB::kWX; - -// a64::Assembler - ShiftOpToLdStOptMap -// ==================================== - -// Table that maps ShiftOp to OPT part in LD/ST (register) opcode. -#define VALUE(index) index == uint32_t(ShiftOp::kUXTW) ? 2u : \ - index == uint32_t(ShiftOp::kLSL) ? 3u : \ - index == uint32_t(ShiftOp::kSXTW) ? 6u : \ - index == uint32_t(ShiftOp::kSXTX) ? 7u : 0xFF -static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; -#undef VALUE - -// a64::Assembler - ExtendOpToRegType -// ================================== - -static inline RegType extendOptionToRegType(uint32_t option) noexcept { - uint32_t pred = (uint32_t(RegType::kGp32) << (0x0 * 4)) | // 0b000 - UXTB. - (uint32_t(RegType::kGp32) << (0x1 * 4)) | // 0b001 - UXTH. - (uint32_t(RegType::kGp32) << (0x2 * 4)) | // 0b010 - UXTW. - (uint32_t(RegType::kGp64) << (0x3 * 4)) | // 0b011 - UXTX|LSL. - (uint32_t(RegType::kGp32) << (0x4 * 4)) | // 0b100 - SXTB. - (uint32_t(RegType::kGp32) << (0x5 * 4)) | // 0b101 - SXTH. - (uint32_t(RegType::kGp32) << (0x6 * 4)) | // 0b110 - SXTW. - (uint32_t(RegType::kGp64) << (0x7 * 4)) ; // 0b111 - SXTX. - return RegType((pred >> (option * 4u)) & 0xFu); -} - -// asmjit::a64::Assembler - SizeOp -// =============================== - -//! Struct that contains Size (2 bits), Q flag, and S (scalar) flag. These values -//! are used to encode Q, Size, and Scalar fields in an opcode. -struct SizeOp { - //! \name Constants - //! \{ - - static inline constexpr uint8_t k128BitShift = 0; - static inline constexpr uint8_t kScalarShift = 1; - static inline constexpr uint8_t kSizeShift = 2; - - static inline constexpr uint8_t kQ = uint8_t(1u << k128BitShift); - static inline constexpr uint8_t kS = uint8_t(1u << kScalarShift); - - static inline constexpr uint8_t k00 = uint8_t(0 << kSizeShift); - static inline constexpr uint8_t k01 = uint8_t(1 << kSizeShift); - static inline constexpr uint8_t k10 = uint8_t(2 << kSizeShift); - static inline constexpr uint8_t k11 = uint8_t(3 << kSizeShift); - - static inline constexpr uint8_t k00Q = k00 | kQ; - static inline constexpr uint8_t k01Q = k01 | kQ; - static inline constexpr uint8_t k10Q = k10 | kQ; - static inline constexpr uint8_t k11Q = k11 | kQ; - - static inline constexpr uint8_t k00S = k00 | kS; - static inline constexpr uint8_t k01S = k01 | kS; - static inline constexpr uint8_t k10S = k10 | kS; - static inline constexpr uint8_t k11S = k11 | kS; - - static inline constexpr uint8_t kInvalid = 0xFFu; - - // Masks used by SizeOpMap. - static inline constexpr uint8_t kSzQ = (0x3u << kSizeShift) | kQ; - static inline constexpr uint8_t kSzS = (0x3u << kSizeShift) | kS; - static inline constexpr uint8_t kSzQS = (0x3u << kSizeShift) | kQ | kS; - - //! \} - - //! \name Members - //! \{ - - uint8_t value; - - //! \} - - //! \name Accessors - //! \{ - - inline bool isValid() const noexcept { return value != kInvalid; } - inline void makeInvalid() noexcept { value = kInvalid; } - - inline uint32_t q() const noexcept { return (value >> k128BitShift) & 0x1u; } - inline uint32_t qs() const noexcept { return ((value >> k128BitShift) | (value >> kScalarShift)) & 0x1u; } - inline uint32_t scalar() const noexcept { return (value >> kScalarShift) & 0x1u; } - inline uint32_t size() const noexcept { return (value >> kSizeShift) & 0x3u; } - - inline void decrementSize() noexcept { - ASMJIT_ASSERT(size() > 0); - value = uint8_t(value - (1u << kSizeShift)); - } - - //! \} -}; - -struct SizeOpTable { - enum TableId : uint8_t { - kTableBin = 0, - kTableAny, - kCount - }; - - // 40 elements for each combination. - SizeOp array[(uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8) + 1) * 8]; -}; - -#define VALUE_BIN(x) { \ - x == (((uint32_t(RegType::kVec64 ) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00Q : \ - x == (((uint32_t(RegType::kVec64 ) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : SizeOp::kInvalid \ -} - -#define VALUE_ANY(x) { \ - x == (((uint32_t(RegType::kVec8) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k00S : \ - x == (((uint32_t(RegType::kVec16) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k01S : \ - x == (((uint32_t(RegType::kVec32) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k10S : \ - x == (((uint32_t(RegType::kVec64) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kNone)) ? SizeOp::k11S : \ - x == (((uint32_t(RegType::kVec64) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00 : \ - x == (((uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kB )) ? SizeOp::k00Q : \ - x == (((uint32_t(RegType::kVec64) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01 : \ - x == (((uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kH )) ? SizeOp::k01Q : \ - x == (((uint32_t(RegType::kVec64) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10 : \ - x == (((uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kS )) ? SizeOp::k10Q : \ - x == (((uint32_t(RegType::kVec64) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11S : \ - x == (((uint32_t(RegType::kVec128) - uint32_t(RegType::kVec8)) << 3) | uint32_t(VecElementType::kD )) ? SizeOp::k11Q : SizeOp::kInvalid \ -} - -static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = { - {{ ASMJIT_LOOKUP_TABLE_40(VALUE_BIN, 0) }}, - {{ ASMJIT_LOOKUP_TABLE_40(VALUE_ANY, 0) }} -}; - -#undef VALUE_ANY -#undef VALUE_BIN - -struct SizeOpMap { - uint8_t tableId; - uint8_t sizeOpMask; - uint16_t acceptMask; -}; - -static const constexpr SizeOpMap sizeOpMap[InstDB::kVO_Count] = { - { // kVO_V_B: - SizeOpTable::kTableBin, SizeOp::kQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q)) - }, - - { // kVO_V_BH: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q)) - }, - - { // kVO_V_BH_4S: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10Q)) - }, - - { // kVO_V_BHS: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q)) - }, - - { // kVO_V_BHS_D2: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k11Q)) - }, - - { // kVO_V_HS: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q)) - }, - - { // kVO_V_S: - SizeOpTable::kTableAny, SizeOp::kQ , uint16_t(B(SizeOp::k10) | B(SizeOp::k10Q)) - }, - - { // kVO_V_B8H4: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01)) - }, - - { // kVO_V_B8H4S2: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01) | B(SizeOp::k10)) - }, - - { // kVO_V_B8D1: - SizeOpTable::kTableAny, SizeOp::kSzQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k11S)) - }, - - { // kVO_V_H4S2: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k10)) - }, - - { // kVO_V_B16: - SizeOpTable::kTableBin, SizeOp::kQ , uint16_t(B(SizeOp::k00Q)) - }, - - { // kVO_V_B16H8: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q)) - }, - - { // kVO_V_B16H8S4: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q) | B(SizeOp::k10Q)) - }, - - { // kVO_V_B16D2: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k11Q)) - }, - - { // kVO_V_H8S4: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01Q) | B(SizeOp::k10Q)) - }, - - { // kVO_V_S4: - SizeOpTable::kTableAny, 0 , uint16_t(B(SizeOp::k10Q)) - }, - - { // kVO_V_D2: - SizeOpTable::kTableAny, 0 , uint16_t(B(SizeOp::k11Q)) - }, - - { // kVO_SV_BHS: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S)) - }, - - { // kVO_SV_B8H4S2: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10S)) - }, - - { // kVO_SV_HS: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S)) - }, - - { // kVO_V_Any: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k11S) | B(SizeOp::k11Q)) - }, - - { // kVO_SV_Any: - SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k00S) | - B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | - B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S) | - B(SizeOp::k11) | B(SizeOp::k11Q) | B(SizeOp::k11S)) - } -}; - -static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept { - return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1; -} - -static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, VecElementType elementType) noexcept { - // Instruction data or Assembler is wrong if this triggers an assertion failure. - ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count); - // ElementType uses 3 bits in the operand signature, it should never overflow. - ASMJIT_ASSERT(uint32_t(elementType) <= 0x7u); - - const SizeOpMap& map = sizeOpMap[vecOpType]; - const SizeOpTable& table = sizeOpTable[map.tableId]; - - size_t index = (Support::min(diff(regType, RegType::kVec8), diff(RegType::kVec128, RegType::kVec8) + 1) << 3) | uint32_t(elementType); - SizeOp op = table.array[index]; - SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) }; - - if (!Support::bitTest(map.acceptMask, op.value)) { - modifiedOp.makeInvalid(); - } - - return modifiedOp; -} - -// a64::Assembler - Immediate Encoding Utilities (Integral) -// ======================================================== - -using Utils::LogicalImm; - -struct HalfWordImm { - uint32_t hw; - uint32_t inv; - uint32_t imm; -}; - -struct LMHImm { - uint32_t lm; - uint32_t h; - uint32_t maxRmId; -}; - -static inline uint32_t countZeroHalfWords64(uint64_t imm) noexcept { - return uint32_t((imm & 0x000000000000FFFFu) == 0) + - uint32_t((imm & 0x00000000FFFF0000u) == 0) + - uint32_t((imm & 0x0000FFFF00000000u) == 0) + - uint32_t((imm & 0xFFFF000000000000u) == 0) ; -} - -static uint32_t encodeMovSequence32(uint32_t out[2], uint32_t imm, uint32_t rd, uint32_t x) noexcept { - ASMJIT_ASSERT(rd <= 31); - - uint32_t kMovZ = 0b01010010100000000000000000000000 | (x << 31); - uint32_t kMovN = 0b00010010100000000000000000000000; - uint32_t kMovK = 0b01110010100000000000000000000000; - - if ((imm & 0xFFFF0000u) == 0x00000000u) { - out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd; - return 1; - } - - if ((imm & 0xFFFF0000u) == 0xFFFF0000u) { - out[0] = kMovN | (0 << 21) | ((~imm & 0xFFFFu) << 5) | rd; - return 1; - } - - if ((imm & 0x0000FFFFu) == 0x00000000u) { - out[0] = kMovZ | (1 << 21) | ((imm >> 16) << 5) | rd; - return 1; - } - - if ((imm & 0x0000FFFFu) == 0x0000FFFFu) { - out[0] = kMovN | (1 << 21) | ((~imm >> 16) << 5) | rd; - return 1; - } - - out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd; - out[1] = kMovK | (1 << 21) | ((imm >> 16) << 5) | rd; - return 2; -} - -static uint32_t encodeMovSequence64(uint32_t out[4], uint64_t imm, uint32_t rd, uint32_t x) noexcept { - ASMJIT_ASSERT(rd <= 31); - - uint32_t kMovZ = 0b11010010100000000000000000000000; - uint32_t kMovN = 0b10010010100000000000000000000000; - uint32_t kMovK = 0b11110010100000000000000000000000; - - if (imm <= 0xFFFFFFFFu) - return encodeMovSequence32(out, uint32_t(imm), rd, x); - - uint32_t zhw = countZeroHalfWords64( imm); - uint32_t ohw = countZeroHalfWords64(~imm); - - if (zhw >= ohw) { - uint32_t op = kMovZ; - uint32_t count = 0; - - for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) { - uint32_t hwImm = uint32_t(imm & 0xFFFFu); - if (hwImm == 0) { - continue; - } - - out[count++] = op | (hwIndex << 21) | (hwImm << 5) | rd; - op = kMovK; - } - - // This should not happen - zero should be handled by encodeMovSequence32(). - ASMJIT_ASSERT(count > 0); - - return count; - } - else { - uint32_t op = kMovN; - uint32_t count = 0; - uint32_t negMask = 0xFFFFu; - - for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) { - uint32_t hwImm = uint32_t(imm & 0xFFFFu); - if (hwImm == 0xFFFFu) { - continue; - } - - out[count++] = op | (hwIndex << 21) | ((hwImm ^ negMask) << 5) | rd; - op = kMovK; - negMask = 0; - } - - if (count == 0) { - out[count++] = kMovN | ((0xFFFF ^ negMask) << 5) | rd; - } - - return count; - } -} - -static inline bool encodeLMH(uint32_t sizeField, uint32_t elementIndex, LMHImm* out) noexcept { - if (sizeField != 1 && sizeField != 2) - return false; - - uint32_t hShift = 3u - sizeField; - uint32_t lmShift = sizeField - 1u; - uint32_t maxElementIndex = 15u >> sizeField; - - out->h = elementIndex >> hShift; - out->lm = (elementIndex << lmShift) & 0x3u; - out->maxRmId = (8u << sizeField) - 1; - - return elementIndex <= maxElementIndex; -} - -// a64::Assembler - Opcode -// ======================= - -//! Helper class to store and manipulate ARM opcode. -struct Opcode { - uint32_t v; - - enum Bits : uint32_t { - kN = (1u << 22), - kQ = (1u << 30), - kX = (1u << 31) - }; - - // -------------------------------------------------------------------------- - // [Opcode Builder] - // -------------------------------------------------------------------------- - - inline uint32_t get() const noexcept { return v; } - inline void reset(uint32_t value) noexcept { v = value; } - - inline bool hasQ() const noexcept { return (v & kQ) != 0; } - inline bool hasX() const noexcept { return (v & kX) != 0; } - - template - inline Opcode& addImm(T value, uint32_t bitIndex) noexcept { return operator|=(uint32_t(value) << bitIndex); } - - template - inline Opcode& xorImm(T value, uint32_t bitIndex) noexcept { return operator^=(uint32_t(value) << bitIndex); } - - template - inline Opcode& addIf(T value, const Condition& condition) noexcept { return operator|=(condition ? uint32_t(value) : uint32_t(0)); } - - inline Opcode& addLogicalImm(const LogicalImm& logicalImm) noexcept { - addImm(logicalImm.n, 22); - addImm(logicalImm.r, 16); - addImm(logicalImm.s, 10); - return *this; - } - - inline Opcode& addReg(uint32_t id, uint32_t bitIndex) noexcept { return operator|=((id & 31u) << bitIndex); } - inline Opcode& addReg(const Operand_& op, uint32_t bitIndex) noexcept { return addReg(op.id(), bitIndex); } - - inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; } - inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; } - inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; } - inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; } - - inline uint32_t operator&(uint32_t x) const noexcept { return v & x; } - inline uint32_t operator|(uint32_t x) const noexcept { return v | x; } - inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; } -}; - -// a64::Assembler - Signature Utilities -// ==================================== - -// TODO: [ARM] Deprecate matchSignature. -static inline bool matchSignature(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept { - if (!(instFlags & (InstDB::kInstFlagLong | InstDB::kInstFlagNarrow))) - return o0.signature() == o1.signature(); - - // TODO: [ARM] Something smart to validate this. - return true; -} - -static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t instFlags) noexcept { - return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature(); -} - -static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint32_t instFlags) noexcept { - return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature(); -} - -// Memory must be either: -// 1. Absolute address, which will be converted to relative. -// 2. Relative displacement (Label). -// 3. Base register + either offset or index. -static inline bool armCheckMemBaseIndexRel(const Mem& mem) noexcept { - // Allowed base types (Nothing, Label, and Gp64). - constexpr uint32_t kBaseMask = B(0) | B(RegType::kLabelTag) | B(RegType::kGp64); - // Allowed index types (Nothing, Gp32, and Gp64). - constexpr uint32_t kIndexMask = B(0) | B(RegType::kGp32) | B(RegType::kGp64) ; - - RegType baseType = mem.baseType(); - RegType indexType = mem.indexType(); - - if (!Support::bitTest(kBaseMask, baseType)) { - return false; - } - - if (baseType > RegType::kLabelTag) { - // Index allows either Gp32 or Gp64. - if (!Support::bitTest(kIndexMask, indexType)) { - return false; - } - - if (indexType == RegType::kNone) { - return true; - } - else { - return !mem.hasOffset(); - } - } - else { - // No index register allowed if this is a PC relative address (literal). - return indexType == RegType::kNone; - } -} - -struct EncodeFpOpcodeBits { - uint32_t sizeMask; - uint32_t mask[3]; -}; - -static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode, uint32_t* szOut) noexcept { - static constexpr uint32_t kQBitIndex = 30; - - static const EncodeFpOpcodeBits szBits[InstDB::kHF_Count] = { - { B(2) | B(1) , { 0u , 0u, B(22) } }, - { B(2) | B(1) | B(0), { 0u , 0u, 0u } }, - { B(2) | B(1) | B(0), { B(23) | B(22) , 0u, B(22) } }, - { B(2) | B(1) | B(0), { B(22) | B(20) | B(19) , 0u, B(22) } }, - { B(2) | B(1) | B(0), { B(22) | B(21) | B(15) | B(14), 0u, B(22) } }, - { B(2) | B(1) | B(0), { B(23) , 0u, B(22) } } - }; - - if (!reg.hasElementType()) { - // Scalar operation [HSD]. - uint32_t sz = diff(reg.regType(), RegType::kVec16); - if (sz > 2u || !Support::bitTest(szBits[sHf].sizeMask, sz)) { - return false; - } - - opcode->reset(szBits[sHf].mask[sz] ^ sOp); - *szOut = sz; - return sOp != 0; - } - else { - // Vector operation [HSD]. - uint32_t q = diff(reg.regType(), RegType::kVec64); - uint32_t sz = diff(reg.elementType(), VecElementType::kH); - - if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz)) { - return false; - } - - opcode->reset(szBits[vHf].mask[sz] ^ (vOp | (q << kQBitIndex))); - *szOut = sz; - return vOp != 0; - } -} - -static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode) noexcept { - uint32_t sz; - return pickFpOpcode(reg, sOp, sHf, vOp, vHf, opcode, &sz); -} - -// a64::Assembler - Operand Checks -// =============================== - -// Checks whether all operands have the same signature. -static inline bool checkSignature(const Operand_& o0, const Operand_& o1) noexcept { - return o0.signature() == o1.signature(); -} - -static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { - return o0.signature() == o1.signature() && - o1.signature() == o2.signature(); -} - -static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { - return o0.signature() == o1.signature() && - o1.signature() == o2.signature() && - o2.signature() == o3.signature(); -} - -// Checks whether the register is GP register of the allowed types. -// -// Allowed is a 2-bit mask, where the first bits allows Gp32 and the second bit allows Gp64. These bits are usually -// stored within the instruction, but could be also hardcoded in the assembler for instructions where GP types are -// not selectable. -static inline bool checkGpType(const Operand_& op, uint32_t allowed) noexcept { - RegType type = op.as().regType(); - return Support::bitTest(allowed << uint32_t(RegType::kGp32), type); -} - -static inline bool checkGpType(const Operand_& op, uint32_t allowed, uint32_t* x) noexcept { - // NOTE: We set 'x' to one only when Gp32 is allowed, otherwise the X is part - // of the opcode and we cannot set it. This is why this works without requiring - // additional logic. - RegType type = op.as().regType(); - *x = diff(type, RegType::kGp32) & allowed; - return Support::bitTest(allowed << uint32_t(RegType::kGp32), type); -} - -static inline bool checkGpType(const Operand_& o0, const Operand_& o1, uint32_t allowed, uint32_t* x) noexcept { - return checkGpType(o0, allowed, x) && checkSignature(o0, o1); -} - -static inline bool checkGpType(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t allowed, uint32_t* x) noexcept { - return checkGpType(o0, allowed, x) && checkSignature(o0, o1, o2); -} - -static inline bool checkGpId(const Operand_& op, uint32_t hiId = kZR) noexcept { - uint32_t id = op.as().id(); - return id < 31u || id == hiId; -} - -static inline bool checkGpId(const Operand_& o0, const Operand_& o1, uint32_t hiId = kZR) noexcept { - uint32_t id0 = o0.as().id(); - uint32_t id1 = o1.as().id(); - - return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId); -} - -static inline bool checkGpId(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t hiId = kZR) noexcept { - uint32_t id0 = o0.as().id(); - uint32_t id1 = o1.as().id(); - uint32_t id2 = o2.as().id(); - - return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId) && (id2 < 31u || id2 == hiId); -} - -static inline bool checkVecId(const Operand_& op) noexcept { - uint32_t id = op.as().id(); - return id <= 31u; -} - -static inline bool checkVecId(const Operand_& o0, const Operand_& o1) noexcept { - uint32_t id0 = o0.as().id(); - uint32_t id1 = o1.as().id(); - - return (id0 | id1) <= 31u; -} - -/* Unused at the moment. -static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { - uint32_t id0 = o0.as().id(); - uint32_t id1 = o1.as().id(); - uint32_t id2 = o2.as().id(); - - return (id0 | id1 | id2) <= 31u; -} - -static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { - uint32_t id0 = o0.as().id(); - uint32_t id1 = o1.as().id(); - uint32_t id2 = o2.as().id(); - uint32_t id3 = o3.as().id(); - - return (id0 | id1 | id2 | id3) <= 31u; -} -*/ - -static inline bool checkMemBase(const Mem& mem) noexcept { - return mem.baseType() == RegType::kGp64 && mem.baseId() <= 31; -} - -static inline bool checkEven(const Operand_& o0, const Operand_& o1) noexcept { - return ((o0.id() | o1.id()) & 1) == 0; -} - -static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1) noexcept { - return ((o0.id() + 1u) & 0x1Fu) == o1.id(); -} - -static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { - return ((o0.id() + 1u) & 0x1Fu) == o1.id() && - ((o0.id() + 2u) & 0x1Fu) == o2.id(); -} - -static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { - return ((o0.id() + 1u) & 0x1Fu) == o1.id() && - ((o0.id() + 2u) & 0x1Fu) == o2.id() && - ((o0.id() + 3u) & 0x1Fu) == o3.id(); -} - -// a64::Assembler - CheckReg -// ========================= - -#define V(index) (index == uint32_t(RegType::kGp32) ? Gp::kIdZr : \ - index == uint32_t(RegType::kGp64) ? Gp::kIdZr : \ - index == uint32_t(RegType::kVec8) ? 31u : \ - index == uint32_t(RegType::kVec16) ? 31u : \ - index == uint32_t(RegType::kVec32) ? 31u : \ - index == uint32_t(RegType::kVec64) ? 31u : \ - index == uint32_t(RegType::kVec128) ? 31u : 0) -static const Support::Array commonHiRegIdOfType = {{ - ASMJIT_LOOKUP_TABLE_32(V, 0) -}}; -#undef V - -static inline bool checkValidRegs(const Operand_& o0) noexcept { - return bool(unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as().regType()])); -} - -static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1) noexcept { - return bool((unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as().regType()])) & - (unsigned(o1.id() < 31) | unsigned(o1.id() == commonHiRegIdOfType[o1.as().regType()]))); -} - -static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { - return bool((unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as().regType()])) & - (unsigned(o1.id() < 31) | unsigned(o1.id() == commonHiRegIdOfType[o1.as().regType()])) & - (unsigned(o2.id() < 31) | unsigned(o2.id() == commonHiRegIdOfType[o2.as().regType()]))); -} - -static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { - return bool((unsigned(o0.id() < 31) | unsigned(o0.id() == commonHiRegIdOfType[o0.as().regType()])) & - (unsigned(o1.id() < 31) | unsigned(o1.id() == commonHiRegIdOfType[o1.as().regType()])) & - (unsigned(o2.id() < 31) | unsigned(o2.id() == commonHiRegIdOfType[o2.as().regType()])) & - (unsigned(o3.id() < 31) | unsigned(o3.id() == commonHiRegIdOfType[o3.as().regType()]))); -} - -// a64::Assembler - Construction & Destruction -// =========================================== - -Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { - _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); - initEmitterFuncs(this); - - if (code) { - code->attach(this); - } -} - -Assembler::~Assembler() noexcept {} - -// a64::Assembler - Emit -// ===================== - -#define ENC_OPS1(OP0) \ - (uint32_t(OperandType::k##OP0)) - -#define ENC_OPS2(OP0, OP1) \ - (uint32_t(OperandType::k##OP0) + \ - (uint32_t(OperandType::k##OP1) << 3)) - -#define ENC_OPS3(OP0, OP1, OP2) \ - (uint32_t(OperandType::k##OP0) + \ - (uint32_t(OperandType::k##OP1) << 3) + \ - (uint32_t(OperandType::k##OP2) << 6)) - -#define ENC_OPS4(OP0, OP1, OP2, OP3) \ - (uint32_t(OperandType::k##OP0) + \ - (uint32_t(OperandType::k##OP1) << 3) + \ - (uint32_t(OperandType::k##OP2) << 6) + \ - (uint32_t(OperandType::k##OP3) << 9)) - -Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { - // Logging/Validation/Error. - constexpr InstOptions kRequiresSpecialHandling = InstOptions::kReserved; - - Error err; - CodeWriter writer(this); - - // Combine all instruction options and also check whether the instruction - // is valid. All options that require special handling (including invalid - // instruction) are handled by the next branch. - InstOptions options = InstOptions(instId - 1 >= Inst::_kIdCount - 1) | InstOptions((size_t)(_bufferEnd - writer.cursor()) < 4) | instOptions() | forcedInstOptions(); - - CondCode instCC = BaseInst::extractARMCondCode(instId); - instId = instId & uint32_t(InstIdParts::kRealId); - - if (instId >= Inst::_kIdCount) { - instId = 0; - } - - const InstDB::InstInfo* instInfo = &InstDB::_instInfoTable[instId]; - uint32_t encodingIndex = instInfo->_encodingDataIndex; - - Opcode opcode; - uint32_t isign4; - uint32_t instFlags; - - const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const Operand_* rmRel = nullptr; - - uint32_t multipleOpData[4]; - uint32_t multipleOpCount; - - // These are only used when instruction uses a relative displacement. - OffsetFormat offsetFormat; // Offset format. - uint64_t offsetValue; // Offset value (if known). - - if (ASMJIT_UNLIKELY(Support::test(options, kRequiresSpecialHandling))) { - if (ASMJIT_UNLIKELY(!_code)) { - return reportError(DebugUtils::errored(kErrorNotInitialized)); - } - - // Unknown instruction. - if (ASMJIT_UNLIKELY(instId == 0)) { - goto InvalidInstruction; - } - - // Condition code can only be used with 'B' instruction. - if (ASMJIT_UNLIKELY(instCC != CondCode::kAL && instId != Inst::kIdB)) { - goto InvalidInstruction; - } - - // Grow request, happens rarely. - err = writer.ensureSpace(this, 4); - if (ASMJIT_UNLIKELY(err)) { - goto Failed; - } - -#ifndef ASMJIT_NO_VALIDATION - // Strict validation. - if (hasDiagnosticOption(DiagnosticOptions::kValidateAssembler)) { - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - err = _funcs.validate(BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); - if (ASMJIT_UNLIKELY(err)) { - goto Failed; - } - } -#endif - } - - // Signature of the first 4 operands. - isign4 = (uint32_t(o0.opType()) ) + - (uint32_t(o1.opType()) << 3) + - (uint32_t(o2.opType()) << 6) + - (uint32_t(o3.opType()) << 9); - instFlags = instInfo->flags(); - - switch (instInfo->_encoding) { - // ------------------------------------------------------------------------ - // [Base - Universal] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseOp: { - const InstDB::EncodingData::BaseOp& opData = InstDB::EncodingData::baseOp[encodingIndex]; - - if (isign4 == 0) { - opcode.reset(opData.opcode); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseOpX16: { - const InstDB::EncodingData::BaseOpX16& opData = InstDB::EncodingData::baseOpX16[encodingIndex]; - - if (isign4 == ENC_OPS1(Reg) && o0.as().isGp64(16)) { - opcode.reset(opData.opcode); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseOpImm: { - const InstDB::EncodingData::BaseOpImm& opData = InstDB::EncodingData::baseOpImm[encodingIndex]; - - if (isign4 == ENC_OPS1(Imm)) { - uint64_t imm = o0.as().valueAs(); - uint32_t immMax = 1u << opData.immBits; - - if (imm >= immMax) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(imm, opData.immOffset); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseR: { - const InstDB::EncodingData::BaseR& opData = InstDB::EncodingData::baseR[encodingIndex]; - - if (isign4 == ENC_OPS1(Reg)) { - if (!checkGpType(o0, opData.rType)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.rHiId)) - goto InvalidPhysId; - - opcode.reset(opData.opcode); - opcode.addReg(o0, opData.rShift); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseRR: { - const InstDB::EncodingData::BaseRR& opData = InstDB::EncodingData::baseRR[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - uint32_t x; - if (!checkGpType(o0, opData.aType, &x)) - goto InvalidInstruction; - - if (!checkGpType(o1, opData.bType)) - goto InvalidInstruction; - - if (opData.uniform && !checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.aHiId)) - goto InvalidPhysId; - - if (!checkGpId(o1, opData.bHiId)) - goto InvalidPhysId; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addReg(o1, opData.bShift); - opcode.addReg(o0, opData.aShift); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseRRR: { - const InstDB::EncodingData::BaseRRR& opData = InstDB::EncodingData::baseRRR[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - uint32_t x; - if (!checkGpType(o0, opData.aType, &x)) - goto InvalidInstruction; - - if (!checkGpType(o1, opData.bType)) - goto InvalidInstruction; - - if (!checkGpType(o2, opData.cType)) - goto InvalidInstruction; - - if (opData.uniform && !checkSignature(o0, o1, o2)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.aHiId)) - goto InvalidPhysId; - - if (!checkGpId(o1, opData.bHiId)) - goto InvalidPhysId; - - if (!checkGpId(o2, opData.cHiId)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseRRRR: { - const InstDB::EncodingData::BaseRRRR& opData = InstDB::EncodingData::baseRRRR[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { - uint32_t x; - if (!checkGpType(o0, opData.aType, &x)) - goto InvalidInstruction; - - if (!checkGpType(o1, opData.bType)) - goto InvalidInstruction; - - if (!checkGpType(o2, opData.cType)) - goto InvalidInstruction; - - if (!checkGpType(o3, opData.dType)) - goto InvalidInstruction; - - if (opData.uniform && !checkSignature(o0, o1, o2, o3)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.aHiId)) - goto InvalidPhysId; - - if (!checkGpId(o1, opData.bHiId)) - goto InvalidPhysId; - - if (!checkGpId(o2, opData.cHiId)) - goto InvalidPhysId; - - if (!checkGpId(o3, opData.dHiId)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addReg(o3, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseRRII: { - const InstDB::EncodingData::BaseRRII& opData = InstDB::EncodingData::baseRRII[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - if (!checkGpType(o0, opData.aType)) - goto InvalidInstruction; - - if (!checkGpType(o1, opData.bType)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.aHiId)) - goto InvalidPhysId; - - if (!checkGpId(o1, opData.bHiId)) - goto InvalidPhysId; - - if (o2.as().valueAs() >= Support::bitMask(opData.aImmSize + opData.aImmDiscardLsb) || - o3.as().valueAs() >= Support::bitMask(opData.bImmSize + opData.bImmDiscardLsb)) - goto InvalidImmediate; - - uint32_t aImm = o2.as().valueAs() >> opData.aImmDiscardLsb; - uint32_t bImm = o3.as().valueAs() >> opData.bImmDiscardLsb; - - if ((aImm << opData.aImmDiscardLsb) != o2.as().valueAs() || - (bImm << opData.bImmDiscardLsb) != o3.as().valueAs()) - goto InvalidImmediate; - - opcode.reset(opData.opcode()); - opcode.addImm(aImm, opData.aImmOffset); - opcode.addImm(bImm, opData.bImmOffset); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Mov] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseMov: { - // MOV is a pseudo instruction that uses various instructions depending on its signature. - uint32_t x = diff(o0.as().regType(), RegType::kGp32); - if (x > 1) - goto InvalidInstruction; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (!o0.as().isGp()) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - bool hasSP = o0.as().isSP() || o1.as().isSP(); - if (hasSP) { - // Cannot be combined with ZR. - if (!checkGpId(o0, o1, kSP)) - goto InvalidPhysId; - - // MOV Rd, Rm -> ADD Rd, Rn, #0. - opcode.reset(0b00010001000000000000000000000000); - opcode.addImm(x, 31); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - else { - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - // MOV Rd, Rm -> ORR Rd, , Rm. - opcode.reset(0b00101010000000000000001111100000); - opcode.addImm(x, 31); - opcode.addReg(o1, 16); - opcode.addReg(o0, 0); - goto EmitOp; - } - } - - if (isign4 == ENC_OPS2(Reg, Imm)) { - if (!o0.as().isGp()) - goto InvalidInstruction; - - uint64_t immValue = o1.as().valueAs(); - if (!x) - immValue &= 0xFFFFFFFFu; - - // Prefer a single MOVN/MOVZ instruction over a logical instruction. - multipleOpCount = encodeMovSequence64(multipleOpData, immValue, o0.id() & 31, x); - if (multipleOpCount == 1 && !o0.as().isSP()) { - opcode.reset(multipleOpData[0]); - goto EmitOp; - } - - // Logical instructions use 13-bit immediate pattern encoded as N:ImmR:ImmS. - LogicalImm logicalImm; - if (!o0.as().isZR()) { - if (Utils::encodeLogicalImm(immValue, x ? 64 : 32, &logicalImm)) { - if (!checkGpId(o0, kSP)) - goto InvalidPhysId; - - opcode.reset(0b00110010000000000000001111100000); - opcode.addImm(x, 31); - opcode.addLogicalImm(logicalImm); - opcode.addReg(o0, 0); - goto EmitOp; - } - } - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - goto EmitOp_Multiple; - } - - break; - } - - case InstDB::kEncodingBaseMovKNZ: { - const InstDB::EncodingData::BaseMovKNZ& opData = InstDB::EncodingData::baseMovKNZ[encodingIndex]; - - uint32_t x = diff(o0.as().regType(), RegType::kGp32); - if (x > 1) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - - if (isign4 == ENC_OPS2(Reg, Imm)) { - uint64_t imm16 = o1.as().valueAs(); - if (imm16 > 0xFFFFu) - goto InvalidImmediate; - - opcode.addImm(imm16, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS3(Reg, Imm, Imm)) { - uint64_t imm16 = o1.as().valueAs(); - uint32_t shiftType = o2.as().predicate(); - uint64_t shiftValue = o2.as().valueAs(); - - if (imm16 > 0xFFFFu || shiftValue > 48 || shiftType != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - // Convert shift value to 'hw' field. - uint32_t hw = uint32_t(shiftValue) >> 4; - if ((hw << 4) != uint32_t(shiftValue)) - goto InvalidImmediate; - - opcode.addImm(hw, 21); - opcode.addImm(imm16, 5); - opcode.addReg(o0, 0); - - if (!x && hw > 1u) - goto InvalidImmediate; - - goto EmitOp; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Adr] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseAdr: { - const InstDB::EncodingData::BaseAdr& opData = InstDB::EncodingData::baseAdr[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) { - if (!o0.as().isGp64()) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addReg(o0, 0); - offsetFormat.resetToImmValue(opData.offsetType, 4, 5, 21, 0); - - if (instId == Inst::kIdAdrp) - offsetFormat._immDiscardLsb = 12; - - rmRel = &o1; - goto EmitOp_Rel; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Arithmetic and Logical] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseAddSub: { - const InstDB::EncodingData::BaseAddSub& opData = InstDB::EncodingData::baseAddSub[encodingIndex]; - - uint32_t x; - if (!checkGpType(o0, o1, kWX, &x)) - goto InvalidInstruction; - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) || isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - opcode.reset(uint32_t(opData.immediateOp) << 24); - - // ADD | SUB (immediate) - ZR is not allowed. - // ADDS|SUBS (immediate) - ZR allowed in Rd, SP allowed in Rn. - uint32_t aHiId = opcode.get() & B(29) ? kZR : kSP; - uint32_t bHiId = kSP; - - if (!checkGpId(o0, aHiId) || !checkGpId(o1, bHiId)) - goto InvalidPhysId; - - // ADD|SUB (immediate) use 12-bit immediate optionally shifted by 'LSL #12'. - uint64_t imm = o2.as().valueAs(); - uint32_t shift = 0; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - if (o3.as().predicate() != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - if (o3.as().value() != 0 && o3.as().value() != 12) - goto InvalidImmediate; - - shift = uint32_t(o3.as().value() != 0); - } - - // Accept immediate value of '0x00XXX000' by setting 'shift' to 12. - if (imm > 0xFFFu) { - if (shift || (imm & ~uint64_t(0xFFFu << 12)) != 0) - goto InvalidImmediate; - shift = 1; - imm >>= 12; - } - - opcode.addImm(x, 31); - opcode.addImm(shift, 22); - opcode.addImm(imm, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - uint32_t opSize = x ? 64 : 32; - uint64_t shift = 0; - uint32_t sType = uint32_t(ShiftOp::kLSL); - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - sType = o3.as().predicate(); - shift = o3.as().valueAs(); - } - - if (!checkGpId(o2, kZR)) - goto InvalidPhysId; - - // Shift operation - LSL, LSR, ASR. - if (sType <= uint32_t(ShiftOp::kASR)) { - bool hasSP = o0.as().isSP() || o1.as().isSP(); - if (!hasSP) { - if (!checkSignature(o1, o2)) { - goto InvalidInstruction; - } - - if (!checkGpId(o0, o1, kZR)) { - goto InvalidPhysId; - } - - if (shift >= opSize) { - goto InvalidImmediate; - } - - opcode.reset(uint32_t(opData.shiftedOp) << 21); - opcode.addImm(x, 31); - opcode.addImm(sType, 22); - opcode.addReg(o2, 16); - opcode.addImm(shift, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - // SP register can only be used with LSL or Extend. - if (sType != uint32_t(ShiftOp::kLSL)) { - goto InvalidImmediate; - } - - sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW); - } - - // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX. - opcode.reset(uint32_t(opData.extendedOp) << 21); - sType -= uint32_t(ShiftOp::kUXTB); - - if (sType > 7 || shift > 4) { - goto InvalidImmediate; - } - - if (!(opcode.get() & B(29))) { - // ADD|SUB (extend) - ZR is not allowed. - if (!checkGpId(o0, o1, kSP)) - goto InvalidPhysId; - } - else { - // ADDS|SUBS (extend) - ZR allowed in Rd, SP allowed in Rn. - if (!checkGpId(o0, kZR) || !checkGpId(o1, kSP)) - goto InvalidPhysId; - } - - // Validate whether the register operands match extend option. - if (o2.as().regType() != extendOptionToRegType(sType) || o1.as().regType() < o2.as().regType()) { - goto InvalidInstruction; - } - - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addImm(sType, 13); - opcode.addImm(shift, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseLogical: { - const InstDB::EncodingData::BaseLogical& opData = InstDB::EncodingData::baseLogical[encodingIndex]; - - uint32_t x; - if (!checkGpType(o0, o1, kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - uint32_t opSize = x ? 64 : 32; - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp != 0) { - opcode.reset(uint32_t(opData.immediateOp) << 23); - - // AND|ANDS|BIC|BICS|ORR|EOR (immediate) uses a LogicalImm format described by N:R:S values. - uint64_t immMask = Support::lsbMask(opSize); - uint64_t immValue = o2.as().valueAs(); - - if (opData.negateImm) - immValue ^= immMask; - - // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR. - LogicalImm logicalImm; - if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm)) - goto InvalidImmediate; - - // AND|BIC|ORR|EOR (immediate) can have SP on destination, but ANDS|BICS (immediate) cannot. - uint32_t kOpANDS = 0x3 << 29; - bool isANDS = (opcode.get() & kOpANDS) == kOpANDS; - - if (!checkGpId(o0, isANDS ? kZR : kSP) || !checkGpId(o1, kZR)) - goto InvalidPhysId; - - opcode.addImm(x, 31); - opcode.addLogicalImm(logicalImm); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - if (!checkSignature(o1, o2)) - goto InvalidInstruction; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!checkGpId(o0, o1, o2, kZR)) - goto InvalidPhysId; - - opcode.reset(uint32_t(opData.shiftedOp) << 21); - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - if (!checkGpId(o0, o1, o2, kZR)) - goto InvalidPhysId; - - uint32_t shiftType = o3.as().predicate(); - uint64_t opShift = o3.as().valueAs(); - - if (shiftType > 0x3 || opShift >= opSize) - goto InvalidImmediate; - - opcode.reset(uint32_t(opData.shiftedOp) << 21); - opcode.addImm(x, 31); - opcode.addImm(shiftType, 22); - opcode.addReg(o2, 16); - opcode.addImm(opShift, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseCmpCmn: { - const InstDB::EncodingData::BaseCmpCmn& opData = InstDB::EncodingData::baseCmpCmn[encodingIndex]; - - uint32_t x; - if (!checkGpType(o0, kWX, &x)) - goto InvalidInstruction; - - if (isign4 == ENC_OPS2(Reg, Imm)) { - // CMN|CMP (immediate) - ZR is not allowed. - if (!checkGpId(o0, kSP)) - goto InvalidPhysId; - - // CMN|CMP (immediate) use 12-bit immediate optionally shifted by 'LSL #12'. - const Imm& imm12 = o1.as(); - uint32_t immShift = 0; - uint64_t immValue = imm12.valueAs(); - - if (immValue > 0xFFFu) { - if ((immValue & ~uint64_t(0xFFFu << 12)) != 0) - goto InvalidImmediate; - immShift = 1; - immValue >>= 12; - } - - opcode.reset(uint32_t(opData.immediateOp) << 24); - opcode.addImm(x, 31); - opcode.addImm(immShift, 22); - opcode.addImm(immValue, 10); - opcode.addReg(o0, 5); - opcode.addReg(Gp::kIdZr, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) { - uint32_t opSize = x ? 64 : 32; - uint32_t sType = 0; - uint64_t shift = 0; - - if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { - sType = o2.as().predicate(); - shift = o2.as().valueAs(); - } - - bool hasSP = o0.as().isSP() || o1.as().isSP(); - - // Shift operation - LSL, LSR, ASR. - if (sType <= uint32_t(ShiftOp::kASR)) { - if (!hasSP) { - if (!checkSignature(o0, o1)) { - goto InvalidInstruction; - } - - if (shift >= opSize) { - goto InvalidImmediate; - } - - opcode.reset(uint32_t(opData.shiftedOp) << 21); - opcode.addImm(x, 31); - opcode.addImm(sType, 22); - opcode.addReg(o1, 16); - opcode.addImm(shift, 10); - opcode.addReg(o0, 5); - opcode.addReg(Gp::kIdZr, 0); - goto EmitOp; - } - - // SP register can only be used with LSL or Extend. - if (sType != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW); - } - - // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX. - sType -= uint32_t(ShiftOp::kUXTB); - if (sType > 7 || shift > 4) { - goto InvalidImmediate; - } - - // Validate whether the register operands match extend option. - if (o1.as().regType() != extendOptionToRegType(sType) || o0.as().regType() < o1.as().regType()) { - goto InvalidInstruction; - } - - opcode.reset(uint32_t(opData.extendedOp) << 21); - opcode.addImm(x, 31); - opcode.addReg(o1, 16); - opcode.addImm(sType, 13); - opcode.addImm(shift, 10); - opcode.addReg(o0, 5); - opcode.addReg(Gp::kIdZr, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseMvnNeg: { - const InstDB::EncodingData::BaseMvnNeg& opData = InstDB::EncodingData::baseMvnNeg[encodingIndex]; - - uint32_t x; - if (!checkGpType(o0, o1, kWX, &x)) - goto InvalidInstruction; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addReg(o1, 16); - opcode.addReg(o0, 0); - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - goto EmitOp; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - uint32_t opSize = x ? 64 : 32; - uint32_t shiftType = o2.as().predicate(); - uint64_t opShift = o2.as().valueAs(); - - if (shiftType > uint32_t(ShiftOp::kROR) || opShift >= opSize) - goto InvalidImmediate; - - opcode.addImm(shiftType, 22); - opcode.addImm(opShift, 10); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseTst: { - const InstDB::EncodingData::BaseTst& opData = InstDB::EncodingData::baseTst[encodingIndex]; - - uint32_t x; - if (!checkGpType(o0, kWX, &x)) - goto InvalidInstruction; - - uint32_t opSize = x ? 64 : 32; - - if (isign4 == ENC_OPS2(Reg, Imm) && opData.immediateOp != 0) { - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - // TST (immediate) uses a LogicalImm format described by N:R:S values. - uint64_t immMask = Support::lsbMask(opSize); - uint64_t immValue = o1.as().valueAs(); - - // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR. - LogicalImm logicalImm; - if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm)) - goto InvalidImmediate; - - opcode.reset(uint32_t(opData.immediateOp) << 22); - opcode.addLogicalImm(logicalImm); - opcode.addImm(x, 31); - opcode.addReg(o0, 5); - opcode.addReg(Gp::kIdZr, 0); - goto EmitOp; - } - - opcode.reset(uint32_t(opData.shiftedOp) << 21); - opcode.addImm(x, 31); - opcode.addReg(o1, 16); - opcode.addReg(o0, 5); - opcode.addReg(Gp::kIdZr, 0); - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - goto EmitOp; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - uint32_t shiftType = o2.as().predicate(); - uint64_t opShift = o2.as().valueAs(); - - if (shiftType > 0x3 || opShift >= opSize) - goto InvalidImmediate; - - opcode.addImm(shiftType, 22); - opcode.addImm(opShift, 10); - goto EmitOp; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Bit Manipulation] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseBfc: { - const InstDB::EncodingData::BaseBfc& opData = InstDB::EncodingData::baseBfc[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Imm, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0)) - goto InvalidPhysId; - - uint64_t lsb = o1.as().valueAs(); - uint64_t width = o2.as().valueAs(); - uint32_t opSize = x ? 64 : 32; - - if (lsb >= opSize || width == 0 || width > opSize) - goto InvalidImmediate; - - uint32_t lsb32 = Support::neg(uint32_t(lsb)) & (opSize - 1); - uint32_t width32 = uint32_t(width) - 1; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addImm(lsb32, 16); - opcode.addImm(width32, 10); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseBfi: { - const InstDB::EncodingData::BaseBfi& opData = InstDB::EncodingData::baseBfi[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1)) - goto InvalidPhysId; - - uint64_t lsb = o2.as().valueAs(); - uint64_t width = o3.as().valueAs(); - uint32_t opSize = x ? 64 : 32; - - if (lsb >= opSize || width == 0 || width > opSize) - goto InvalidImmediate; - - uint32_t lImm = Support::neg(uint32_t(lsb)) & (opSize - 1); - uint32_t wImm = uint32_t(width) - 1; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addImm(lImm, 16); - opcode.addImm(wImm, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseBfm: { - const InstDB::EncodingData::BaseBfm& opData = InstDB::EncodingData::baseBfm[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1)) - goto InvalidPhysId; - - uint64_t immR = o2.as().valueAs(); - uint64_t immS = o3.as().valueAs(); - uint32_t opSize = x ? 64 : 32; - - if ((immR | immS) >= opSize) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addImm(immR, 16); - opcode.addImm(immS, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseBfx: { - const InstDB::EncodingData::BaseBfx& opData = InstDB::EncodingData::baseBfx[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1)) - goto InvalidPhysId; - - uint64_t lsb = o2.as().valueAs(); - uint64_t width = o3.as().valueAs(); - uint32_t opSize = x ? 64 : 32; - - if (lsb >= opSize || width == 0 || width > opSize) - goto InvalidImmediate; - - uint32_t lsb32 = uint32_t(lsb); - uint32_t width32 = lsb32 + uint32_t(width) - 1u; - - if (width32 >= opSize) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addImm(lsb32, 16); - opcode.addImm(width32, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseExtend: { - const InstDB::EncodingData::BaseExtend& opData = InstDB::EncodingData::baseExtend[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - uint32_t x; - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!o1.as().isGp32()) - goto InvalidInstruction; - - if (!checkGpId(o0, o1)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseExtract: { - const InstDB::EncodingData::BaseExtract& opData = InstDB::EncodingData::baseExtract[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - uint32_t x; - if (!checkGpType(o0, kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1, o2)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, o2)) - goto InvalidPhysId; - - uint64_t lsb = o3.as().valueAs(); - uint32_t opSize = x ? 64 : 32; - - if (lsb >= opSize) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addReg(o2, 16); - opcode.addImm(lsb, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseRev: { - if (isign4 == ENC_OPS2(Reg, Reg)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1)) - goto InvalidPhysId; - - opcode.reset(0b01011010110000000000100000000000); - opcode.addImm(x, 31); - opcode.addImm(x, 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseShift: { - const InstDB::EncodingData::BaseShift& opData = InstDB::EncodingData::baseShift[encodingIndex]; - - uint32_t x; - if (!checkGpType(o0, kWX, &x)) - goto InvalidInstruction; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!checkSignature(o0, o1, o2)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, o2, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.registerOp()); - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp()) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - uint64_t immR = o2.as().valueAs(); - uint32_t opSize = x ? 64 : 32; - - if (immR >= opSize) - goto InvalidImmediate; - - opcode.reset(opData.immediateOp()); - opcode.addImm(x, 31); - opcode.addImm(x, 22); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - - if (opcode.get() & B(10)) { - // ASR and LSR (immediate) has the same logic. - opcode.addImm(x, 15); - opcode.addImm(immR, 16); - goto EmitOp; - } - - if (opData.ror == 0) { - // LSL (immediate) is an alias to UBFM - uint32_t ubfmImmR = Support::neg(uint32_t(immR)) & (opSize - 1); - uint32_t ubfmImmS = opSize - 1 - uint32_t(immR); - - opcode.addImm(ubfmImmR, 16); - opcode.addImm(ubfmImmS, 10); - goto EmitOp; - } - else { - // ROR (immediate) is an alias to EXTR. - opcode.addImm(immR, 10); - opcode.addReg(o1, 16); - goto EmitOp; - } - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Conditionals] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseCCmp: { - const InstDB::EncodingData::BaseCCmp& opData = InstDB::EncodingData::baseCCmp[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm) || isign4 == ENC_OPS4(Reg, Imm, Imm, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - uint64_t nzcv = o2.as().valueAs(); - uint64_t cond = o3.as().valueAs(); - - if ((nzcv | cond) > 0xFu) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); - opcode.addImm(nzcv, 0); - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - // CCMN|CCMP (register) form. - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o1, kZR)) - goto InvalidPhysId; - - opcode.addReg(o1, 16); - opcode.addReg(o0, 5); - goto EmitOp; - } - else { - // CCMN|CCMP (immediate) form. - uint64_t imm5 = o1.as().valueAs(); - if (imm5 > 0x1F) - goto InvalidImmediate; - - opcode.addImm(1, 11); - opcode.addImm(imm5, 16); - opcode.addReg(o0, 5); - goto EmitOp; - } - } - - break; - } - - case InstDB::kEncodingBaseCInc: { - const InstDB::EncodingData::BaseCInc& opData = InstDB::EncodingData::baseCInc[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { - uint32_t x; - if (!checkGpType(o0, o1, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - uint64_t cond = o2.as().valueAs(); - if (cond - 2u > 0xEu) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addReg(o1, 16); - opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseCSel: { - const InstDB::EncodingData::BaseCSel& opData = InstDB::EncodingData::baseCSel[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - uint32_t x; - if (!checkGpType(o0, o1, o2, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, o2, kZR)) - goto InvalidPhysId; - - uint64_t cond = o3.as().valueAs(); - if (cond > 0xFu) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseCSet: { - const InstDB::EncodingData::BaseCSet& opData = InstDB::EncodingData::baseCSet[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - uint64_t cond = o1.as().valueAs(); - if (cond - 2u >= 0xEu) - goto InvalidImmediate; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Min/Max] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseMinMax: { - const InstDB::EncodingData::BaseMinMax& opData = InstDB::EncodingData::baseMinMax[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1, o2)) - goto InvalidInstruction; - - opcode.reset(opData.regOp); - opcode.addImm(x, 31); - opcode.addReg(o2, 16); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { - uint32_t x; - if (!checkGpType(o0, InstDB::kWX, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - uint64_t imm = o2.as().valueAs(); - - if (opData.immOp & (1u << 18)) { - // Zero extend imm. - if (!Support::isUInt8(imm)) { - goto InvalidImmediate; - } - } - else { - // Sign extend imm. - if (!Support::isInt8(int64_t(imm))) { - goto InvalidImmediate; - } - } - - opcode.reset(opData.immOp); - opcode.addImm(x, 31); - opcode.addImm(uint32_t(imm & 0xFFu), 10); - opcode.addReg(o1, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Special] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseAtDcIcTlbi: { - const InstDB::EncodingData::BaseAtDcIcTlbi& opData = InstDB::EncodingData::baseAtDcIcTlbi[encodingIndex]; - - if (isign4 == ENC_OPS1(Imm) || isign4 == ENC_OPS2(Imm, Reg)) { - if (opData.mandatoryReg && isign4 != ENC_OPS2(Imm, Reg)) - goto InvalidInstruction; - - if (o0.as().valueAs() > 0x7FFFu) - goto InvalidImmediate; - - uint32_t imm = o0.as().valueAs(); - if ((imm & opData.immVerifyMask) != opData.immVerifyData) - goto InvalidImmediate; - - uint32_t rt = 31; - if (o1.isReg()) { - if (!o1.as().isGp64()) - goto InvalidInstruction; - - if (!checkGpId(o1, kZR)) - goto InvalidPhysId; - - rt = o1.id() & 31; - } - - opcode.reset(0b11010101000010000000000000000000); - opcode.addImm(imm, 5); - opcode.addReg(rt, 0); - goto EmitOp; - } - break; - } - - case InstDB::kEncodingBaseMrs: { - if (isign4 == ENC_OPS2(Reg, Imm)) { - if (!o0.as().isGp64()) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - if (o1.as().valueAs() > 0xFFFFu) - goto InvalidImmediate; - - uint32_t imm = o1.as().valueAs(); - if (!(imm & B(15))) - goto InvalidImmediate; - - opcode.reset(0b11010101001100000000000000000000); - opcode.addImm(imm, 5); - opcode.addReg(o0, 0); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseMsr: { - if (isign4 == ENC_OPS2(Imm, Reg)) { - if (!o1.as().isGp64()) - goto InvalidInstruction; - - if (o0.as().valueAs() > 0xFFFFu) - goto InvalidImmediate; - - uint32_t imm = o0.as().valueAs(); - if (!(imm & B(15))) - goto InvalidImmediate; - - if (!checkGpId(o1, kZR)) - goto InvalidPhysId; - - opcode.reset(0b11010101000100000000000000000000); - opcode.addImm(imm, 5); - opcode.addReg(o1, 0); - goto EmitOp; - } - - if (isign4 == ENC_OPS2(Imm, Imm)) { - if (o0.as().valueAs() > 0x1Fu) - goto InvalidImmediate; - - if (o1.as().valueAs() > 0xFu) - goto InvalidImmediate; - - uint32_t op = o0.as().valueAs(); - uint32_t cRm = o1.as().valueAs(); - - uint32_t op1 = uint32_t(op) >> 3; - uint32_t op2 = uint32_t(op) & 0x7u; - - opcode.reset(0b11010101000000000100000000011111); - opcode.addImm(op1, 16); - opcode.addImm(cRm, 8); - opcode.addImm(op2, 5); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseSys: { - if (isign4 == ENC_OPS4(Imm, Imm, Imm, Imm)) { - if (o0.as().valueAs() > 0x7u || - o1.as().valueAs() > 0xFu || - o2.as().valueAs() > 0xFu || - o3.as().valueAs() > 0x7u) - goto InvalidImmediate; - - uint32_t op1 = o0.as().valueAs(); - uint32_t cRn = o1.as().valueAs(); - uint32_t cRm = o2.as().valueAs(); - uint32_t op2 = o3.as().valueAs(); - uint32_t rt = 31; - - const Operand_& o4 = opExt[EmitterUtils::kOp4]; - if (o4.isReg()) { - if (!o4.as().isGp64()) - goto InvalidInstruction; - - if (!checkGpId(o4, kZR)) - goto InvalidPhysId; - - rt = o4.id() & 31; - } - else if (!o4.isNone()) { - goto InvalidInstruction; - } - - opcode.reset(0b11010101000010000000000000000000); - opcode.addImm(op1, 16); - opcode.addImm(cRn, 12); - opcode.addImm(cRm, 8); - opcode.addImm(op2, 5); - opcode.addImm(rt, 0); - goto EmitOp; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Branch] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseBranchReg: { - const InstDB::EncodingData::BaseBranchReg& opData = InstDB::EncodingData::baseBranchReg[encodingIndex]; - - if (isign4 == ENC_OPS1(Reg)) { - if (!o0.as().isGp64()) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode); - opcode.addReg(o0, 5); - goto EmitOp; - } - - break; - } - - case InstDB::kEncodingBaseBranchRel: { - const InstDB::EncodingData::BaseBranchRel& opData = InstDB::EncodingData::baseBranchRel[encodingIndex]; - - if (isign4 == ENC_OPS1(Label) || isign4 == ENC_OPS1(Imm)) { - opcode.reset(opData.opcode); - rmRel = &o0; - - // A variation that uses Cond code (or where Cond code is forced like BC.). - if (instCC != CondCode::kAL || Support::bitTest(opcode.v, 30)) { - if (opcode.hasX()) { - // Condition code cannot be applied when the instruction has X bit set (this would be BL instruction). - goto InvalidInstruction; - } - - opcode |= B(30); - opcode.addImm(condCodeToOpcodeCond(uint32_t(instCC)), 0); - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); - goto EmitOp_Rel; - } - - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 0, 26, 2); - goto EmitOp_Rel; - } - - break; - } - - case InstDB::kEncodingBaseBranchCmp: { - const InstDB::EncodingData::BaseBranchCmp& opData = InstDB::EncodingData::baseBranchCmp[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) { - uint32_t x; - if (!checkGpType(o0, kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode); - opcode.addImm(x, 31); - opcode.addReg(o0, 0); - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); - - rmRel = &o1; - goto EmitOp_Rel; - } - - break; - } - - case InstDB::kEncodingBaseBranchTst: { - const InstDB::EncodingData::BaseBranchTst& opData = InstDB::EncodingData::baseBranchTst[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Imm, Label) || isign4 == ENC_OPS3(Reg, Imm, Imm)) { - uint32_t x; - if (!checkGpType(o0, kWX, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - uint64_t imm = o1.as().valueAs(); - - opcode.reset(opData.opcode); - if (imm >= 32) { - if (!x) - goto InvalidImmediate; - opcode.addImm(x, 31); - imm &= 0x1F; - } - - opcode.addReg(o0, 0); - opcode.addImm(imm, 19); - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 14, 2); - - rmRel = &o2; - goto EmitOp_Rel; - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Prefetch] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBasePrfm: { - const InstDB::EncodingData::BasePrfm& opData = InstDB::EncodingData::basePrfm[encodingIndex]; - - if (isign4 == ENC_OPS2(Imm, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - uint32_t immShift = 3u; - - if (o0.as().valueAs() > 0x1Fu) - goto InvalidImmediate; - - if (!armCheckMemBaseIndexRel(m)) - goto InvalidAddress; - - int64_t offset = m.offset(); - uint32_t prfop = o0.as().valueAs(); - - if (m.hasBaseReg()) { - // [Base {Offset | Index}] - if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; - if (opt == 0xFF) - goto InvalidAddress; - - uint32_t shift = m.shift(); - uint32_t s = shift != 0; - - if (s && shift != immShift) - goto InvalidAddressScale; - - opcode.reset(uint32_t(opData.registerOp) << 21); - opcode.addImm(opt, 13); - opcode.addImm(s, 12); - opcode |= B(11); - opcode.addImm(prfop, 0); - goto EmitOp_MemBaseIndex_Rn5_Rm16; - } - - if (!Support::isInt32(offset)) - goto InvalidDisplacement; - - int32_t offset32 = int32_t(offset); - - if (m.isPreOrPost()) - goto InvalidAddress; - - uint32_t imm12 = uint32_t(offset32) >> immShift; - - if (Support::isUInt12(imm12) && (imm12 << immShift) == uint32_t(offset32)) { - opcode.reset(uint32_t(opData.sOffsetOp) << 22); - opcode.addImm(imm12, 10); - opcode.addImm(prfop, 0); - goto EmitOp_MemBase_Rn5; - } - - if (Support::isInt9(offset32)) { - opcode.reset(uint32_t(opData.uOffsetOp) << 21); - opcode.addImm(uint32_t(offset32) & 0x1FFu, 12); - opcode.addImm(prfop, 0); - goto EmitOp_MemBase_Rn5; - } - - goto InvalidAddress; - } - else { - opcode.reset(uint32_t(opData.literalOp) << 24); - opcode.addImm(prfop, 0); - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); - goto EmitOp_Rel; - } - } - - break; - } - - // ------------------------------------------------------------------------ - // [Base - Load / Store] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingBaseLdSt: { - const InstDB::EncodingData::BaseLdSt& opData = InstDB::EncodingData::baseLdSt[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - uint32_t x; - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - // Instructions that work with either word or dword have the unsigned - // offset shift set to 2 (word), so we set it to 3 (dword) if this is - // X version of the instruction. - uint32_t xShiftMask = uint32_t(opData.uOffsetShift == 2); - uint32_t immShift = uint32_t(opData.uOffsetShift) + (x & xShiftMask); - - if (!armCheckMemBaseIndexRel(m)) - goto InvalidAddress; - - int64_t offset = m.offset(); - if (m.hasBaseReg()) { - // [Base {Offset | Index}] - if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; - if (opt == 0xFF) - goto InvalidAddress; - - uint32_t shift = m.shift(); - uint32_t s = shift != 0; - - if (s && shift != immShift) - goto InvalidAddressScale; - - opcode.reset(uint32_t(opData.registerOp) << 21); - opcode.xorImm(x, opData.xOffset); - opcode.addImm(opt, 13); - opcode.addImm(s, 12); - opcode |= B(11); - opcode.addReg(o0, 0); - goto EmitOp_MemBaseIndex_Rn5_Rm16; - } - - // Makes it easier to work with the offset especially on 32-bit arch. - if (!Support::isInt32(offset)) - goto InvalidDisplacement; - int32_t offset32 = int32_t(offset); - - if (m.isPreOrPost()) { - if (!Support::isInt9(offset32)) - goto InvalidDisplacement; - - opcode.reset(uint32_t(opData.prePostOp) << 21); - opcode.xorImm(x, opData.xOffset); - opcode.addImm(offset32 & 0x1FF, 12); - opcode.addImm(m.isPreIndex(), 11); - opcode |= B(10); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - else { - uint32_t imm12 = uint32_t(offset32) >> immShift; - - // Alternative form of LDUR/STUR and related instructions as described by AArch64 reference manual: - // - // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset. - if (!Support::isUInt12(imm12) || (imm12 << immShift) != uint32_t(offset32)) { - instId = opData.uAltInstId; - instInfo = &InstDB::_instInfoTable[instId]; - encodingIndex = instInfo->_encodingDataIndex; - goto Case_BaseLdurStur; - } - - opcode.reset(uint32_t(opData.uOffsetOp) << 22); - opcode.xorImm(x, opData.xOffset); - opcode.addImm(imm12, 10); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - } - else { - if (!opData.literalOp) - goto InvalidAddress; - - opcode.reset(uint32_t(opData.literalOp) << 24); - opcode.xorImm(x, opData.xOffset); - opcode.addReg(o0, 0); - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); - goto EmitOp_Rel; - } - } - - break; - } - - case InstDB::kEncodingBaseLdpStp: { - const InstDB::EncodingData::BaseLdpStp& opData = InstDB::EncodingData::baseLdpStp[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { - const Mem& m = o2.as(); - rmRel = &m; - - uint32_t x; - if (!checkGpType(o0, o1, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - if (m.baseType() != RegType::kGp64 || m.hasIndex()) - goto InvalidAddress; - - if (m.isOffset64Bit()) - goto InvalidDisplacement; - - uint32_t offsetShift = opData.offsetShift + x; - int32_t offset32 = m.offsetLo32() >> offsetShift; - - // Make sure we didn't lose bits by applying the mandatory offset shift. - if (uint32_t(offset32) << offsetShift != uint32_t(m.offsetLo32())) - goto InvalidDisplacement; - - // Offset is encoded as 7-bit immediate. - if (!Support::isInt7(offset32)) - goto InvalidDisplacement; - - if (m.isPreOrPost() && offset32 != 0) { - if (!opData.prePostOp) - goto InvalidAddress; - - opcode.reset(uint32_t(opData.prePostOp) << 22); - opcode.addImm(m.isPreIndex(), 24); - } - else { - opcode.reset(uint32_t(opData.offsetOp) << 22); - } - - opcode.addImm(x, opData.xOffset); - opcode.addImm(offset32 & 0x7F, 15); - opcode.addReg(o1, 10); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseStx: { - const InstDB::EncodingData::BaseStx& opData = InstDB::EncodingData::baseStx[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { - const Mem& m = o2.as(); - uint32_t x; - - if (!o0.as().isGp32() || !checkGpType(o1, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o0, 16); - opcode.addReg(o1, 0); - - rmRel = &m; - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseLdxp: { - const InstDB::EncodingData::BaseLdxp& opData = InstDB::EncodingData::baseLdxp[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { - const Mem& m = o2.as(); - uint32_t x; - - if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o1, 10); - opcode.addReg(o0, 0); - - rmRel = &m; - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseStxp: { - const InstDB::EncodingData::BaseStxp& opData = InstDB::EncodingData::baseStxp[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) { - const Mem& m = o3.as(); - uint32_t x; - - if (!o0.as().isGp32() || !checkGpType(o1, opData.rType, &x) || !checkSignature(o1, o2)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, o2, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o0, 16); - opcode.addReg(o2, 10); - opcode.addReg(o1, 0); - - rmRel = &m; - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseRM_NoImm: { - const InstDB::EncodingData::BaseRM_NoImm& opData = InstDB::EncodingData::baseRM_NoImm[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - uint32_t x; - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.rHiId)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o0, 0); - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseRM_SImm9: { -Case_BaseLdurStur: - const InstDB::EncodingData::BaseRM_SImm9& opData = InstDB::EncodingData::baseRM_SImm9[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - uint32_t x; - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.rHiId)) - goto InvalidPhysId; - - if (m.hasBaseReg() && !m.hasIndex()) { - if (m.isOffset64Bit()) - goto InvalidDisplacement; - - int32_t offset32 = m.offsetLo32() >> opData.immShift; - if (Support::shl(offset32, opData.immShift) != m.offsetLo32()) - goto InvalidDisplacement; - - if (!Support::isInt9(offset32)) - goto InvalidDisplacement; - - if (m.isFixedOffset()) { - opcode.reset(opData.offsetOp()); - } - else { - if (!opData.prePostOp()) - goto InvalidInstruction; - - opcode.reset(opData.prePostOp()); - opcode.xorImm(m.isPreIndex(), 11); - } - - opcode.xorImm(x, opData.xOffset); - opcode.addImm(offset32 & 0x1FF, 12); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - - goto InvalidAddress; - } - - break; - } - - case InstDB::kEncodingBaseRM_SImm10: { - const InstDB::EncodingData::BaseRM_SImm10& opData = InstDB::EncodingData::baseRM_SImm10[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - uint32_t x; - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, opData.rHiId)) - goto InvalidPhysId; - - if (m.hasBaseReg() && !m.hasIndex()) { - if (m.isOffset64Bit()) - goto InvalidDisplacement; - - int32_t offset32 = m.offsetLo32() >> opData.immShift; - if (Support::shl(offset32, opData.immShift) != m.offsetLo32()) - goto InvalidDisplacement; - - if (!Support::isInt10(offset32)) - goto InvalidDisplacement; - - if (m.isPostIndex()) - goto InvalidAddress; - - // Offset has 10 bits, sign is stored in the 10th bit. - offset32 &= 0x3FF; - - opcode.reset(opData.opcode()); - opcode.xorImm(m.isPreIndex(), 11); - opcode.xorImm(x, opData.xOffset); - opcode.addImm(offset32 >> 9, 22); - opcode.addImm(offset32, 12); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - - goto InvalidAddress; - } - - break; - } - - case InstDB::kEncodingBaseAtomicOp: { - const InstDB::EncodingData::BaseAtomicOp& opData = InstDB::EncodingData::baseAtomicOp[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { - const Mem& m = o2.as(); - uint32_t x; - - if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkGpId(o0, o1, kZR)) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o0, 16); - opcode.addReg(o1, 0); - - rmRel = &m; - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseAtomicSt: { - const InstDB::EncodingData::BaseAtomicSt& opData = InstDB::EncodingData::baseAtomicSt[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - uint32_t x; - - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkGpId(o0, kZR)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o0, 16); - opcode.addReg(Gp::kIdZr, 0); - - rmRel = &m; - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - case InstDB::kEncodingBaseAtomicCasp: { - const InstDB::EncodingData::BaseAtomicCasp& opData = InstDB::EncodingData::baseAtomicCasp[encodingIndex]; - const Operand_& o4 = opExt[EmitterUtils::kOp4]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) { - const Mem& m = o4.as(); - uint32_t x; - - if (!checkGpType(o0, opData.rType, &x)) - goto InvalidInstruction; - - if (!checkSignature(o0, o1, o2, o3)) - goto InvalidInstruction; - - if (!checkEven(o0, o2) || !checkGpId(o0, o2, kZR)) - goto InvalidPhysId; - - if (!checkConsecutive(o0, o1) || !checkConsecutive(o2, o3)) - goto InvalidPhysId; - - opcode.reset(opData.opcode()); - opcode.addImm(x, opData.xOffset); - opcode.addReg(o0, 16); - opcode.addReg(o2, 0); - - rmRel = &m; - goto EmitOp_MemBaseNoImm_Rn5; - } - - break; - } - - // ------------------------------------------------------------------------ - // [FSimd - Instructions] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingFSimdSV: { - const InstDB::EncodingData::FSimdSV& opData = InstDB::EncodingData::fSimdSV[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - uint32_t q = diff(o1.as().regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - if (o0.as().hasElementType()) - goto InvalidInstruction; - - // This operation is only defined for: - // hD, vS.{4|8}h (16-bit) - // sD, vS.4s (32-bit) - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - uint32_t elementSz = diff(o1.as().elementType(), VecElementType::kH); - - // Size greater than 1 means 64-bit elements, not supported. - if ((sz | elementSz) > 1 || sz != elementSz) - goto InvalidInstruction; - - // Size 1 (32-bit float) requires at least 4 elements. - if (sz && !q) - goto InvalidInstruction; - - // Bit flipping according to sz. - static const uint32_t szBits[] = { B(29), 0 }; - - opcode.reset(opData.opcode << 10); - opcode ^= szBits[sz]; - opcode.addImm(q, 30); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingFSimdVV: { - const InstDB::EncodingData::FSimdVV& opData = InstDB::EncodingData::fSimdVV[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - if (!pickFpOpcode(o0.as(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingFSimdVVV: { - const InstDB::EncodingData::FSimdVVV& opData = InstDB::EncodingData::fSimdVVV[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - if (!pickFpOpcode(o0.as(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingFSimdVVVe: { - const InstDB::EncodingData::FSimdVVVe& opData = InstDB::EncodingData::fSimdVVVe[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!o2.as().hasElementIndex()) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - if (!pickFpOpcode(o0.as(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5_Rm16; - } - else { - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - uint32_t q = o1.as().isVec128(); - uint32_t sz; - - if (!pickFpOpcode(o0.as(), opData.elementScalarOp(), InstDB::kHF_D, opData.elementVectorOp(), InstDB::kHF_D, &opcode, &sz)) - goto InvalidInstruction; - - if (sz == 0 && o2.as().id() > 15) - goto InvalidPhysId; - - uint32_t elementIndex = o2.as().elementIndex(); - if (elementIndex > (7u >> sz)) - goto InvalidElementIndex; - - uint32_t hlm = elementIndex << sz; - opcode.addImm(q, 30); - opcode.addImm(hlm & 3u, 20); - opcode.addImm(hlm >> 2, 11); - goto EmitOp_Rd0_Rn5_Rm16; - } - } - - break; - } - - case InstDB::kEncodingFSimdVVVV: { - const InstDB::EncodingData::FSimdVVVV& opData = InstDB::EncodingData::fSimdVVVV[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { - if (!matchSignature(o0, o1, o2, o3, instFlags)) - goto InvalidInstruction; - - if (!pickFpOpcode(o0.as(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5_Rm16_Ra10; - } - - break; - } - - case InstDB::kEncodingSimdFcadd: { - const InstDB::EncodingData::SimdFcadd& opData = InstDB::EncodingData::simdFcadd[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - if (!checkSignature(o0, o1, o2) || o0.as().hasElementIndex()) - goto InvalidInstruction; - - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - uint32_t sz = diff(o0.as().elementType(), VecElementType::kB); - if (sz == 0 || sz > 3) - goto InvalidInstruction; - - // 0 <- 90deg. - // 1 <- 270deg. - uint32_t rot = 0; - if (o3.as().value() == 270) - rot = 1; - else if (o3.as().value() != 90) - goto InvalidImmediate; - - opcode.reset(opData.opcode()); - opcode.addImm(q, 30); - opcode.addImm(sz, 22); - opcode.addImm(rot, 12); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingSimdFccmpFccmpe: { - const InstDB::EncodingData::SimdFccmpFccmpe& opData = InstDB::EncodingData::simdFccmpFccmpe[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - if (sz > 2) - goto InvalidInstruction; - - if (!checkSignature(o0, o1) || o0.as().hasElementType()) - goto InvalidInstruction; - - uint64_t nzcv = o2.as().valueAs(); - uint64_t cond = o3.as().valueAs(); - - if ((nzcv | cond) > 0xFu) - goto InvalidImmediate; - - uint32_t type = (sz - 1) & 0x3u; - - opcode.reset(opData.opcode()); - opcode.addImm(type, 22); - opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); - opcode.addImm(nzcv, 0); - - goto EmitOp_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingSimdFcm: { - const InstDB::EncodingData::SimdFcm& opData = InstDB::EncodingData::simdFcm[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.hasRegisterOp()) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - if (!pickFpOpcode(o0.as(), opData.registerScalarOp(), opData.registerScalarHf(), opData.registerVectorOp(), opData.registerVectorHf(), &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5_Rm16; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.hasZeroOp()) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (o2.as().value() != 0 || o2.as().predicate() != 0) - goto InvalidImmediate; - - if (!pickFpOpcode(o0.as(), opData.zeroScalarOp(), InstDB::kHF_B, opData.zeroVectorOp(), InstDB::kHF_B, &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdFcmla: { - const InstDB::EncodingData::SimdFcmla& opData = InstDB::EncodingData::simdFcmla[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - uint32_t sz = diff(o0.as().elementType(), VecElementType::kB); - if (sz == 0 || sz > 3) - goto InvalidInstruction; - - uint32_t rot = 0; - switch (o3.as().value()) { - case 0 : rot = 0; break; - case 90 : rot = 1; break; - case 180: rot = 2; break; - case 270: rot = 3; break; - default: - goto InvalidImmediate; - } - - if (!o2.as().hasElementIndex()) { - if (!checkSignature(o1, o2)) - goto InvalidInstruction; - - opcode.reset(opData.regularOp()); - opcode.addImm(q, 30); - opcode.addImm(sz, 22); - opcode.addImm(rot, 11); - goto EmitOp_Rd0_Rn5_Rm16; - } - else { - if (o0.as().elementType() != o2.as().elementType()) - goto InvalidInstruction; - - // Only allowed vectors are: 4H, 8H, and 4S. - if (!(sz == 1 || (q == 1 && sz == 2))) - goto InvalidInstruction; - - // Element index ranges: - // 4H - ElementIndex[0..1] (index 2..3 is UNDEFINED). - // 8H - ElementIndex[0..3]. - // 4S - ElementIndex[0..1]. - uint32_t elementIndex = o2.as().elementIndex(); - uint32_t hlFieldShift = sz == 1 ? 0u : 1u; - uint32_t maxElementIndex = q == 1 && sz == 1 ? 3u : 1u; - - if (elementIndex > maxElementIndex) - goto InvalidElementIndex; - - uint32_t hl = elementIndex << hlFieldShift; - - opcode.reset(opData.elementOp()); - opcode.addImm(q, 30); - opcode.addImm(sz, 22); - opcode.addImm(hl & 1u, 21); // L field. - opcode.addImm(hl >> 1, 11); // H field. - opcode.addImm(rot, 13); - goto EmitOp_Rd0_Rn5_Rm16; - } - } - - break; - } - - case InstDB::kEncodingSimdFcmpFcmpe: { - const InstDB::EncodingData::SimdFcmpFcmpe& opData = InstDB::EncodingData::simdFcmpFcmpe[encodingIndex]; - - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - uint32_t type = (sz - 1) & 0x3u; - - if (sz > 2) - goto InvalidInstruction; - - if (o0.as().hasElementType()) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - opcode.addImm(type, 22); - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - goto EmitOp_Rn5_Rm16; - } - - if (isign4 == ENC_OPS2(Reg, Imm)) { - if (o1.as().value() != 0 || o1.as().predicate() != 0) - goto InvalidInstruction; - - opcode |= B(3); - goto EmitOp_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdFcsel: { - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - if (!checkSignature(o0, o1, o2)) - goto InvalidInstruction; - - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - uint32_t type = (sz - 1) & 0x3u; - - if (sz > 2 || o0.as().hasElementType()) - goto InvalidInstruction; - - uint64_t cond = o3.as().valueAs(); - if (cond > 0xFu) - goto InvalidImmediate; - - opcode.reset(0b00011110001000000000110000000000); - opcode.addImm(type, 22); - opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingSimdFcvt: { - if (isign4 == ENC_OPS2(Reg, Reg)) { - uint32_t dstSz = diff(o0.as().regType(), RegType::kVec16); - uint32_t srcSz = diff(o1.as().regType(), RegType::kVec16); - - if ((dstSz | srcSz) > 3) - goto InvalidInstruction; - - if (o0.as().hasElementType() || o1.as().hasElementType()) - goto InvalidInstruction; - - // Table that provides 'type' and 'opc' according to the dst/src combination. - static const uint8_t table[] = { - 0xFFu, // H <- H (Invalid). - 0x03u, // H <- S (type=00 opc=11). - 0x13u, // H <- D (type=01 opc=11). - 0xFFu, // H <- Q (Invalid). - 0x30u, // S <- H (type=11 opc=00). - 0xFFu, // S <- S (Invalid). - 0x10u, // S <- D (type=01 opc=00). - 0xFFu, // S <- Q (Invalid). - 0x31u, // D <- H (type=11 opc=01). - 0x01u, // D <- S (type=00 opc=01). - 0xFFu, // D <- D (Invalid). - 0xFFu, // D <- Q (Invalid). - 0xFFu, // Q <- H (Invalid). - 0xFFu, // Q <- S (Invalid). - 0xFFu, // Q <- D (Invalid). - 0xFFu // Q <- Q (Invalid). - }; - - uint32_t typeOpc = table[(dstSz << 2) | srcSz]; - opcode.reset(0b0001111000100010010000 << 10); - opcode.addImm(typeOpc >> 4, 22); - opcode.addImm(typeOpc & 15, 15); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdFcvtLN: { - const InstDB::EncodingData::SimdFcvtLN& opData = InstDB::EncodingData::simdFcvtLN[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - // Scalar form - only FCVTXN. - if (o0.as().isVec32() && o1.as().isVec64()) { - if (!opData.hasScalar()) - goto InvalidInstruction; - - if (o0.as().hasElementType() || o1.as().hasElementType()) - goto InvalidInstruction; - - opcode.reset(opData.scalarOp()); - opcode |= B(22); // sz bit must be 1, the only supported combination of FCVTXN. - goto EmitOp_Rd0_Rn5; - } - - opcode.reset(opData.vectorOp()); - - const Vec& rL = (instFlags & InstDB::kInstFlagLong) ? o0.as() : o1.as(); - const Vec& rN = (instFlags & InstDB::kInstFlagLong) ? o1.as() : o0.as(); - - uint32_t q = diff(rN.regType(), RegType::kVec64); - if (uint32_t(opcode.hasQ()) != q) - goto InvalidInstruction; - - if (rL.isVecS4() && rN.elementType() == VecElementType::kH && !opData.isCvtxn()) { - goto EmitOp_Rd0_Rn5; - } - - if (rL.isVecD2() && rN.elementType() == VecElementType::kS) { - opcode |= B(22); - goto EmitOp_Rd0_Rn5; - } - } - - break; - } - - case InstDB::kEncodingSimdFcvtSV: { - const InstDB::EncodingData::SimdFcvtSV& opData = InstDB::EncodingData::simdFcvtSV[encodingIndex]; - - // So we can support both IntToFloat and FloatToInt conversions. - const Operand_& oGp = opData.isFloatToInt() ? o0 : o1; - const Operand_& oVec = opData.isFloatToInt() ? o1 : o0; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (oGp.as().isGp() && oVec.as().isVec()) { - uint32_t x = oGp.as().isGp64(); - uint32_t type = diff(oVec.as().regType(), RegType::kVec16); - - if (type > 2u) - goto InvalidInstruction; - - type = (type - 1u) & 0x3; - opcode.reset(opData.generalOp()); - opcode.addImm(type, 22); - opcode.addImm(x, 31); - goto EmitOp_Rd0_Rn5; - } - - if (o0.as().isVec() && o1.as().isVec()) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!pickFpOpcode(o0.as(), opData.scalarIntOp(), InstDB::kHF_B, opData.vectorIntOp(), InstDB::kHF_B, &opcode)) - goto InvalidInstruction; - - goto EmitOp_Rd0_Rn5; - } - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.isFixedPoint()) { - if (o2.as().valueAs() >= 64) - goto InvalidInstruction; - - uint32_t scale = o2.as().valueAs(); - if (scale == 0) - goto InvalidInstruction; - - if (oGp.as().isGp() && oVec.as().isVec()) { - uint32_t x = oGp.as().isGp64(); - uint32_t type = diff(oVec.as().regType(), RegType::kVec16); - - uint32_t scaleLimit = 32u << x; - if (scale > scaleLimit) - goto InvalidInstruction; - - type = (type - 1u) & 0x3; - opcode.reset(opData.generalOp() ^ B(21)); - opcode.addImm(type, 22); - opcode.addImm(x, 31); - opcode.addImm(64u - scale, 10); - goto EmitOp_Rd0_Rn5; - } - - if (o0.as().isVec() && o1.as().isVec()) { - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - uint32_t sz; - if (!pickFpOpcode(o0.as(), opData.scalarFpOp(), InstDB::kHF_0, opData.vectorFpOp(), InstDB::kHF_0, &opcode, &sz)) - goto InvalidInstruction; - - uint32_t scaleLimit = 16u << sz; - if (scale > scaleLimit) - goto InvalidInstruction; - - uint32_t imm = Support::neg(scale) & Support::lsbMask(sz + 4 + 1); - opcode.addImm(imm, 16); - goto EmitOp_Rd0_Rn5; - } - } - - break; - } - - case InstDB::kEncodingSimdFmlal: { - const InstDB::EncodingData::SimdFmlal& opData = InstDB::EncodingData::simdFmlal[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - uint32_t qIsOptional = opData.optionalQ(); - - if (qIsOptional) { - // This instruction works with either 64-bit or 128-bit registers, - // encoded by Q bit. - if (q > 1) - goto InvalidInstruction; - } - else { - // This instruction requires 128-bit vector registers. - if (q != 1) - goto InvalidInstruction; - - // The instruction is ehtier B (bottom) or T (top), which is part of - // the opcode, which uses Q bit, so we have to clear it explicitly. - q = 0; - } - - if (uint32_t(o0.as().regType()) != uint32_t(o1.as().regType()) + qIsOptional || - uint32_t(o0.as().elementType()) != opData.tA || - uint32_t(o1.as().elementType()) != opData.tB) - goto InvalidInstruction; - - if (!o2.as().hasElementIndex()) { - if (!checkSignature(o1, o2)) - goto InvalidInstruction; - - opcode.reset(opData.vectorOp()); - opcode.addImm(q, 30); - goto EmitOp_Rd0_Rn5_Rm16; - } - else { - if (uint32_t(o2.as().elementType()) != opData.tElement) - goto InvalidInstruction; - - if (o2.as().id() > 15) - goto InvalidPhysId; - - uint32_t elementIndex = o2.as().elementIndex(); - if (elementIndex > 7u) - goto InvalidElementIndex; - - opcode.reset(opData.elementOp()); - opcode.addImm(q, 30); - opcode.addImm(elementIndex & 3u, 20); - opcode.addImm(elementIndex >> 2, 11); - goto EmitOp_Rd0_Rn5_Rm16; - } - } - - break; - } - - case InstDB::kEncodingSimdFmov: { - if (isign4 == ENC_OPS2(Reg, Reg)) { - // FMOV Gp <-> Vec opcode: - opcode.reset(0b00011110001001100000000000000000); - - if (o0.as().isGp() && o1.as().isVec()) { - // FMOV Wd, Hn (sf=0 type=11 rmode=00 op=110) - // FMOV Xd, Hn (sf=1 type=11 rmode=00 op=110) - // FMOV Wd, Sn (sf=0 type=00 rmode=00 op=110) - // FMOV Xd, Dn (sf=1 type=11 rmode=00 op=110) - // FMOV Xd, Vn.d[1] (sf=1 type=10 rmode=01 op=110) - uint32_t x = o0.as().isGp64(); - uint32_t sz = diff(o1.as().regType(), RegType::kVec16); - - uint32_t type = (sz - 1) & 0x3u; - uint32_t rModeOp = 0b00110; - - if (o1.as().hasElementIndex()) { - // Special case. - if (!x || !o1.as().isVecD2() || o1.as().elementIndex() != 1) - goto InvalidInstruction; - type = 0b10; - rModeOp = 0b01110; - } - else { - // Must be scalar. - if (sz > 2) - goto InvalidInstruction; - - if (o1.as().hasElementType()) - goto InvalidInstruction; - - if (o1.as().isVec32() && x) - goto InvalidInstruction; - - if (o1.as().isVec64() && !x) - goto InvalidInstruction; - } - - opcode.addImm(x, 31); - opcode.addImm(type, 22); - opcode.addImm(rModeOp, 16); - goto EmitOp_Rd0_Rn5; - } - - if (o0.as().isVec() && o1.as().isGp()) { - // FMOV Hd, Wn (sf=0 type=11 rmode=00 op=111) - // FMOV Hd, Xn (sf=1 type=11 rmode=00 op=111) - // FMOV Sd, Wn (sf=0 type=00 rmode=00 op=111) - // FMOV Dd, Xn (sf=1 type=11 rmode=00 op=111) - // FMOV Vd.d[1], Xn (sf=1 type=10 rmode=01 op=111) - uint32_t x = o1.as().isGp64(); - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - - uint32_t type = (sz - 1) & 0x3u; - uint32_t rModeOp = 0b00111; - - if (o0.as().hasElementIndex()) { - // Special case. - if (!x || !o0.as().isVecD2() || o0.as().elementIndex() != 1) - goto InvalidInstruction; - type = 0b10; - rModeOp = 0b01111; - } - else { - // Must be scalar. - if (sz > 2) - goto InvalidInstruction; - - if (o0.as().hasElementType()) - goto InvalidInstruction; - - if (o0.as().isVec32() && x) - goto InvalidInstruction; - - if (o0.as().isVec64() && !x) - goto InvalidInstruction; - } - - opcode.addImm(x, 31); - opcode.addImm(type, 22); - opcode.addImm(rModeOp, 16); - goto EmitOp_Rd0_Rn5; - } - - if (checkSignature(o0, o1)) { - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - if (sz > 2) - goto InvalidInstruction; - - if (o0.as().hasElementType()) - goto InvalidInstruction; - - uint32_t type = (sz - 1) & 0x3; - opcode.reset(0b00011110001000000100000000000000); - opcode.addImm(type, 22); - goto EmitOp_Rd0_Rn5; - } - } - - if (isign4 == ENC_OPS2(Reg, Imm)) { - if (o0.as().isVec()) { - double fpValue; - if (o1.as().isDouble()) - fpValue = o1.as().valueAs(); - else if (o1.as().isInt32()) - fpValue = o1.as().valueAs(); - else - goto InvalidImmediate; - - if (!Utils::isFP64Imm8(fpValue)) - goto InvalidImmediate; - - uint32_t imm8 = Utils::encodeFP64ToImm8(fpValue); - if (!o0.as().hasElementType()) { - // FMOV (scalar, immediate). - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - uint32_t type = (sz - 1u) & 0x3u; - - if (sz > 2) - goto InvalidInstruction; - - opcode.reset(0b00011110001000000001000000000000); - opcode.addImm(type, 22); - opcode.addImm(imm8, 13); - goto EmitOp_Rd0; - } - else { - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - uint32_t sz = diff(o0.as().elementType(), VecElementType::kH); - - if (q > 1 || sz > 2) - goto InvalidInstruction; - - static const uint32_t szBits[3] = { B(11), B(0), B(29) }; - opcode.reset(0b00001111000000001111010000000000); - opcode ^= szBits[sz]; - opcode.addImm(q, 30); - opcode.addImm(imm8 >> 5, 16); - opcode.addImm(imm8 & 31, 5); - goto EmitOp_Rd0; - } - } - } - - break; - } - - case InstDB::kEncodingFSimdPair: { - const InstDB::EncodingData::FSimdPair& opData = InstDB::EncodingData::fSimdPair[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - // This operation is only defined for: - // hD, vS.2h (16-bit) - // sD, vS.2s (32-bit) - // dD, vS.2d (64-bit) - uint32_t sz = diff(o0.as().regType(), RegType::kVec16); - if (sz > 2) - goto InvalidInstruction; - - static const uint32_t szSignatures[3] = { - RegTraits::kSignature | (Vec::kSignatureElementH), - RegTraits::kSignature | (Vec::kSignatureElementS), - RegTraits::kSignature | (Vec::kSignatureElementD) - }; - - if (o1.signature() != szSignatures[sz]) - goto InvalidInstruction; - - static const uint32_t szBits[] = { B(29), 0, B(22) }; - opcode.reset(opData.scalarOp()); - opcode ^= szBits[sz]; - goto EmitOp_Rd0_Rn5; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!checkSignature(o0, o1, o2)) - goto InvalidInstruction; - - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - uint32_t sz = diff(o0.as().elementType(), VecElementType::kH); - if (sz > 2) - goto InvalidInstruction; - - static const uint32_t szBits[3] = { B(22) | B(21) | B(15) | B(14), 0, B(22) }; - opcode.reset(opData.vectorOp()); - opcode ^= szBits[sz]; - opcode.addImm(q, 30); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - // ------------------------------------------------------------------------ - // [ISimd - Instructions] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingISimdSV: { - const InstDB::EncodingData::ISimdSV& opData = InstDB::EncodingData::iSimdSV[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - // The first destination operand is scalar, which matches element-type of source vectors. - uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0; - if (diff(o0.as().regType(), RegType::kVec8) != diff(o1.as().elementType(), VecElementType::kB) + L) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as().regType(), o1.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - opcode.addImm(sizeOp.q(), 30); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingISimdVV: { - const InstDB::EncodingData::ISimdVV& opData = InstDB::EncodingData::iSimdVV[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - const Operand_& sop = significantSimdOp(o0, o1, instFlags); - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as().regType(), sop.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingISimdVVx: { - const InstDB::EncodingData::ISimdVVx& opData = InstDB::EncodingData::iSimdVVx[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (o0.signature() != opData.op0Signature || - o1.signature() != opData.op1Signature) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingISimdVVV: { - const InstDB::EncodingData::ISimdVVV& opData = InstDB::EncodingData::iSimdVVV[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - const Operand_& sop = significantSimdOp(o0, o1, instFlags); - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as().regType(), sop.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingISimdVVVx: { - const InstDB::EncodingData::ISimdVVVx& opData = InstDB::EncodingData::iSimdVVVx[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (o0.signature() != opData.op0Signature || - o1.signature() != opData.op1Signature || - o2.signature() != opData.op2Signature) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingISimdWWV: { - // Special case for wide add/sub [s|b][add|sub][w]{2}. - const InstDB::EncodingData::ISimdWWV& opData = InstDB::EncodingData::iSimdWWV[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o2.as().regType(), o2.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (!checkSignature(o0, o1) || !o0.as().isVec128() || uint32_t(o0.as().elementType()) != uint32_t(o2.as().elementType()) + 1u) - goto InvalidInstruction; - - opcode.reset(opData.opcode()); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingISimdVVVe: { - const InstDB::EncodingData::ISimdVVVe& opData = InstDB::EncodingData::iSimdVVVe[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - const Operand_& sop = significantSimdOp(o0, o1, instFlags); - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - if (!o2.as().hasElementIndex()) { - SizeOp sizeOp = armElementTypeToSizeOp(opData.regularVecType, sop.as().regType(), sop.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (!checkSignature(o1, o2)) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.regularOp) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16; - } - else { - SizeOp sizeOp = armElementTypeToSizeOp(opData.elementVecType, sop.as().regType(), sop.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - uint32_t elementIndex = o2.as().elementIndex(); - LMHImm lmh; - - if (!encodeLMH(sizeOp.size(), elementIndex, &lmh)) - goto InvalidElementIndex; - - if (o2.as().id() > lmh.maxRmId) - goto InvalidPhysId; - - opcode.reset(uint32_t(opData.elementOp) << 10); - opcode.addImm(sizeOp.q(), 30); - opcode.addImm(sizeOp.size(), 22); - opcode.addImm(lmh.lm, 20); - opcode.addImm(lmh.h, 11); - goto EmitOp_Rd0_Rn5_Rm16; - } - } - - break; - } - - case InstDB::kEncodingISimdVVVI: { - const InstDB::EncodingData::ISimdVVVI& opData = InstDB::EncodingData::iSimdVVVI[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { - const Operand_& sop = significantSimdOp(o0, o1, instFlags); - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as().regType(), sop.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - uint64_t immValue = o3.as().valueAs(); - uint32_t immSize = opData.immSize; - - if (opData.imm64HasOneBitLess && !sizeOp.q()) - immSize--; - - uint32_t immMax = 1u << immSize; - if (immValue >= immMax) - goto InvalidImmediate; - - opcode.reset(opData.opcode()); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - opcode.addImm(immValue, opData.immShift); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingISimdVVVV: { - const InstDB::EncodingData::ISimdVVVV& opData = InstDB::EncodingData::iSimdVVVV[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { - const Operand_& sop = significantSimdOp(o0, o1, instFlags); - if (!matchSignature(o0, o1, o2, o3, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as().regType(), sop.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16_Ra10; - } - - break; - } - - case InstDB::kEncodingISimdVVVVx: { - const InstDB::EncodingData::ISimdVVVVx& opData = InstDB::EncodingData::iSimdVVVVx[encodingIndex]; - - if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { - if (o0.signature() != opData.op0Signature || - o1.signature() != opData.op1Signature || - o2.signature() != opData.op2Signature || - o3.signature() != opData.op3Signature) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.opcode) << 10); - goto EmitOp_Rd0_Rn5_Rm16_Ra10; - } - - break; - } - - - case InstDB::kEncodingISimdPair: { - const InstDB::EncodingData::ISimdPair& opData = InstDB::EncodingData::iSimdPair[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg) && opData.opcode2) { - if (o0.as().isVecD1() && o1.as().isVecD2()) { - opcode.reset(uint32_t(opData.opcode2) << 10); - opcode.addImm(0x3, 22); // size. - goto EmitOp_Rd0_Rn5; - } - } - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.opType3, o0.as().regType(), o0.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.opcode3) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingSimdBicOrr: { - const InstDB::EncodingData::SimdBicOrr& opData = InstDB::EncodingData::simdBicOrr[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_B, o0.as().regType(), o0.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.registerOp) << 10); - opcode.addImm(sizeOp.q(), 30); - goto EmitOp_Rd0_Rn5_Rm16; - } - - if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) { - SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_HS, o0.as().regType(), o0.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (o1.as().valueAs() > 0xFFFFFFFFu) - goto InvalidImmediate; - - uint32_t imm = o1.as().valueAs(); - uint32_t shift = 0; - uint32_t maxShift = (8u << sizeOp.size()) - 8u; - - if (o2.isImm()) { - if (o2.as().predicate() != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - if (imm > 0xFFu || o2.as().valueAs() > maxShift) - goto InvalidImmediate; - - shift = o2.as().valueAs(); - if ((shift & 0x7u) != 0u) - goto InvalidImmediate; - } - else if (imm) { - shift = Support::ctz(imm) & ~0x7u; - imm >>= shift; - - if (imm > 0xFFu || shift > maxShift) - goto InvalidImmediate; - } - - uint32_t cmode = 0x1u | ((shift / 8u) << 1); - if (sizeOp.size() == 1) - cmode |= B(3); - - // The immediate value is split into ABC and DEFGH parts. - uint32_t abc = (imm >> 5) & 0x7u; - uint32_t defgh = imm & 0x1Fu; - - opcode.reset(uint32_t(opData.immediateOp) << 10); - opcode.addImm(sizeOp.q(), 30); - opcode.addImm(abc, 16); - opcode.addImm(cmode, 12); - opcode.addImm(defgh, 5); - goto EmitOp_Rd0; - } - - break; - } - - case InstDB::kEncodingSimdCmp: { - const InstDB::EncodingData::SimdCmp& opData = InstDB::EncodingData::simdCmp[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.regOp) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as().regType(), o0.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.regOp) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.zeroOp) { - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - if (o2.as().value() != 0) - goto InvalidImmediate; - - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as().regType(), o0.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.zeroOp) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdDot: { - const InstDB::EncodingData::SimdDot& opData = InstDB::EncodingData::simdDot[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - uint32_t size = 2; - - if (q > 1u) - goto InvalidInstruction; - - if (!o2.as().hasElementIndex()) { - if (!opData.vectorOp) - goto InvalidInstruction; - - if (o0.as().regType() != o1.as().regType() || o1.as().regType() != o2.as().regType()) - goto InvalidInstruction; - - if (uint32_t(o0.as().elementType()) != opData.tA || - uint32_t(o1.as().elementType()) != opData.tB || - uint32_t(o2.as().elementType()) != opData.tB) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.vectorOp) << 10); - opcode.addImm(q, 30); - goto EmitOp_Rd0_Rn5_Rm16; - } - else { - if (!opData.elementOp) - goto InvalidInstruction; - - if (o0.as().regType() != o1.as().regType() || !o2.as().isVec128()) - goto InvalidInstruction; - - if (uint32_t(o0.as().elementType()) != opData.tA || - uint32_t(o1.as().elementType()) != opData.tB || - uint32_t(o2.as().elementType()) != opData.tElement) - goto InvalidInstruction; - - uint32_t elementIndex = o2.as().elementIndex(); - LMHImm lmh; - - if (!encodeLMH(size, elementIndex, &lmh)) - goto InvalidElementIndex; - - if (o2.as().id() > lmh.maxRmId) - goto InvalidPhysId; - - opcode.reset(uint32_t(opData.elementOp) << 10); - opcode.addImm(q, 30); - opcode.addImm(lmh.lm, 20); - opcode.addImm(lmh.h, 11); - goto EmitOp_Rd0_Rn5_Rm16; - } - } - - break; - } - - case InstDB::kEncodingSimdDup: SimdDup: { - if (isign4 == ENC_OPS2(Reg, Reg)) { - // Truth table of valid encodings of `Q:1|ElementType:3` - uint32_t kValidEncodings = B(uint32_t(VecElementType::kB) + 0) | - B(uint32_t(VecElementType::kH) + 0) | - B(uint32_t(VecElementType::kS) + 0) | - B(uint32_t(VecElementType::kB) + 8) | - B(uint32_t(VecElementType::kH) + 8) | - B(uint32_t(VecElementType::kS) + 8) | - B(uint32_t(VecElementType::kD) + 8) ; - - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - - if (o1.as().isGp()) { - // DUP - Vec (scalar|vector) <- GP register. - // - // NOTE: This is only scalar for `dup d, x` case, otherwise the value - // would be duplicated across all vector elements (1, 2, 4, 8, or 16). - uint32_t elementType = uint32_t(o0.as().elementType()); - if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) - goto InvalidInstruction; - - uint32_t lsbIndex = elementType - 1u; - uint32_t imm5 = 1u << lsbIndex; - - opcode.reset(0b0000111000000000000011 << 10); - opcode.addImm(q, 30); - opcode.addImm(imm5, 16); - goto EmitOp_Rd0_Rn5; - } - - if (!o1.as().isVec() || !o1.as().hasElementIndex()) - goto InvalidInstruction; - - uint32_t dstIndex = o1.as().elementIndex(); - if (!o0.as().hasElementType()) { - // DUP - Vec (scalar) <- Vec[N]. - uint32_t lsbIndex = diff(o0.as().regType(), RegType::kVec8); - - if (lsbIndex != diff(o1.as().elementType(), VecElementType::kB) || lsbIndex > 3) - goto InvalidInstruction; - - uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; - if (imm5 > 31) - goto InvalidElementIndex; - - opcode.reset(0b0101111000000000000001 << 10); - opcode.addImm(imm5, 16); - goto EmitOp_Rd0_Rn5; - } - else { - // DUP - Vec (all) <- Vec[N]. - uint32_t elementType = uint32_t(o0.as().elementType()); - if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) - goto InvalidInstruction; - - uint32_t lsbIndex = elementType - 1u; - uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; - - if (imm5 > 31) - goto InvalidElementIndex; - - opcode.reset(0b0000111000000000000001 << 10); - opcode.addImm(q, 30); - opcode.addImm(imm5, 16); - goto EmitOp_Rd0_Rn5; - } - } - - break; - } - - case InstDB::kEncodingSimdIns: SimdIns: { - if (isign4 == ENC_OPS2(Reg, Reg) && o0.as().isVec128()) { - if (!o0.as().hasElementIndex()) - goto InvalidInstruction; - - uint32_t elementType = uint32_t(o0.as().elementType()); - uint32_t dstIndex = o0.as().elementIndex(); - uint32_t lsbIndex = elementType - 1u; - - uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; - if (imm5 > 31) - goto InvalidElementIndex; - - if (o1.as().isGp()) { - // INS - Vec[N] <- GP register. - opcode.reset(0b0100111000000000000111 << 10); - opcode.addImm(imm5, 16); - goto EmitOp_Rd0_Rn5; - } - else if (o1.as().isVec128() && o1.as().hasElementIndex()) { - // INS - Vec[N] <- Vec[M]. - if (o0.as().elementType() != o1.as().elementType()) - goto InvalidInstruction; - - uint32_t srcIndex = o1.as().elementIndex(); - if (o0.as().regType() != o1.as().regType()) - goto InvalidInstruction; - - uint32_t imm4 = srcIndex << lsbIndex; - if (imm4 > 15) - goto InvalidElementIndex; - - opcode.reset(0b0110111000000000000001 << 10); - opcode.addImm(imm5, 16); - opcode.addImm(imm4, 11); - goto EmitOp_Rd0_Rn5; - } - } - - break; - } - - case InstDB::kEncodingSimdMov: { - if (isign4 == ENC_OPS2(Reg, Reg)) { - if (o0.as().isVec() && o1.as().isVec()) { - // INS v.x[index], v.x[index]. - if (o0.as().hasElementIndex() && o1.as().hasElementIndex()) - goto SimdIns; - - // DUP {b|h|s|d}, v.{b|h|s|d}[index]. - if (o1.as().hasElementIndex()) - goto SimdDup; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - // ORR Vd, Vn, Vm - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - opcode.reset(0b0000111010100000000111 << 10); - opcode.addImm(q, 30); - opcode.addReg(o1, 16); // Vn == Vm. - goto EmitOp_Rd0_Rn5; - } - - if (o0.as().isVec() && o1.as().isGp()) { - // INS v.x[index], Rn. - if (o0.as().hasElementIndex()) - goto SimdIns; - - goto InvalidInstruction; - } - - if (o0.as().isGp() && o1.as().isVec()) { - // UMOV Rd, V.{s|d}[index]. - encodingIndex = 1; - goto SimdUmov; - } - } - - break; - } - - case InstDB::kEncodingSimdMoviMvni: { - const InstDB::EncodingData::SimdMoviMvni& opData = InstDB::EncodingData::simdMoviMvni[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) { - SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_Any, o0.as().regType(), o0.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - uint64_t imm64 = o1.as().valueAs(); - uint32_t imm8 = 0; - uint32_t cmode = 0; - uint32_t inverted = opData.inverted; - uint32_t op = 0; - uint32_t shift = 0; - uint32_t shiftOp = uint32_t(ShiftOp::kLSL); - - if (sizeOp.size() == 3u) { - // The second immediate should not be present, however, we accept - // an immediate value of zero as some user code may still pass it. - if (o2.isImm() && o0.as().value() != 0) - goto InvalidImmediate; - - if (Utils::isByteMaskImm8(imm64)) { - imm8 = Utils::encodeImm64ByteMaskToImm8(imm64); - } - else { - // Change from D to S and from 64-bit imm to 32-bit imm if this - // is not a byte-mask pattern. - if ((imm64 >> 32) == (imm64 & 0xFFFFFFFFu)) { - imm64 &= 0xFFFFFFFFu; - sizeOp.decrementSize(); - } - else { - goto InvalidImmediate; - } - } - } - - if (sizeOp.size() < 3u) { - if (imm64 > 0xFFFFFFFFu) - goto InvalidImmediate; - imm8 = uint32_t(imm64); - - if (sizeOp.size() == 2) { - if ((imm8 >> 16) == (imm8 & 0xFFFFu)) { - imm8 >>= 16; - sizeOp.decrementSize(); - } - } - - if (sizeOp.size() == 1) { - if (imm8 > 0xFFFFu) - goto InvalidImmediate; - - if ((imm8 >> 8) == (imm8 & 0xFFu)) { - imm8 >>= 8; - sizeOp.decrementSize(); - } - } - - uint32_t maxShift = (8u << sizeOp.size()) - 8u; - if (o2.isImm()) { - if (imm8 > 0xFFu || o2.as().valueAs() > maxShift) - goto InvalidImmediate; - - shift = o2.as().valueAs(); - shiftOp = o2.as().predicate(); - } - else if (imm8) { - shift = Support::ctz(imm8) & ~0x7u; - imm8 >>= shift; - - if (imm8 > 0xFFu || shift > maxShift) - goto InvalidImmediate; - } - - if ((shift & 0x7u) != 0u) - goto InvalidImmediate; - } - - shift /= 8u; - - switch (sizeOp.size()) { - case 0: - if (shiftOp != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - if (inverted) { - imm8 = ~imm8 & 0xFFu; - } - - cmode = B(3) | B(2) | B(1); - break; - - case 1: - if (shiftOp != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - cmode = B(3) | (shift << 1); - op = inverted; - break; - - case 2: - if (shiftOp == uint32_t(ShiftOp::kLSL)) { - cmode = shift << 1; - } - else if (shiftOp == uint32_t(ShiftOp::kMSL)) { - if (shift == 0 || shift > 2) - goto InvalidImmediate; - cmode = B(3) | B(2) | (shift - 1u); - } - else { - goto InvalidImmediate; - } - - op = inverted; - break; - - case 3: - if (inverted) { - imm8 = ~imm8 & 0xFFu; - } - - op = 1; - cmode = B(3) | B(2) | B(1); - break; - } - - // The immediate value is split into ABC and DEFGH parts. - uint32_t abc = (imm8 >> 5) & 0x7u; - uint32_t defgh = imm8 & 0x1Fu; - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(sizeOp.q(), 30); - opcode.addImm(op, 29); - opcode.addImm(abc, 16); - opcode.addImm(cmode, 12); - opcode.addImm(defgh, 5); - goto EmitOp_Rd0; - } - - break; - } - - case InstDB::kEncodingSimdShift: { - const InstDB::EncodingData::SimdShift& opData = InstDB::EncodingData::simdShift[encodingIndex]; - - const Operand_& sop = significantSimdOp(o0, o1, instFlags); - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as().regType(), sop.as().elementType()); - - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp) { - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - if (o2.as().valueAs() > 63) - goto InvalidImmediate; - - uint32_t lsbShift = sizeOp.size() + 3u; - uint32_t lsbMask = (1u << lsbShift) - 1u; - uint32_t imm = o2.as().valueAs(); - - // Some instructions use IMM and some X - IMM, so negate if required. - if (opData.invertedImm) { - if (imm == 0 || imm > (1u << lsbShift)) - goto InvalidImmediate; - imm = Support::neg(imm) & lsbMask; - } - - if (imm > lsbMask) - goto InvalidImmediate; - imm |= (1u << lsbShift); - - opcode.reset(uint32_t(opData.immediateOp) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(imm, 16); - goto EmitOp_Rd0_Rn5; - } - - if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.registerOp) { - if (!matchSignature(o0, o1, o2, instFlags)) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.registerOp) << 10); - opcode.addImm(sizeOp.qs(), 30); - opcode.addImm(sizeOp.scalar(), 28); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5_Rm16; - } - - break; - } - - case InstDB::kEncodingSimdShiftES: { - const InstDB::EncodingData::SimdShiftES& opData = InstDB::EncodingData::simdShiftES[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as().regType(), o1.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - // The immediate value must match the element size. - uint64_t shift = o2.as().valueAs(); - uint32_t shiftOp = o2.as().predicate(); - - if (shift != (8u << sizeOp.size()) || shiftOp != uint32_t(ShiftOp::kLSL)) - goto InvalidImmediate; - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(sizeOp.q(), 30); - opcode.addImm(sizeOp.size(), 22); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdSm3tt: { - const InstDB::EncodingData::SimdSm3tt& opData = InstDB::EncodingData::simdSm3tt[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { - if (o0.as().isVecS4() && o1.as().isVecS4() && o2.as().isVecS4() && o2.as().hasElementIndex()) { - uint32_t imm2 = o2.as().elementIndex(); - if (imm2 > 3) - goto InvalidElementIndex; - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(imm2, 12); - goto EmitOp_Rd0_Rn5_Rm16; - } - } - - break; - } - - - case InstDB::kEncodingSimdSmovUmov: SimdUmov: { - const InstDB::EncodingData::SimdSmovUmov& opData = InstDB::EncodingData::simdSmovUmov[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg) && o0.as().isGp() && o1.as().isVec()) { - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as().regType(), o1.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (!o1.as().hasElementIndex()) - goto InvalidInstruction; - - uint32_t x = o0.as().isGp64(); - uint32_t gpMustBeX = uint32_t(sizeOp.size() >= 3u - opData.isSigned); - - if (opData.isSigned) { - if (gpMustBeX && !x) - goto InvalidInstruction; - } - else { - if (x != gpMustBeX) - goto InvalidInstruction; - } - - uint32_t elementIndex = o1.as().elementIndex(); - uint32_t maxElementIndex = 15u >> sizeOp.size(); - - if (elementIndex > maxElementIndex) - goto InvalidElementIndex; - - uint32_t imm5 = (1u | (elementIndex << 1)) << sizeOp.size(); - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(x, 30); - opcode.addImm(imm5, 16); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdSxtlUxtl: { - const InstDB::EncodingData::SimdSxtlUxtl& opData = InstDB::EncodingData::simdSxtlUxtl[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Reg)) { - SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as().regType(), o1.as().elementType()); - if (!sizeOp.isValid()) - goto InvalidInstruction; - - if (!matchSignature(o0, o1, instFlags)) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(sizeOp.q(), 30); - opcode.addImm(1u, sizeOp.size() + 19); - goto EmitOp_Rd0_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdTblTbx: { - const InstDB::EncodingData::SimdTblTbx& opData = InstDB::EncodingData::simdTblTbx[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { - // TBL/TBX ., { .16B }, . - // TBL/TBX ., { .16B, .16B }, . - // TBL/TBX ., { .16B, .16B, .16B }, . - // TBL/TBX ., { .16B, .16B, .16B, .16B }, . - opcode.reset(uint32_t(opData.opcode) << 10); - - const Operand_& o4 = opExt[EmitterUtils::kOp4]; - const Operand_& o5 = opExt[EmitterUtils::kOp5]; - - uint32_t q = diff(o0.as().regType(), RegType::kVec64); - if (q > 1 || o0.as().hasElementIndex()) - goto InvalidInstruction; - - if (!o1.as().isVecB16() || o1.as().hasElementIndex()) - goto InvalidInstruction; - - uint32_t len = uint32_t(!o3.isNone()) + uint32_t(!o4.isNone()) + uint32_t(!o5.isNone()); - opcode.addImm(q, 30); - opcode.addImm(len, 13); - - switch (len) { - case 0: - if (!checkSignature(o0, o2)) - goto InvalidInstruction; - - if (o2.id() > 31) - goto InvalidPhysId; - - opcode.addReg(o2, 16); - goto EmitOp_Rd0_Rn5; - - case 1: - if (!checkSignature(o0, o3)) - goto InvalidInstruction; - - if (o3.id() > 31) - goto InvalidPhysId; - - opcode.addReg(o3, 16); - goto EmitOp_Rd0_Rn5; - - case 2: - if (!checkSignature(o0, o4)) - goto InvalidInstruction; - - if (o4.id() > 31) - goto InvalidPhysId; - - opcode.addReg(o4, 16); - goto EmitOp_Rd0_Rn5; - - case 3: - if (!checkSignature(o0, o5)) - goto InvalidInstruction; - - if (o5.id() > 31) - goto InvalidPhysId; - - opcode.addReg(o5, 16); - goto EmitOp_Rd0_Rn5; - - default: - // Should never happen. - goto InvalidInstruction; - } - } - - break; - } - - // ------------------------------------------------------------------------ - // [Simd - Load / Store] - // ------------------------------------------------------------------------ - - case InstDB::kEncodingSimdLdSt: { - const InstDB::EncodingData::SimdLdSt& opData = InstDB::EncodingData::simdLdSt[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - // Width | SZ | XY | XSZ - // -------+----------+-----------+----- - // 8-bit | size==00 | opc == 01 | 000 - // 16-bit | size==01 | opc == 01 | 001 - // 32-bit | size==10 | opc == 01 | 010 - // 64-bit | size==11 | opc == 01 | 011 - // 128-bit| size==00 | opc == 11 | 100 - uint32_t xsz = diff(o0.as().regType(), RegType::kVec8); - if (xsz > 4u || o0.as().hasElementIndex()) - goto InvalidRegType; - - if (!checkVecId(o0)) - goto InvalidPhysId; - - if (!armCheckMemBaseIndexRel(m)) - goto InvalidAddress; - - int64_t offset = m.offset(); - if (m.hasBaseReg()) { - // [Base {Offset | Index}] - if (m.hasIndex()) { - uint32_t opt = armShiftOpToLdStOptMap[size_t(m.shiftOp())]; - if (opt == 0xFFu) - goto InvalidAddress; - - uint32_t shift = m.shift(); - uint32_t s = (shift != 0); - - if (s && shift != xsz) - goto InvalidAddressScale; - - opcode.reset(uint32_t(opData.registerOp) << 21); - opcode.addImm(xsz & 3u, 30); - opcode.addImm(xsz >> 2, 23); - opcode.addImm(opt, 13); - opcode.addImm(s, 12); - opcode |= B(11); - opcode.addReg(o0, 0); - goto EmitOp_MemBaseIndex_Rn5_Rm16; - } - - // Makes it easier to work with the offset especially on 32-bit arch. - if (!Support::isInt32(offset)) - goto InvalidDisplacement; - int32_t offset32 = int32_t(offset); - - if (m.isPreOrPost()) { - if (!Support::isInt9(offset32)) - goto InvalidDisplacement; - - opcode.reset(uint32_t(opData.prePostOp) << 21); - opcode.addImm(xsz & 3u, 30); - opcode.addImm(xsz >> 2, 23); - opcode.addImm(offset32 & 0x1FF, 12); - opcode.addImm(m.isPreIndex(), 11); - opcode |= B(10); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - else { - uint32_t imm12 = uint32_t(offset32) >> xsz; - - // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset. - if (!Support::isUInt12(imm12) || (imm12 << xsz) != uint32_t(offset32)) { - instId = opData.uAltInstId; - instInfo = &InstDB::_instInfoTable[instId]; - encodingIndex = instInfo->_encodingDataIndex; - goto Case_SimdLdurStur; - } - - opcode.reset(uint32_t(opData.uOffsetOp) << 22); - opcode.addImm(xsz & 3u, 30); - opcode.addImm(xsz >> 2, 23); - opcode.addImm(imm12, 10); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - } - else { - if (!opData.literalOp) - goto InvalidAddress; - - if (xsz < 2u) - goto InvalidRegType; - - uint32_t opc = xsz - 2u; - opcode.reset(uint32_t(opData.literalOp) << 24); - opcode.addImm(opc, 30); - opcode.addReg(o0, 0); - offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); - goto EmitOp_Rel; - } - } - - break; - } - - case InstDB::kEncodingSimdLdpStp: { - const InstDB::EncodingData::SimdLdpStp& opData = InstDB::EncodingData::simdLdpStp[encodingIndex]; - - if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { - const Mem& m = o2.as(); - rmRel = &m; - - uint32_t opc = diff(o0.as().regType(), RegType::kVec32); - if (opc > 2u || o0.as().hasElementTypeOrIndex()) - goto InvalidInstruction; - - if (!checkSignature(o0, o1)) - goto InvalidInstruction; - - if (!checkVecId(o0, o1)) - goto InvalidPhysId; - - if (m.baseType() != RegType::kGp64 || m.hasIndex()) - goto InvalidAddress; - - if (m.isOffset64Bit()) - goto InvalidDisplacement; - - uint32_t offsetShift = 2u + opc; - int32_t offset32 = m.offsetLo32() >> offsetShift; - - // Make sure we didn't lose bits by applying the mandatory offset shift. - if (Support::shl(offset32, offsetShift) != m.offsetLo32()) - goto InvalidDisplacement; - - // Offset is encoded as a 7-bit immediate. - if (!Support::isInt7(offset32)) - goto InvalidDisplacement; - - if (m.isPreOrPost() && offset32 != 0) { - if (!opData.prePostOp) - goto InvalidAddress; - - opcode.reset(uint32_t(opData.prePostOp) << 22); - opcode.addImm(m.isPreIndex(), 24); - } - else { - opcode.reset(uint32_t(opData.offsetOp) << 22); - } - - opcode.addImm(opc, 30); - opcode.addImm(offset32 & 0x7F, 15); - opcode.addReg(o1, 10); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - - break; - } - - case InstDB::kEncodingSimdLdurStur: { -Case_SimdLdurStur: - const InstDB::EncodingData::SimdLdurStur& opData = InstDB::EncodingData::simdLdurStur[encodingIndex]; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - const Mem& m = o1.as(); - rmRel = &m; - - uint32_t sz = diff(o0.as().regType(), RegType::kVec8); - if (sz > 4 || o0.as().hasElementTypeOrIndex()) - goto InvalidInstruction; - - if (!checkVecId(o0)) - goto InvalidPhysId; - - if (!armCheckMemBaseIndexRel(m)) - goto InvalidAddress; - - if (m.hasBaseReg() && !m.hasIndex() && !m.isPreOrPost()) { - if (m.isOffset64Bit()) - goto InvalidDisplacement; - - int32_t offset32 = m.offsetLo32(); - if (!Support::isInt9(offset32)) - goto InvalidDisplacement; - - opcode.reset(uint32_t(opData.opcode) << 10); - opcode.addImm(sz & 3u, 30); - opcode.addImm(sz >> 2, 23); - opcode.addImm(offset32 & 0x1FF, 12); - opcode.addReg(o0, 0); - goto EmitOp_MemBase_Rn5; - } - - goto InvalidAddress; - } - - break; - } - - case InstDB::kEncodingSimdLdNStN: { - const InstDB::EncodingData::SimdLdNStN& opData = InstDB::EncodingData::simdLdNStN[encodingIndex]; - const Operand_& o4 = opExt[EmitterUtils::kOp4]; - - uint32_t n = 1; - - if (isign4 == ENC_OPS2(Reg, Mem)) { - if (opData.n != 1) - goto InvalidInstruction; - - rmRel = &o1; - } - else if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { - if (opData.n != 1 && opData.n != 2) - goto InvalidInstruction; - - if (!checkSignature(o0, o1) || !checkConsecutive(o0, o1)) - goto InvalidInstruction; - - n = 2; - rmRel = &o2; - } - else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem) && o4.isNone()) { - if (opData.n != 1 && opData.n != 3) - goto InvalidInstruction; - - if (!checkSignature(o0, o1, o2) || !checkConsecutive(o0, o1, o2)) - goto InvalidInstruction; - - n = 3; - rmRel = &o3; - } - else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) { - if (opData.n != 1 && opData.n != 4) - goto InvalidInstruction; - - if (!checkSignature(o0, o1, o2, o3) || !checkConsecutive(o0, o1, o2, o3)) - goto InvalidInstruction; - - n = 4; - rmRel = &o4; - } - else { - goto InvalidInstruction; - } - - // We will use `v` and `m` from now as those are relevant for encoding. - const Vec& v = o0.as(); - const Mem& m = rmRel->as(); - - uint32_t q = 0; - uint32_t rm = 0; - uint32_t rn = m.baseId(); - uint32_t sz = diff(v.elementType(), VecElementType::kB); - uint32_t opcSsize = sz; - uint32_t offsetPossibility = 0; - - if (sz > 3) - goto InvalidInstruction; - - if (m.baseType() != RegType::kGp64) - goto InvalidAddress; - - // Rn cannot be ZR, but can be SP. - if (rn > 30 && rn != Gp::kIdSp) - goto InvalidAddress; - - rn &= 31; - - if (opData.replicate) { - if (n != opData.n) - goto InvalidInstruction; - - // Replicates to the whole register, element index cannot be used. - if (v.hasElementIndex()) - goto InvalidInstruction; - - q = diff(v.regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - opcode.reset(uint32_t(opData.singleOp) << 10); - offsetPossibility = (1u << sz) * n; - } - else if (v.hasElementIndex()) { - if (n != opData.n) - goto InvalidInstruction; - - // LDx/STx (single structure). - static const uint8_t opcSsizeBySzS[] = { 0x0u << 3, 0x2u << 3, 0x4u << 3, (0x4u << 3) | 1u }; - - opcode.reset(uint32_t(opData.singleOp) << 10); - opcSsize = opcSsizeBySzS[sz]; - offsetPossibility = (1u << sz) * opData.n; - - uint32_t elementIndex = v.elementIndex(); - uint32_t maxElementIndex = 15 >> sz; - - if (elementIndex > maxElementIndex) - goto InvalidElementIndex; - - elementIndex <<= sz; - q = elementIndex >> 3; - opcSsize |= elementIndex & 0x7u; - } - else { - // LDx/STx (multiple structures). - static const uint8_t opcSsizeByN[] = { 0u, 0x7u << 2, 0xAu << 2, 0x6u << 2, 0x2u << 2 }; - - q = diff(v.regType(), RegType::kVec64); - if (q > 1) - goto InvalidInstruction; - - if (opData.n == 1) - opcSsize |= opcSsizeByN[n]; - - opcode.reset(uint32_t(opData.multipleOp) << 10); - offsetPossibility = (8u << q) * n; - } - - if (m.hasIndex()) { - if (m.hasOffset() || !m.isPostIndex()) - goto InvalidAddress; - - rm = m.indexId(); - if (rm > 30) - goto InvalidAddress; - - // Bit 23 - PostIndex. - opcode |= B(23); - } - else { - if (m.hasOffset()) { - if (m.offset() != int32_t(offsetPossibility) || !m.isPostIndex()) - goto InvalidAddress; - rm = 31; - - // Bit 23 - PostIndex. - opcode |= B(23); - } - } - - opcode.addImm(q, 30); - opcode.addImm(rm, 16); - opcode.addImm(opcSsize, 10); - opcode.addImm(rn, 5); - goto EmitOp_Rd0; - } - - default: - break; - } - - goto InvalidInstruction; - - // -------------------------------------------------------------------------- - // [EmitGp - Single] - // -------------------------------------------------------------------------- - -EmitOp_Rd0: - if (!checkValidRegs(o0)) - goto InvalidPhysId; - - opcode.addReg(o0, 0); - goto EmitOp; - -EmitOp_Rn5: - if (!checkValidRegs(o0)) - goto InvalidPhysId; - - opcode.addReg(o0, 5); - goto EmitOp; - -EmitOp_Rn5_Rm16: - if (!checkValidRegs(o0, o1)) - goto InvalidPhysId; - - opcode.addReg(o0, 5); - opcode.addReg(o1, 16); - goto EmitOp; - -EmitOp_Rd0_Rn5: - if (!checkValidRegs(o0, o1)) - goto InvalidPhysId; - - opcode.addReg(o0, 0); - opcode.addReg(o1, 5); - goto EmitOp; - -EmitOp_Rd0_Rn5_Rm16_Ra10: - if (!checkValidRegs(o0, o1, o2, o3)) - goto InvalidPhysId; - - opcode.addReg(o0, 0); - opcode.addReg(o1, 5); - opcode.addReg(o2, 16); - opcode.addReg(o3, 10); - goto EmitOp; - -EmitOp_Rd0_Rn5_Rm16: - if (!checkValidRegs(o0, o1, o3)) - goto InvalidPhysId; - - opcode.addReg(o0, 0); - opcode.addReg(o1, 5); - opcode.addReg(o2, 16); - goto EmitOp; - - // -------------------------------------------------------------------------- - // [EmitGp - Multiple] - // -------------------------------------------------------------------------- - -EmitOp_Multiple: - { - ASMJIT_ASSERT(multipleOpCount > 0); - err = writer.ensureSpace(this, multipleOpCount * 4u); - if (ASMJIT_UNLIKELY(err)) { - goto Failed; - } - - for (uint32_t i = 0; i < multipleOpCount; i++) { - writer.emit32uLE(multipleOpData[i]); - } - - goto EmitDone; - } - - // -------------------------------------------------------------------------- - // [EmitGp - Memory] - // -------------------------------------------------------------------------- - -EmitOp_MemBase_Rn5: - if (!checkMemBase(rmRel->as())) { - goto InvalidAddress; - } - - opcode.addReg(rmRel->as().baseId(), 5); - goto EmitOp; - -EmitOp_MemBaseNoImm_Rn5: - if (!checkMemBase(rmRel->as()) || rmRel->as().hasIndex()) { - goto InvalidAddress; - } - - if (rmRel->as().hasOffset()) { - goto InvalidDisplacement; - } - - opcode.addReg(rmRel->as().baseId(), 5); - goto EmitOp; - -EmitOp_MemBaseIndex_Rn5_Rm16: - if (!rmRel->as().hasBaseReg()) { - goto InvalidAddress; - } - - if (rmRel->as().indexId() > 30 && rmRel->as().indexId() != Gp::kIdZr) { - goto InvalidPhysId; - } - - opcode.addReg(rmRel->as().indexId(), 16); - opcode.addReg(rmRel->as().baseId(), 5); - goto EmitOp; - - // -------------------------------------------------------------------------- - // [EmitOp - PC Relative] - // -------------------------------------------------------------------------- - -EmitOp_Rel: - { - if (rmRel->isLabel() || rmRel->isMem()) { - uint32_t labelId; - int64_t labelOffset = 0; - - if (rmRel->isLabel()) { - labelId = rmRel->as