1 // AsmJit - Machine code generation for C++
2 //
3 //  * Official AsmJit Home Page: https://asmjit.com
4 //  * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 //    claim that you wrote the original software. If you use this software
18 //    in a product, an acknowledgment in the product documentation would be
19 //    appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 //    misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23 
24 #ifndef ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
25 #define ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
26 
27 // This file provides architecture-specific classes that are required in the
28 // core library. For example Imm operand allows to be created from arm::Shift
29 // in a const-expr way, so the arm::Shift must be provided. So this header
30 // file provides everything architecture-specific that is used by the Core API.
31 
32 #include "../core/globals.h"
33 
34 // ============================================================================
35 // [asmjit::arm]
36 // ============================================================================
37 
ASMJIT_BEGIN_SUB_NAMESPACE(arm)38 ASMJIT_BEGIN_SUB_NAMESPACE(arm)
39 
40 //! \addtogroup asmjit_arm
41 //! \{
42 
43 //! Represents ARM immediate shift operation type and value.
44 class Shift {
45 public:
46   //! Operation predicate (ARM) describes either SHIFT or EXTEND operation.
47   //!
48   //! \note The constants are AsmJit specific. The first 5 values describe real
49   //! constants on ARM32 and AArch64 hardware, however, the addition constants
50   //! that describe extend modes are specific to AsmJit and would be translated
51   //! to the AArch64 specific constants by the assembler.
52   enum Op : uint32_t {
53     //! Shift left logical operation (default).
54     //!
55     //! Available to all ARM architectures.
56     kOpLSL = 0x00u,
57 
58     //! Shift right logical operation.
59     //!
60     //! Available to all ARM architectures.
61     kOpLSR = 0x01u,
62 
63     //! Shift right arithmetic operation.
64     //!
65     //! Available to all ARM architectures.
66     kOpASR = 0x02u,
67 
68     //! Rotate right operation.
69     //!
70     //! \note Not available in AArch64 mode.
71     kOpROR = 0x03u,
72 
73     //! Rotate right with carry operation (encoded as `kShiftROR` with zero).
74     //!
75     //! \note Not available in AArch64 mode.
76     kOpRRX = 0x04u,
77 
78     //! Shift left by filling low order bits with ones.
79     kOpMSL = 0x05u,
80 
81     //! UXTN extend register operation (AArch64 only).
82     kOpUXTB = 0x06u,
83     //! UXTH extend register operation (AArch64 only).
84     kOpUXTH = 0x07u,
85     //! UXTW extend register operation (AArch64 only).
86     kOpUXTW = 0x08u,
87     //! UXTX extend register operation (AArch64 only).
88     kOpUXTX = 0x09u,
89 
90     //! SXTB extend register operation (AArch64 only).
91     kOpSXTB = 0x0Au,
92     //! SXTH extend register operation (AArch64 only).
93     kOpSXTH = 0x0Bu,
94     //! SXTW extend register operation (AArch64 only).
95     kOpSXTW = 0x0Cu,
96     //! SXTX extend register operation (AArch64 only).
97     kOpSXTX = 0x0Du
98 
99     // NOTE: 0xE and 0xF are used by memory operand to specify POST|PRE offset mode.
100   };
101 
102   //! Shift operation.
103   uint32_t _op;
104   //! Shift Value.
105   uint32_t _value;
106 
107   //! Default constructed Shift is not initialized.
108   inline Shift() noexcept = default;
109 
110   //! Copy constructor (default)
111   constexpr Shift(const Shift& other) noexcept = default;
112 
113   //! Constructs Shift from operation `op` and shift `value`.
114   constexpr Shift(uint32_t op, uint32_t value) noexcept
115     : _op(op),
116       _value(value) {}
117 
118   //! Returns the shift operation.
119   constexpr uint32_t op() const noexcept { return _op; }
120   //! Returns the shift smount.
121   constexpr uint32_t value() const noexcept { return _value; }
122 
123   //! Sets shift operation to `op`.
124   inline void setOp(uint32_t op) noexcept { _op = op; }
125   //! Sets shift amount to `value`.
126   inline void setValue(uint32_t value) noexcept { _value = value; }
127 };
128 
129 //! Constructs a `LSL #value` shift (logical shift left).
lsl(uint32_t value)130 static constexpr Shift lsl(uint32_t value) noexcept { return Shift(Shift::kOpLSL, value); }
131 //! Constructs a `LSR #value` shift (logical shift right).
lsr(uint32_t value)132 static constexpr Shift lsr(uint32_t value) noexcept { return Shift(Shift::kOpLSR, value); }
133 //! Constructs a `ASR #value` shift (arithmetic shift right).
asr(uint32_t value)134 static constexpr Shift asr(uint32_t value) noexcept { return Shift(Shift::kOpASR, value); }
135 //! Constructs a `ROR #value` shift (rotate right).
ror(uint32_t value)136 static constexpr Shift ror(uint32_t value) noexcept { return Shift(Shift::kOpROR, value); }
137 //! Constructs a `RRX` shift (rotate with carry by 1).
rrx()138 static constexpr Shift rrx() noexcept { return Shift(Shift::kOpRRX, 0); }
139 //! Constructs a `MSL #value` shift (logical shift left filling ones).
msl(uint32_t value)140 static constexpr Shift msl(uint32_t value) noexcept { return Shift(Shift::kOpMSL, value); }
141 
142 //! Constructs a `UXTB #value` extend and shift (unsigned byte extend).
uxtb(uint32_t value)143 static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(Shift::kOpUXTB, value); }
144 //! Constructs a `UXTH #value` extend and shift (unsigned hword extend).
uxth(uint32_t value)145 static constexpr Shift uxth(uint32_t value) noexcept { return Shift(Shift::kOpUXTH, value); }
146 //! Constructs a `UXTW #value` extend and shift (unsigned word extend).
uxtw(uint32_t value)147 static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(Shift::kOpUXTW, value); }
148 //! Constructs a `UXTX #value` extend and shift (unsigned dword extend).
uxtx(uint32_t value)149 static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(Shift::kOpUXTX, value); }
150 
151 //! Constructs a `SXTB #value` extend and shift (signed byte extend).
sxtb(uint32_t value)152 static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(Shift::kOpSXTB, value); }
153 //! Constructs a `SXTH #value` extend and shift (signed hword extend).
sxth(uint32_t value)154 static constexpr Shift sxth(uint32_t value) noexcept { return Shift(Shift::kOpSXTH, value); }
155 //! Constructs a `SXTW #value` extend and shift (signed word extend).
sxtw(uint32_t value)156 static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(Shift::kOpSXTW, value); }
157 //! Constructs a `SXTX #value` extend and shift (signed dword extend).
sxtx(uint32_t value)158 static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(Shift::kOpSXTX, value); }
159 
160 //! \}
161 
162 ASMJIT_END_SUB_NAMESPACE
163 
164 #endif // ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED
165