1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
4*03ce13f7SAndroid Build Coastguard Worker // for details. All rights reserved. Use of this source code is governed by a
5*03ce13f7SAndroid Build Coastguard Worker // BSD-style license that can be found in the LICENSE file.
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // Modified by the Subzero authors.
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
10*03ce13f7SAndroid Build Coastguard Worker //
11*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator
12*03ce13f7SAndroid Build Coastguard Worker //
13*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
14*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
15*03ce13f7SAndroid Build Coastguard Worker //
16*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*03ce13f7SAndroid Build Coastguard Worker ///
18*03ce13f7SAndroid Build Coastguard Worker /// \file
19*03ce13f7SAndroid Build Coastguard Worker /// \brief Implements the Assembler class for ARM32.
20*03ce13f7SAndroid Build Coastguard Worker ///
21*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
22*03ce13f7SAndroid Build Coastguard Worker
23*03ce13f7SAndroid Build Coastguard Worker #include "IceAssemblerARM32.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceUtils.h"
26*03ce13f7SAndroid Build Coastguard Worker
27*03ce13f7SAndroid Build Coastguard Worker namespace {
28*03ce13f7SAndroid Build Coastguard Worker
29*03ce13f7SAndroid Build Coastguard Worker using namespace Ice;
30*03ce13f7SAndroid Build Coastguard Worker using namespace Ice::ARM32;
31*03ce13f7SAndroid Build Coastguard Worker
32*03ce13f7SAndroid Build Coastguard Worker using WordType = uint32_t;
33*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kWordSize = sizeof(WordType);
34*03ce13f7SAndroid Build Coastguard Worker
35*03ce13f7SAndroid Build Coastguard Worker // The following define individual bits.
36*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B0 = 1;
37*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B1 = 1 << 1;
38*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B2 = 1 << 2;
39*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B3 = 1 << 3;
40*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B4 = 1 << 4;
41*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B5 = 1 << 5;
42*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B6 = 1 << 6;
43*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B7 = 1 << 7;
44*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B8 = 1 << 8;
45*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B9 = 1 << 9;
46*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B10 = 1 << 10;
47*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B11 = 1 << 11;
48*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B12 = 1 << 12;
49*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B13 = 1 << 13;
50*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B14 = 1 << 14;
51*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B15 = 1 << 15;
52*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B16 = 1 << 16;
53*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B17 = 1 << 17;
54*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B18 = 1 << 18;
55*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B19 = 1 << 19;
56*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B20 = 1 << 20;
57*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B21 = 1 << 21;
58*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B22 = 1 << 22;
59*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B23 = 1 << 23;
60*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B24 = 1 << 24;
61*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B25 = 1 << 25;
62*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B26 = 1 << 26;
63*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B27 = 1 << 27;
64*03ce13f7SAndroid Build Coastguard Worker
65*03ce13f7SAndroid Build Coastguard Worker // Constants used for the decoding or encoding of the individual fields of
66*03ce13f7SAndroid Build Coastguard Worker // instructions. Based on ARM section A5.1.
67*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT L = 1 << 20; // load (or store)
68*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT W = 1 << 21; // writeback base register
69*03ce13f7SAndroid Build Coastguard Worker // (or leave unchanged)
70*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT B = 1 << 22; // unsigned byte (or word)
71*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT U = 1 << 23; // positive (or negative)
72*03ce13f7SAndroid Build Coastguard Worker // offset/index
73*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT P = 1 << 24; // offset/pre-indexed
74*03ce13f7SAndroid Build Coastguard Worker // addressing (or
75*03ce13f7SAndroid Build Coastguard Worker // post-indexed addressing)
76*03ce13f7SAndroid Build Coastguard Worker
77*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kConditionShift = 28;
78*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kLinkShift = 24;
79*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kOpcodeShift = 21;
80*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRdShift = 12;
81*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRmShift = 0;
82*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRnShift = 16;
83*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRsShift = 8;
84*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kSShift = 20;
85*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kTypeShift = 25;
86*03ce13f7SAndroid Build Coastguard Worker
87*03ce13f7SAndroid Build Coastguard Worker // Immediate instruction fields encoding.
88*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kImmed8Bits = 8;
89*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kImmed8Shift = 0;
90*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRotateBits = 4;
91*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRotateShift = 8;
92*03ce13f7SAndroid Build Coastguard Worker
93*03ce13f7SAndroid Build Coastguard Worker // Shift instruction register fields encodings.
94*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kShiftImmShift = 7;
95*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kShiftImmBits = 5;
96*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kShiftShift = 5;
97*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kImmed12Bits = 12;
98*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kImm12Shift = 0;
99*03ce13f7SAndroid Build Coastguard Worker
100*03ce13f7SAndroid Build Coastguard Worker // Rotation instructions (uxtb etc.).
101*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kRotationShift = 10;
102*03ce13f7SAndroid Build Coastguard Worker
103*03ce13f7SAndroid Build Coastguard Worker // MemEx instructions.
104*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kMemExOpcodeShift = 20;
105*03ce13f7SAndroid Build Coastguard Worker
106*03ce13f7SAndroid Build Coastguard Worker // Div instruction register field encodings.
107*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kDivRdShift = 16;
108*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kDivRmShift = 8;
109*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kDivRnShift = 0;
110*03ce13f7SAndroid Build Coastguard Worker
111*03ce13f7SAndroid Build Coastguard Worker // Type of instruction encoding (bits 25-27). See ARM section A5.1
112*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000
113*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000
114*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001
115*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010
116*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT kInstTypeRegisterShift = 3; // i.e. 011
117*03ce13f7SAndroid Build Coastguard Worker
118*03ce13f7SAndroid Build Coastguard Worker // Limit on number of registers in a vpush/vpop.
119*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT VpushVpopMaxConsecRegs = 16;
120*03ce13f7SAndroid Build Coastguard Worker
121*03ce13f7SAndroid Build Coastguard Worker // Offset modifier to current PC for next instruction. The offset is off by 8
122*03ce13f7SAndroid Build Coastguard Worker // due to the way the ARM CPUs read PC.
123*03ce13f7SAndroid Build Coastguard Worker static constexpr IOffsetT kPCReadOffset = 8;
124*03ce13f7SAndroid Build Coastguard Worker
125*03ce13f7SAndroid Build Coastguard Worker // Mask to pull out PC offset from branch (b) instruction.
126*03ce13f7SAndroid Build Coastguard Worker static constexpr int kBranchOffsetBits = 24;
127*03ce13f7SAndroid Build Coastguard Worker static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff;
128*03ce13f7SAndroid Build Coastguard Worker
encodeBool(bool B)129*03ce13f7SAndroid Build Coastguard Worker IValueT encodeBool(bool B) { return B ? 1 : 0; }
130*03ce13f7SAndroid Build Coastguard Worker
encodeRotation(ARM32::AssemblerARM32::RotationValue Value)131*03ce13f7SAndroid Build Coastguard Worker IValueT encodeRotation(ARM32::AssemblerARM32::RotationValue Value) {
132*03ce13f7SAndroid Build Coastguard Worker return static_cast<IValueT>(Value);
133*03ce13f7SAndroid Build Coastguard Worker }
134*03ce13f7SAndroid Build Coastguard Worker
encodeGPRRegister(RegARM32::GPRRegister Rn)135*03ce13f7SAndroid Build Coastguard Worker IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) {
136*03ce13f7SAndroid Build Coastguard Worker return static_cast<IValueT>(Rn);
137*03ce13f7SAndroid Build Coastguard Worker }
138*03ce13f7SAndroid Build Coastguard Worker
decodeGPRRegister(IValueT R)139*03ce13f7SAndroid Build Coastguard Worker RegARM32::GPRRegister decodeGPRRegister(IValueT R) {
140*03ce13f7SAndroid Build Coastguard Worker return static_cast<RegARM32::GPRRegister>(R);
141*03ce13f7SAndroid Build Coastguard Worker }
142*03ce13f7SAndroid Build Coastguard Worker
encodeCondition(CondARM32::Cond Cond)143*03ce13f7SAndroid Build Coastguard Worker IValueT encodeCondition(CondARM32::Cond Cond) {
144*03ce13f7SAndroid Build Coastguard Worker return static_cast<IValueT>(Cond);
145*03ce13f7SAndroid Build Coastguard Worker }
146*03ce13f7SAndroid Build Coastguard Worker
encodeShift(OperandARM32::ShiftKind Shift)147*03ce13f7SAndroid Build Coastguard Worker IValueT encodeShift(OperandARM32::ShiftKind Shift) {
148*03ce13f7SAndroid Build Coastguard Worker // Follows encoding in ARM section A8.4.1 "Constant shifts".
149*03ce13f7SAndroid Build Coastguard Worker switch (Shift) {
150*03ce13f7SAndroid Build Coastguard Worker case OperandARM32::kNoShift:
151*03ce13f7SAndroid Build Coastguard Worker case OperandARM32::LSL:
152*03ce13f7SAndroid Build Coastguard Worker return 0; // 0b00
153*03ce13f7SAndroid Build Coastguard Worker case OperandARM32::LSR:
154*03ce13f7SAndroid Build Coastguard Worker return 1; // 0b01
155*03ce13f7SAndroid Build Coastguard Worker case OperandARM32::ASR:
156*03ce13f7SAndroid Build Coastguard Worker return 2; // 0b10
157*03ce13f7SAndroid Build Coastguard Worker case OperandARM32::ROR:
158*03ce13f7SAndroid Build Coastguard Worker case OperandARM32::RRX:
159*03ce13f7SAndroid Build Coastguard Worker return 3; // 0b11
160*03ce13f7SAndroid Build Coastguard Worker }
161*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Unknown Shift value");
162*03ce13f7SAndroid Build Coastguard Worker return 0;
163*03ce13f7SAndroid Build Coastguard Worker }
164*03ce13f7SAndroid Build Coastguard Worker
165*03ce13f7SAndroid Build Coastguard Worker // Returns the bits in the corresponding masked value.
mask(IValueT Value,IValueT Shift,IValueT Bits)166*03ce13f7SAndroid Build Coastguard Worker IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) {
167*03ce13f7SAndroid Build Coastguard Worker return (Value >> Shift) & ((1 << Bits) - 1);
168*03ce13f7SAndroid Build Coastguard Worker }
169*03ce13f7SAndroid Build Coastguard Worker
170*03ce13f7SAndroid Build Coastguard Worker // Extract out a Bit in Value.
isBitSet(IValueT Bit,IValueT Value)171*03ce13f7SAndroid Build Coastguard Worker bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; }
172*03ce13f7SAndroid Build Coastguard Worker
173*03ce13f7SAndroid Build Coastguard Worker // Returns the GPR register at given Shift in Value.
getGPRReg(IValueT Shift,IValueT Value)174*03ce13f7SAndroid Build Coastguard Worker RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
175*03ce13f7SAndroid Build Coastguard Worker return decodeGPRRegister((Value >> Shift) & 0xF);
176*03ce13f7SAndroid Build Coastguard Worker }
177*03ce13f7SAndroid Build Coastguard Worker
getEncodedGPRegNum(const Variable * Var)178*03ce13f7SAndroid Build Coastguard Worker IValueT getEncodedGPRegNum(const Variable *Var) {
179*03ce13f7SAndroid Build Coastguard Worker assert(Var->hasReg());
180*03ce13f7SAndroid Build Coastguard Worker const auto Reg = Var->getRegNum();
181*03ce13f7SAndroid Build Coastguard Worker return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
182*03ce13f7SAndroid Build Coastguard Worker : RegARM32::getEncodedGPR(Reg);
183*03ce13f7SAndroid Build Coastguard Worker }
184*03ce13f7SAndroid Build Coastguard Worker
getEncodedSRegNum(const Variable * Var)185*03ce13f7SAndroid Build Coastguard Worker IValueT getEncodedSRegNum(const Variable *Var) {
186*03ce13f7SAndroid Build Coastguard Worker assert(Var->hasReg());
187*03ce13f7SAndroid Build Coastguard Worker return RegARM32::getEncodedSReg(Var->getRegNum());
188*03ce13f7SAndroid Build Coastguard Worker }
189*03ce13f7SAndroid Build Coastguard Worker
getEncodedDRegNum(const Variable * Var)190*03ce13f7SAndroid Build Coastguard Worker IValueT getEncodedDRegNum(const Variable *Var) {
191*03ce13f7SAndroid Build Coastguard Worker return RegARM32::getEncodedDReg(Var->getRegNum());
192*03ce13f7SAndroid Build Coastguard Worker }
193*03ce13f7SAndroid Build Coastguard Worker
getEncodedQRegNum(const Variable * Var)194*03ce13f7SAndroid Build Coastguard Worker IValueT getEncodedQRegNum(const Variable *Var) {
195*03ce13f7SAndroid Build Coastguard Worker return RegARM32::getEncodedQReg(Var->getRegNum());
196*03ce13f7SAndroid Build Coastguard Worker }
197*03ce13f7SAndroid Build Coastguard Worker
mapQRegToDReg(IValueT EncodedQReg)198*03ce13f7SAndroid Build Coastguard Worker IValueT mapQRegToDReg(IValueT EncodedQReg) {
199*03ce13f7SAndroid Build Coastguard Worker IValueT DReg = EncodedQReg << 1;
200*03ce13f7SAndroid Build Coastguard Worker assert(DReg < RegARM32::getNumDRegs());
201*03ce13f7SAndroid Build Coastguard Worker return DReg;
202*03ce13f7SAndroid Build Coastguard Worker }
203*03ce13f7SAndroid Build Coastguard Worker
mapQRegToSReg(IValueT EncodedQReg)204*03ce13f7SAndroid Build Coastguard Worker IValueT mapQRegToSReg(IValueT EncodedQReg) {
205*03ce13f7SAndroid Build Coastguard Worker IValueT SReg = EncodedQReg << 2;
206*03ce13f7SAndroid Build Coastguard Worker assert(SReg < RegARM32::getNumSRegs());
207*03ce13f7SAndroid Build Coastguard Worker return SReg;
208*03ce13f7SAndroid Build Coastguard Worker }
209*03ce13f7SAndroid Build Coastguard Worker
getYInRegXXXXY(IValueT RegXXXXY)210*03ce13f7SAndroid Build Coastguard Worker IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; }
211*03ce13f7SAndroid Build Coastguard Worker
getXXXXInRegXXXXY(IValueT RegXXXXY)212*03ce13f7SAndroid Build Coastguard Worker IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; }
213*03ce13f7SAndroid Build Coastguard Worker
getYInRegYXXXX(IValueT RegYXXXX)214*03ce13f7SAndroid Build Coastguard Worker IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; }
215*03ce13f7SAndroid Build Coastguard Worker
getXXXXInRegYXXXX(IValueT RegYXXXX)216*03ce13f7SAndroid Build Coastguard Worker IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; }
217*03ce13f7SAndroid Build Coastguard Worker
218*03ce13f7SAndroid Build Coastguard Worker // Figures out Op/Cmode values for given Value. Returns true if able to encode.
encodeAdvSIMDExpandImm(IValueT Value,Type ElmtTy,IValueT & Op,IValueT & Cmode,IValueT & Imm8)219*03ce13f7SAndroid Build Coastguard Worker bool encodeAdvSIMDExpandImm(IValueT Value, Type ElmtTy, IValueT &Op,
220*03ce13f7SAndroid Build Coastguard Worker IValueT &Cmode, IValueT &Imm8) {
221*03ce13f7SAndroid Build Coastguard Worker // TODO(kschimpf): Handle other shifted 8-bit values.
222*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Imm8Mask = 0xFF;
223*03ce13f7SAndroid Build Coastguard Worker if ((Value & IValueT(~Imm8Mask)) != 0)
224*03ce13f7SAndroid Build Coastguard Worker return false;
225*03ce13f7SAndroid Build Coastguard Worker Imm8 = Value;
226*03ce13f7SAndroid Build Coastguard Worker switch (ElmtTy) {
227*03ce13f7SAndroid Build Coastguard Worker case IceType_i8:
228*03ce13f7SAndroid Build Coastguard Worker Op = 0;
229*03ce13f7SAndroid Build Coastguard Worker Cmode = 14; // 0b1110
230*03ce13f7SAndroid Build Coastguard Worker return true;
231*03ce13f7SAndroid Build Coastguard Worker case IceType_i16:
232*03ce13f7SAndroid Build Coastguard Worker Op = 0;
233*03ce13f7SAndroid Build Coastguard Worker Cmode = 8; // 0b1000
234*03ce13f7SAndroid Build Coastguard Worker return true;
235*03ce13f7SAndroid Build Coastguard Worker case IceType_i32:
236*03ce13f7SAndroid Build Coastguard Worker Op = 0;
237*03ce13f7SAndroid Build Coastguard Worker Cmode = 0; // 0b0000
238*03ce13f7SAndroid Build Coastguard Worker return true;
239*03ce13f7SAndroid Build Coastguard Worker default:
240*03ce13f7SAndroid Build Coastguard Worker return false;
241*03ce13f7SAndroid Build Coastguard Worker }
242*03ce13f7SAndroid Build Coastguard Worker }
243*03ce13f7SAndroid Build Coastguard Worker
244*03ce13f7SAndroid Build Coastguard Worker // Defines layouts of an operand representing a (register) memory address,
245*03ce13f7SAndroid Build Coastguard Worker // possibly modified by an immediate value.
246*03ce13f7SAndroid Build Coastguard Worker enum EncodedImmAddress {
247*03ce13f7SAndroid Build Coastguard Worker // Address modified by a rotated immediate 8-bit value.
248*03ce13f7SAndroid Build Coastguard Worker RotatedImm8Address,
249*03ce13f7SAndroid Build Coastguard Worker
250*03ce13f7SAndroid Build Coastguard Worker // Alternate encoding for RotatedImm8Address, where the offset is divided by 4
251*03ce13f7SAndroid Build Coastguard Worker // before encoding.
252*03ce13f7SAndroid Build Coastguard Worker RotatedImm8Div4Address,
253*03ce13f7SAndroid Build Coastguard Worker
254*03ce13f7SAndroid Build Coastguard Worker // Address modified by an immediate 12-bit value.
255*03ce13f7SAndroid Build Coastguard Worker Imm12Address,
256*03ce13f7SAndroid Build Coastguard Worker
257*03ce13f7SAndroid Build Coastguard Worker // Alternate encoding 3, for an address modified by a rotated immediate 8-bit
258*03ce13f7SAndroid Build Coastguard Worker // value.
259*03ce13f7SAndroid Build Coastguard Worker RotatedImm8Enc3Address,
260*03ce13f7SAndroid Build Coastguard Worker
261*03ce13f7SAndroid Build Coastguard Worker // Encoding where no immediate offset is used.
262*03ce13f7SAndroid Build Coastguard Worker NoImmOffsetAddress
263*03ce13f7SAndroid Build Coastguard Worker };
264*03ce13f7SAndroid Build Coastguard Worker
265*03ce13f7SAndroid Build Coastguard Worker // The way an operand is encoded into a sequence of bits in functions
266*03ce13f7SAndroid Build Coastguard Worker // encodeOperand and encodeAddress below.
267*03ce13f7SAndroid Build Coastguard Worker enum EncodedOperand {
268*03ce13f7SAndroid Build Coastguard Worker // Unable to encode, value left undefined.
269*03ce13f7SAndroid Build Coastguard Worker CantEncode = 0,
270*03ce13f7SAndroid Build Coastguard Worker
271*03ce13f7SAndroid Build Coastguard Worker // Value is register found.
272*03ce13f7SAndroid Build Coastguard Worker EncodedAsRegister,
273*03ce13f7SAndroid Build Coastguard Worker
274*03ce13f7SAndroid Build Coastguard Worker // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8
275*03ce13f7SAndroid Build Coastguard Worker // value.
276*03ce13f7SAndroid Build Coastguard Worker EncodedAsRotatedImm8,
277*03ce13f7SAndroid Build Coastguard Worker
278*03ce13f7SAndroid Build Coastguard Worker // EncodedAsImmRegOffset is a memory operand that can take three forms, based
279*03ce13f7SAndroid Build Coastguard Worker // on type EncodedImmAddress:
280*03ce13f7SAndroid Build Coastguard Worker //
281*03ce13f7SAndroid Build Coastguard Worker // ***** RotatedImm8Address *****
282*03ce13f7SAndroid Build Coastguard Worker //
283*03ce13f7SAndroid Build Coastguard Worker // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
284*03ce13f7SAndroid Build Coastguard Worker // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
285*03ce13f7SAndroid Build Coastguard Worker // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value.
286*03ce13f7SAndroid Build Coastguard Worker //
287*03ce13f7SAndroid Build Coastguard Worker // ***** RotatedImm8Div4Address *****
288*03ce13f7SAndroid Build Coastguard Worker //
289*03ce13f7SAndroid Build Coastguard Worker // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1
290*03ce13f7SAndroid Build Coastguard Worker // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to
291*03ce13f7SAndroid Build Coastguard Worker // Rn.
292*03ce13f7SAndroid Build Coastguard Worker //
293*03ce13f7SAndroid Build Coastguard Worker // ***** Imm12Address *****
294*03ce13f7SAndroid Build Coastguard Worker //
295*03ce13f7SAndroid Build Coastguard Worker // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
296*03ce13f7SAndroid Build Coastguard Worker // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
297*03ce13f7SAndroid Build Coastguard Worker // Rn should be used, and iiiiiiiiiiii defines the immediate 12-bit value.
298*03ce13f7SAndroid Build Coastguard Worker //
299*03ce13f7SAndroid Build Coastguard Worker // ***** NoImmOffsetAddress *****
300*03ce13f7SAndroid Build Coastguard Worker //
301*03ce13f7SAndroid Build Coastguard Worker // Value=000000001000nnnn0000000000000000 where nnnn=Rn.
302*03ce13f7SAndroid Build Coastguard Worker EncodedAsImmRegOffset,
303*03ce13f7SAndroid Build Coastguard Worker
304*03ce13f7SAndroid Build Coastguard Worker // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn,
305*03ce13f7SAndroid Build Coastguard Worker // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift
306*03ce13f7SAndroid Build Coastguard Worker // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if
307*03ce13f7SAndroid Build Coastguard Worker // writeback to Rn.
308*03ce13f7SAndroid Build Coastguard Worker EncodedAsShiftRotateImm5,
309*03ce13f7SAndroid Build Coastguard Worker
310*03ce13f7SAndroid Build Coastguard Worker // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value
311*03ce13f7SAndroid Build Coastguard Worker // to shift.
312*03ce13f7SAndroid Build Coastguard Worker EncodedAsShiftImm5,
313*03ce13f7SAndroid Build Coastguard Worker
314*03ce13f7SAndroid Build Coastguard Worker // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift
315*03ce13f7SAndroid Build Coastguard Worker // kind, and iiiii is the shift amount.
316*03ce13f7SAndroid Build Coastguard Worker EncodedAsShiftedRegister,
317*03ce13f7SAndroid Build Coastguard Worker
318*03ce13f7SAndroid Build Coastguard Worker // Value=ssss0tt1mmmm where mmmm=Rm, tt is an encoded ShiftKind, and ssss=Rms.
319*03ce13f7SAndroid Build Coastguard Worker EncodedAsRegShiftReg,
320*03ce13f7SAndroid Build Coastguard Worker
321*03ce13f7SAndroid Build Coastguard Worker // Value is 32bit integer constant.
322*03ce13f7SAndroid Build Coastguard Worker EncodedAsConstI32
323*03ce13f7SAndroid Build Coastguard Worker };
324*03ce13f7SAndroid Build Coastguard Worker
325*03ce13f7SAndroid Build Coastguard Worker // Sets Encoding to a rotated Imm8 encoding of Value, if possible.
encodeRotatedImm8(IValueT RotateAmt,IValueT Immed8)326*03ce13f7SAndroid Build Coastguard Worker IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) {
327*03ce13f7SAndroid Build Coastguard Worker assert(RotateAmt < (1 << kRotateBits));
328*03ce13f7SAndroid Build Coastguard Worker assert(Immed8 < (1 << kImmed8Bits));
329*03ce13f7SAndroid Build Coastguard Worker return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift);
330*03ce13f7SAndroid Build Coastguard Worker }
331*03ce13f7SAndroid Build Coastguard Worker
332*03ce13f7SAndroid Build Coastguard Worker // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5,
333*03ce13f7SAndroid Build Coastguard Worker // tt=Shift, and mmmm=Rm.
encodeShiftRotateImm5(IValueT Rm,OperandARM32::ShiftKind Shift,IOffsetT imm5)334*03ce13f7SAndroid Build Coastguard Worker IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift,
335*03ce13f7SAndroid Build Coastguard Worker IOffsetT imm5) {
336*03ce13f7SAndroid Build Coastguard Worker (void)kShiftImmBits;
337*03ce13f7SAndroid Build Coastguard Worker assert(imm5 < (1 << kShiftImmBits));
338*03ce13f7SAndroid Build Coastguard Worker return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm;
339*03ce13f7SAndroid Build Coastguard Worker }
340*03ce13f7SAndroid Build Coastguard Worker
341*03ce13f7SAndroid Build Coastguard Worker // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and
342*03ce13f7SAndroid Build Coastguard Worker // tt=Shift.
encodeShiftRotateReg(IValueT Rm,OperandARM32::ShiftKind Shift,IValueT Rs)343*03ce13f7SAndroid Build Coastguard Worker IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift,
344*03ce13f7SAndroid Build Coastguard Worker IValueT Rs) {
345*03ce13f7SAndroid Build Coastguard Worker return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 |
346*03ce13f7SAndroid Build Coastguard Worker (Rm << kRmShift);
347*03ce13f7SAndroid Build Coastguard Worker }
348*03ce13f7SAndroid Build Coastguard Worker
349*03ce13f7SAndroid Build Coastguard Worker // Defines the set of registers expected in an operand.
350*03ce13f7SAndroid Build Coastguard Worker enum RegSetWanted { WantGPRegs, WantSRegs, WantDRegs, WantQRegs };
351*03ce13f7SAndroid Build Coastguard Worker
encodeOperand(const Operand * Opnd,IValueT & Value,RegSetWanted WantedRegSet)352*03ce13f7SAndroid Build Coastguard Worker EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value,
353*03ce13f7SAndroid Build Coastguard Worker RegSetWanted WantedRegSet) {
354*03ce13f7SAndroid Build Coastguard Worker Value = 0; // Make sure initialized.
355*03ce13f7SAndroid Build Coastguard Worker if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
356*03ce13f7SAndroid Build Coastguard Worker if (Var->hasReg()) {
357*03ce13f7SAndroid Build Coastguard Worker switch (WantedRegSet) {
358*03ce13f7SAndroid Build Coastguard Worker case WantGPRegs:
359*03ce13f7SAndroid Build Coastguard Worker Value = getEncodedGPRegNum(Var);
360*03ce13f7SAndroid Build Coastguard Worker break;
361*03ce13f7SAndroid Build Coastguard Worker case WantSRegs:
362*03ce13f7SAndroid Build Coastguard Worker Value = getEncodedSRegNum(Var);
363*03ce13f7SAndroid Build Coastguard Worker break;
364*03ce13f7SAndroid Build Coastguard Worker case WantDRegs:
365*03ce13f7SAndroid Build Coastguard Worker Value = getEncodedDRegNum(Var);
366*03ce13f7SAndroid Build Coastguard Worker break;
367*03ce13f7SAndroid Build Coastguard Worker case WantQRegs:
368*03ce13f7SAndroid Build Coastguard Worker Value = getEncodedQRegNum(Var);
369*03ce13f7SAndroid Build Coastguard Worker break;
370*03ce13f7SAndroid Build Coastguard Worker }
371*03ce13f7SAndroid Build Coastguard Worker return EncodedAsRegister;
372*03ce13f7SAndroid Build Coastguard Worker }
373*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
374*03ce13f7SAndroid Build Coastguard Worker }
375*03ce13f7SAndroid Build Coastguard Worker if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
376*03ce13f7SAndroid Build Coastguard Worker const IValueT Immed8 = FlexImm->getImm();
377*03ce13f7SAndroid Build Coastguard Worker const IValueT Rotate = FlexImm->getRotateAmt();
378*03ce13f7SAndroid Build Coastguard Worker if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))))
379*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
380*03ce13f7SAndroid Build Coastguard Worker Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
381*03ce13f7SAndroid Build Coastguard Worker return EncodedAsRotatedImm8;
382*03ce13f7SAndroid Build Coastguard Worker }
383*03ce13f7SAndroid Build Coastguard Worker if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) {
384*03ce13f7SAndroid Build Coastguard Worker Value = Const->getValue();
385*03ce13f7SAndroid Build Coastguard Worker return EncodedAsConstI32;
386*03ce13f7SAndroid Build Coastguard Worker }
387*03ce13f7SAndroid Build Coastguard Worker if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) {
388*03ce13f7SAndroid Build Coastguard Worker Operand *Amt = FlexReg->getShiftAmt();
389*03ce13f7SAndroid Build Coastguard Worker IValueT Rm;
390*03ce13f7SAndroid Build Coastguard Worker if (encodeOperand(FlexReg->getReg(), Rm, WantGPRegs) != EncodedAsRegister)
391*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
392*03ce13f7SAndroid Build Coastguard Worker if (const auto *Var = llvm::dyn_cast<Variable>(Amt)) {
393*03ce13f7SAndroid Build Coastguard Worker IValueT Rs;
394*03ce13f7SAndroid Build Coastguard Worker if (encodeOperand(Var, Rs, WantGPRegs) != EncodedAsRegister)
395*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
396*03ce13f7SAndroid Build Coastguard Worker Value = encodeShiftRotateReg(Rm, FlexReg->getShiftOp(), Rs);
397*03ce13f7SAndroid Build Coastguard Worker return EncodedAsRegShiftReg;
398*03ce13f7SAndroid Build Coastguard Worker }
399*03ce13f7SAndroid Build Coastguard Worker // If reached, the amount is a shifted amount by some 5-bit immediate.
400*03ce13f7SAndroid Build Coastguard Worker uint32_t Imm5;
401*03ce13f7SAndroid Build Coastguard Worker if (const auto *ShAmt = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) {
402*03ce13f7SAndroid Build Coastguard Worker Imm5 = ShAmt->getShAmtImm();
403*03ce13f7SAndroid Build Coastguard Worker } else if (const auto *IntConst = llvm::dyn_cast<ConstantInteger32>(Amt)) {
404*03ce13f7SAndroid Build Coastguard Worker int32_t Val = IntConst->getValue();
405*03ce13f7SAndroid Build Coastguard Worker if (Val < 0)
406*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
407*03ce13f7SAndroid Build Coastguard Worker Imm5 = static_cast<uint32_t>(Val);
408*03ce13f7SAndroid Build Coastguard Worker } else
409*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
410*03ce13f7SAndroid Build Coastguard Worker Value = encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5);
411*03ce13f7SAndroid Build Coastguard Worker return EncodedAsShiftedRegister;
412*03ce13f7SAndroid Build Coastguard Worker }
413*03ce13f7SAndroid Build Coastguard Worker if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) {
414*03ce13f7SAndroid Build Coastguard Worker const IValueT Immed5 = ShImm->getShAmtImm();
415*03ce13f7SAndroid Build Coastguard Worker assert(Immed5 < (1 << kShiftImmBits));
416*03ce13f7SAndroid Build Coastguard Worker Value = (Immed5 << kShiftImmShift);
417*03ce13f7SAndroid Build Coastguard Worker return EncodedAsShiftImm5;
418*03ce13f7SAndroid Build Coastguard Worker }
419*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
420*03ce13f7SAndroid Build Coastguard Worker }
421*03ce13f7SAndroid Build Coastguard Worker
encodeImmRegOffset(IValueT Reg,IOffsetT Offset,OperandARM32Mem::AddrMode Mode,IOffsetT MaxOffset,IValueT OffsetShift)422*03ce13f7SAndroid Build Coastguard Worker IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset,
423*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem::AddrMode Mode, IOffsetT MaxOffset,
424*03ce13f7SAndroid Build Coastguard Worker IValueT OffsetShift) {
425*03ce13f7SAndroid Build Coastguard Worker IValueT Value = Mode | (Reg << kRnShift);
426*03ce13f7SAndroid Build Coastguard Worker if (Offset < 0) {
427*03ce13f7SAndroid Build Coastguard Worker Offset = -Offset;
428*03ce13f7SAndroid Build Coastguard Worker Value ^= U; // Flip U to adjust sign.
429*03ce13f7SAndroid Build Coastguard Worker }
430*03ce13f7SAndroid Build Coastguard Worker assert(Offset <= MaxOffset);
431*03ce13f7SAndroid Build Coastguard Worker (void)MaxOffset;
432*03ce13f7SAndroid Build Coastguard Worker return Value | (Offset >> OffsetShift);
433*03ce13f7SAndroid Build Coastguard Worker }
434*03ce13f7SAndroid Build Coastguard Worker
435*03ce13f7SAndroid Build Coastguard Worker // Encodes immediate register offset using encoding 3.
encodeImmRegOffsetEnc3(IValueT Rn,IOffsetT Imm8,OperandARM32Mem::AddrMode Mode)436*03ce13f7SAndroid Build Coastguard Worker IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8,
437*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem::AddrMode Mode) {
438*03ce13f7SAndroid Build Coastguard Worker IValueT Value = Mode | (Rn << kRnShift);
439*03ce13f7SAndroid Build Coastguard Worker if (Imm8 < 0) {
440*03ce13f7SAndroid Build Coastguard Worker Imm8 = -Imm8;
441*03ce13f7SAndroid Build Coastguard Worker Value = (Value ^ U);
442*03ce13f7SAndroid Build Coastguard Worker }
443*03ce13f7SAndroid Build Coastguard Worker assert(Imm8 < (1 << 8));
444*03ce13f7SAndroid Build Coastguard Worker Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f);
445*03ce13f7SAndroid Build Coastguard Worker return Value;
446*03ce13f7SAndroid Build Coastguard Worker }
447*03ce13f7SAndroid Build Coastguard Worker
encodeImmRegOffset(EncodedImmAddress ImmEncoding,IValueT Reg,IOffsetT Offset,OperandARM32Mem::AddrMode Mode)448*03ce13f7SAndroid Build Coastguard Worker IValueT encodeImmRegOffset(EncodedImmAddress ImmEncoding, IValueT Reg,
449*03ce13f7SAndroid Build Coastguard Worker IOffsetT Offset, OperandARM32Mem::AddrMode Mode) {
450*03ce13f7SAndroid Build Coastguard Worker switch (ImmEncoding) {
451*03ce13f7SAndroid Build Coastguard Worker case RotatedImm8Address: {
452*03ce13f7SAndroid Build Coastguard Worker constexpr IOffsetT MaxOffset = (1 << 8) - 1;
453*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT NoRightShift = 0;
454*03ce13f7SAndroid Build Coastguard Worker return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift);
455*03ce13f7SAndroid Build Coastguard Worker }
456*03ce13f7SAndroid Build Coastguard Worker case RotatedImm8Div4Address: {
457*03ce13f7SAndroid Build Coastguard Worker assert((Offset & 0x3) == 0);
458*03ce13f7SAndroid Build Coastguard Worker constexpr IOffsetT MaxOffset = (1 << 8) - 1;
459*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT RightShift2 = 2;
460*03ce13f7SAndroid Build Coastguard Worker return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, RightShift2);
461*03ce13f7SAndroid Build Coastguard Worker }
462*03ce13f7SAndroid Build Coastguard Worker case Imm12Address: {
463*03ce13f7SAndroid Build Coastguard Worker constexpr IOffsetT MaxOffset = (1 << 12) - 1;
464*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT NoRightShift = 0;
465*03ce13f7SAndroid Build Coastguard Worker return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift);
466*03ce13f7SAndroid Build Coastguard Worker }
467*03ce13f7SAndroid Build Coastguard Worker case RotatedImm8Enc3Address:
468*03ce13f7SAndroid Build Coastguard Worker return encodeImmRegOffsetEnc3(Reg, Offset, Mode);
469*03ce13f7SAndroid Build Coastguard Worker case NoImmOffsetAddress: {
470*03ce13f7SAndroid Build Coastguard Worker assert(Offset == 0);
471*03ce13f7SAndroid Build Coastguard Worker assert(Mode == OperandARM32Mem::Offset);
472*03ce13f7SAndroid Build Coastguard Worker return Reg << kRnShift;
473*03ce13f7SAndroid Build Coastguard Worker }
474*03ce13f7SAndroid Build Coastguard Worker }
475*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("(silence g++ warning)");
476*03ce13f7SAndroid Build Coastguard Worker }
477*03ce13f7SAndroid Build Coastguard Worker
478*03ce13f7SAndroid Build Coastguard Worker // Encodes memory address Opnd, and encodes that information into Value, based
479*03ce13f7SAndroid Build Coastguard Worker // on how ARM represents the address. Returns how the value was encoded.
encodeAddress(const Operand * Opnd,IValueT & Value,const AssemblerARM32::TargetInfo & TInfo,EncodedImmAddress ImmEncoding)480*03ce13f7SAndroid Build Coastguard Worker EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value,
481*03ce13f7SAndroid Build Coastguard Worker const AssemblerARM32::TargetInfo &TInfo,
482*03ce13f7SAndroid Build Coastguard Worker EncodedImmAddress ImmEncoding) {
483*03ce13f7SAndroid Build Coastguard Worker Value = 0; // Make sure initialized.
484*03ce13f7SAndroid Build Coastguard Worker if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
485*03ce13f7SAndroid Build Coastguard Worker // Should be a stack variable, with an offset.
486*03ce13f7SAndroid Build Coastguard Worker if (Var->hasReg())
487*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
488*03ce13f7SAndroid Build Coastguard Worker IOffsetT Offset = Var->getStackOffset();
489*03ce13f7SAndroid Build Coastguard Worker if (!Utils::IsAbsoluteUint(12, Offset))
490*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
491*03ce13f7SAndroid Build Coastguard Worker const auto BaseRegNum =
492*03ce13f7SAndroid Build Coastguard Worker Var->hasReg() ? Var->getBaseRegNum() : TInfo.FrameOrStackReg;
493*03ce13f7SAndroid Build Coastguard Worker Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset,
494*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem::Offset);
495*03ce13f7SAndroid Build Coastguard Worker return EncodedAsImmRegOffset;
496*03ce13f7SAndroid Build Coastguard Worker }
497*03ce13f7SAndroid Build Coastguard Worker if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) {
498*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Mem->getBase();
499*03ce13f7SAndroid Build Coastguard Worker if (!Var->hasReg())
500*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
501*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = getEncodedGPRegNum(Var);
502*03ce13f7SAndroid Build Coastguard Worker if (Mem->isRegReg()) {
503*03ce13f7SAndroid Build Coastguard Worker const Variable *Index = Mem->getIndex();
504*03ce13f7SAndroid Build Coastguard Worker if (Var == nullptr)
505*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
506*03ce13f7SAndroid Build Coastguard Worker Value = (Rn << kRnShift) | Mem->getAddrMode() |
507*03ce13f7SAndroid Build Coastguard Worker encodeShiftRotateImm5(getEncodedGPRegNum(Index),
508*03ce13f7SAndroid Build Coastguard Worker Mem->getShiftOp(), Mem->getShiftAmt());
509*03ce13f7SAndroid Build Coastguard Worker return EncodedAsShiftRotateImm5;
510*03ce13f7SAndroid Build Coastguard Worker }
511*03ce13f7SAndroid Build Coastguard Worker // Encoded as immediate register offset.
512*03ce13f7SAndroid Build Coastguard Worker ConstantInteger32 *Offset = Mem->getOffset();
513*03ce13f7SAndroid Build Coastguard Worker Value = encodeImmRegOffset(ImmEncoding, Rn, Offset->getValue(),
514*03ce13f7SAndroid Build Coastguard Worker Mem->getAddrMode());
515*03ce13f7SAndroid Build Coastguard Worker return EncodedAsImmRegOffset;
516*03ce13f7SAndroid Build Coastguard Worker }
517*03ce13f7SAndroid Build Coastguard Worker return CantEncode;
518*03ce13f7SAndroid Build Coastguard Worker }
519*03ce13f7SAndroid Build Coastguard Worker
520*03ce13f7SAndroid Build Coastguard Worker // Checks that Offset can fit in imm24 constant of branch (b) instruction.
assertCanEncodeBranchOffset(IOffsetT Offset)521*03ce13f7SAndroid Build Coastguard Worker void assertCanEncodeBranchOffset(IOffsetT Offset) {
522*03ce13f7SAndroid Build Coastguard Worker (void)Offset;
523*03ce13f7SAndroid Build Coastguard Worker (void)kBranchOffsetBits;
524*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsAligned(Offset, 4) &&
525*03ce13f7SAndroid Build Coastguard Worker Utils::IsInt(kBranchOffsetBits, Offset >> 2));
526*03ce13f7SAndroid Build Coastguard Worker }
527*03ce13f7SAndroid Build Coastguard Worker
encodeBranchOffset(IOffsetT Offset,IValueT Inst)528*03ce13f7SAndroid Build Coastguard Worker IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
529*03ce13f7SAndroid Build Coastguard Worker // Adjust offset to the way ARM CPUs read PC.
530*03ce13f7SAndroid Build Coastguard Worker Offset -= kPCReadOffset;
531*03ce13f7SAndroid Build Coastguard Worker
532*03ce13f7SAndroid Build Coastguard Worker assertCanEncodeBranchOffset(Offset);
533*03ce13f7SAndroid Build Coastguard Worker
534*03ce13f7SAndroid Build Coastguard Worker // Properly preserve only the bits supported in the instruction.
535*03ce13f7SAndroid Build Coastguard Worker Offset >>= 2;
536*03ce13f7SAndroid Build Coastguard Worker Offset &= kBranchOffsetMask;
537*03ce13f7SAndroid Build Coastguard Worker return (Inst & ~kBranchOffsetMask) | Offset;
538*03ce13f7SAndroid Build Coastguard Worker }
539*03ce13f7SAndroid Build Coastguard Worker
encodeRegister(const Operand * OpReg,RegSetWanted WantedRegSet,const char * RegName,const char * InstName)540*03ce13f7SAndroid Build Coastguard Worker IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet,
541*03ce13f7SAndroid Build Coastguard Worker const char *RegName, const char *InstName) {
542*03ce13f7SAndroid Build Coastguard Worker IValueT Reg = 0;
543*03ce13f7SAndroid Build Coastguard Worker if (encodeOperand(OpReg, Reg, WantedRegSet) != EncodedAsRegister)
544*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
545*03ce13f7SAndroid Build Coastguard Worker RegName);
546*03ce13f7SAndroid Build Coastguard Worker return Reg;
547*03ce13f7SAndroid Build Coastguard Worker }
548*03ce13f7SAndroid Build Coastguard Worker
encodeGPRegister(const Operand * OpReg,const char * RegName,const char * InstName)549*03ce13f7SAndroid Build Coastguard Worker IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
550*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
551*03ce13f7SAndroid Build Coastguard Worker return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
552*03ce13f7SAndroid Build Coastguard Worker }
553*03ce13f7SAndroid Build Coastguard Worker
encodeSRegister(const Operand * OpReg,const char * RegName,const char * InstName)554*03ce13f7SAndroid Build Coastguard Worker IValueT encodeSRegister(const Operand *OpReg, const char *RegName,
555*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
556*03ce13f7SAndroid Build Coastguard Worker return encodeRegister(OpReg, WantSRegs, RegName, InstName);
557*03ce13f7SAndroid Build Coastguard Worker }
558*03ce13f7SAndroid Build Coastguard Worker
encodeDRegister(const Operand * OpReg,const char * RegName,const char * InstName)559*03ce13f7SAndroid Build Coastguard Worker IValueT encodeDRegister(const Operand *OpReg, const char *RegName,
560*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
561*03ce13f7SAndroid Build Coastguard Worker return encodeRegister(OpReg, WantDRegs, RegName, InstName);
562*03ce13f7SAndroid Build Coastguard Worker }
563*03ce13f7SAndroid Build Coastguard Worker
encodeQRegister(const Operand * OpReg,const char * RegName,const char * InstName)564*03ce13f7SAndroid Build Coastguard Worker IValueT encodeQRegister(const Operand *OpReg, const char *RegName,
565*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
566*03ce13f7SAndroid Build Coastguard Worker return encodeRegister(OpReg, WantQRegs, RegName, InstName);
567*03ce13f7SAndroid Build Coastguard Worker }
568*03ce13f7SAndroid Build Coastguard Worker
verifyPOrNotW(IValueT Address,const char * InstName)569*03ce13f7SAndroid Build Coastguard Worker void verifyPOrNotW(IValueT Address, const char *InstName) {
570*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::minimal())
571*03ce13f7SAndroid Build Coastguard Worker return;
572*03ce13f7SAndroid Build Coastguard Worker if (!isBitSet(P, Address) && isBitSet(W, Address))
573*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
574*03ce13f7SAndroid Build Coastguard Worker ": P=0 when W=1 not allowed");
575*03ce13f7SAndroid Build Coastguard Worker }
576*03ce13f7SAndroid Build Coastguard Worker
verifyRegsNotEq(IValueT Reg1,const char * Reg1Name,IValueT Reg2,const char * Reg2Name,const char * InstName)577*03ce13f7SAndroid Build Coastguard Worker void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2,
578*03ce13f7SAndroid Build Coastguard Worker const char *Reg2Name, const char *InstName) {
579*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::minimal())
580*03ce13f7SAndroid Build Coastguard Worker return;
581*03ce13f7SAndroid Build Coastguard Worker if (Reg1 == Reg2)
582*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": " + Reg1Name + "=" +
583*03ce13f7SAndroid Build Coastguard Worker Reg2Name + " not allowed");
584*03ce13f7SAndroid Build Coastguard Worker }
585*03ce13f7SAndroid Build Coastguard Worker
verifyRegNotPc(IValueT Reg,const char * RegName,const char * InstName)586*03ce13f7SAndroid Build Coastguard Worker void verifyRegNotPc(IValueT Reg, const char *RegName, const char *InstName) {
587*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(Reg, RegName, RegARM32::Encoded_Reg_pc, "pc", InstName);
588*03ce13f7SAndroid Build Coastguard Worker }
589*03ce13f7SAndroid Build Coastguard Worker
verifyAddrRegNotPc(IValueT RegShift,IValueT Address,const char * RegName,const char * InstName)590*03ce13f7SAndroid Build Coastguard Worker void verifyAddrRegNotPc(IValueT RegShift, IValueT Address, const char *RegName,
591*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
592*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::minimal())
593*03ce13f7SAndroid Build Coastguard Worker return;
594*03ce13f7SAndroid Build Coastguard Worker if (getGPRReg(RegShift, Address) == RegARM32::Encoded_Reg_pc)
595*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": " + RegName +
596*03ce13f7SAndroid Build Coastguard Worker "=pc not allowed");
597*03ce13f7SAndroid Build Coastguard Worker }
598*03ce13f7SAndroid Build Coastguard Worker
verifyRegNotPcWhenSetFlags(IValueT Reg,bool SetFlags,const char * InstName)599*03ce13f7SAndroid Build Coastguard Worker void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags,
600*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
601*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::minimal())
602*03ce13f7SAndroid Build Coastguard Worker return;
603*03ce13f7SAndroid Build Coastguard Worker if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc))
604*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": " +
605*03ce13f7SAndroid Build Coastguard Worker RegARM32::getRegName(RegARM32::Reg_pc) +
606*03ce13f7SAndroid Build Coastguard Worker "=pc not allowed when CC=1");
607*03ce13f7SAndroid Build Coastguard Worker }
608*03ce13f7SAndroid Build Coastguard Worker
609*03ce13f7SAndroid Build Coastguard Worker enum SIMDShiftType { ST_Vshl, ST_Vshr };
610*03ce13f7SAndroid Build Coastguard Worker
encodeSIMDShiftImm6(SIMDShiftType Shift,Type ElmtTy,const IValueT Imm)611*03ce13f7SAndroid Build Coastguard Worker IValueT encodeSIMDShiftImm6(SIMDShiftType Shift, Type ElmtTy,
612*03ce13f7SAndroid Build Coastguard Worker const IValueT Imm) {
613*03ce13f7SAndroid Build Coastguard Worker assert(Imm > 0);
614*03ce13f7SAndroid Build Coastguard Worker const SizeT MaxShift = getScalarIntBitWidth(ElmtTy);
615*03ce13f7SAndroid Build Coastguard Worker assert(Imm < 2 * MaxShift);
616*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy == IceType_i8 || ElmtTy == IceType_i16 ||
617*03ce13f7SAndroid Build Coastguard Worker ElmtTy == IceType_i32);
618*03ce13f7SAndroid Build Coastguard Worker const IValueT VshlImm = Imm - MaxShift;
619*03ce13f7SAndroid Build Coastguard Worker const IValueT VshrImm = 2 * MaxShift - Imm;
620*03ce13f7SAndroid Build Coastguard Worker return ((Shift == ST_Vshl) ? VshlImm : VshrImm) & (2 * MaxShift - 1);
621*03ce13f7SAndroid Build Coastguard Worker }
622*03ce13f7SAndroid Build Coastguard Worker
encodeSIMDShiftImm6(SIMDShiftType Shift,Type ElmtTy,const ConstantInteger32 * Imm6)623*03ce13f7SAndroid Build Coastguard Worker IValueT encodeSIMDShiftImm6(SIMDShiftType Shift, Type ElmtTy,
624*03ce13f7SAndroid Build Coastguard Worker const ConstantInteger32 *Imm6) {
625*03ce13f7SAndroid Build Coastguard Worker const IValueT Imm = Imm6->getValue();
626*03ce13f7SAndroid Build Coastguard Worker return encodeSIMDShiftImm6(Shift, ElmtTy, Imm);
627*03ce13f7SAndroid Build Coastguard Worker }
628*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
629*03ce13f7SAndroid Build Coastguard Worker
630*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
631*03ce13f7SAndroid Build Coastguard Worker namespace ARM32 {
632*03ce13f7SAndroid Build Coastguard Worker
emit(GlobalContext * Ctx,const Assembler & Asm) const633*03ce13f7SAndroid Build Coastguard Worker size_t MoveRelocatableFixup::emit(GlobalContext *Ctx,
634*03ce13f7SAndroid Build Coastguard Worker const Assembler &Asm) const {
635*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
636*03ce13f7SAndroid Build Coastguard Worker return InstARM32::InstSize;
637*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrEmit();
638*03ce13f7SAndroid Build Coastguard Worker IValueT Inst = Asm.load<IValueT>(position());
639*03ce13f7SAndroid Build Coastguard Worker const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ||
640*03ce13f7SAndroid Build Coastguard Worker kind() == llvm::ELF::R_ARM_MOVW_PREL_NC;
641*03ce13f7SAndroid Build Coastguard Worker const auto Symbol = symbol().toString();
642*03ce13f7SAndroid Build Coastguard Worker const bool NeedsPCRelSuffix =
643*03ce13f7SAndroid Build Coastguard Worker (Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable);
644*03ce13f7SAndroid Build Coastguard Worker Str << "\t"
645*03ce13f7SAndroid Build Coastguard Worker "mov"
646*03ce13f7SAndroid Build Coastguard Worker << (IsMovw ? "w" : "t") << "\t"
647*03ce13f7SAndroid Build Coastguard Worker << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF))
648*03ce13f7SAndroid Build Coastguard Worker << ", #:" << (IsMovw ? "lower" : "upper") << "16:" << Symbol
649*03ce13f7SAndroid Build Coastguard Worker << (NeedsPCRelSuffix ? " - ." : "")
650*03ce13f7SAndroid Build Coastguard Worker << "\t@ .word "
651*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp): This is broken, it also needs to add a magic constant.
652*03ce13f7SAndroid Build Coastguard Worker << llvm::format_hex_no_prefix(Inst, 8) << "\n";
653*03ce13f7SAndroid Build Coastguard Worker return InstARM32::InstSize;
654*03ce13f7SAndroid Build Coastguard Worker }
655*03ce13f7SAndroid Build Coastguard Worker
encodeElmtType(Type ElmtTy)656*03ce13f7SAndroid Build Coastguard Worker IValueT AssemblerARM32::encodeElmtType(Type ElmtTy) {
657*03ce13f7SAndroid Build Coastguard Worker switch (ElmtTy) {
658*03ce13f7SAndroid Build Coastguard Worker case IceType_i8:
659*03ce13f7SAndroid Build Coastguard Worker return 0;
660*03ce13f7SAndroid Build Coastguard Worker case IceType_i16:
661*03ce13f7SAndroid Build Coastguard Worker return 1;
662*03ce13f7SAndroid Build Coastguard Worker case IceType_i32:
663*03ce13f7SAndroid Build Coastguard Worker case IceType_f32:
664*03ce13f7SAndroid Build Coastguard Worker return 2;
665*03ce13f7SAndroid Build Coastguard Worker case IceType_i64:
666*03ce13f7SAndroid Build Coastguard Worker return 3;
667*03ce13f7SAndroid Build Coastguard Worker default:
668*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("SIMD op: Don't understand element type " +
669*03ce13f7SAndroid Build Coastguard Worker typeStdString(ElmtTy));
670*03ce13f7SAndroid Build Coastguard Worker }
671*03ce13f7SAndroid Build Coastguard Worker }
672*03ce13f7SAndroid Build Coastguard Worker
673*03ce13f7SAndroid Build Coastguard Worker // This fixup points to an ARM32 instruction with the following format:
emitOffset(Assembler * Asm) const674*03ce13f7SAndroid Build Coastguard Worker void MoveRelocatableFixup::emitOffset(Assembler *Asm) const {
675*03ce13f7SAndroid Build Coastguard Worker // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd,
676*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt.
677*03ce13f7SAndroid Build Coastguard Worker
678*03ce13f7SAndroid Build Coastguard Worker const IValueT Inst = Asm->load<IValueT>(position());
679*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Imm16Mask = 0x000F0FFF;
680*03ce13f7SAndroid Build Coastguard Worker const IValueT Imm16 = offset() & 0xffff;
681*03ce13f7SAndroid Build Coastguard Worker Asm->store(position(),
682*03ce13f7SAndroid Build Coastguard Worker (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff));
683*03ce13f7SAndroid Build Coastguard Worker }
684*03ce13f7SAndroid Build Coastguard Worker
createMoveFixup(bool IsMovW,const Constant * Value)685*03ce13f7SAndroid Build Coastguard Worker MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW,
686*03ce13f7SAndroid Build Coastguard Worker const Constant *Value) {
687*03ce13f7SAndroid Build Coastguard Worker MoveRelocatableFixup *F =
688*03ce13f7SAndroid Build Coastguard Worker new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup();
689*03ce13f7SAndroid Build Coastguard Worker F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC
690*03ce13f7SAndroid Build Coastguard Worker : llvm::ELF::R_ARM_MOVT_ABS);
691*03ce13f7SAndroid Build Coastguard Worker F->set_value(Value);
692*03ce13f7SAndroid Build Coastguard Worker Buffer.installFixup(F);
693*03ce13f7SAndroid Build Coastguard Worker return F;
694*03ce13f7SAndroid Build Coastguard Worker }
695*03ce13f7SAndroid Build Coastguard Worker
emit(GlobalContext * Ctx,const Assembler & Asm) const696*03ce13f7SAndroid Build Coastguard Worker size_t BlRelocatableFixup::emit(GlobalContext *Ctx,
697*03ce13f7SAndroid Build Coastguard Worker const Assembler &Asm) const {
698*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
699*03ce13f7SAndroid Build Coastguard Worker return InstARM32::InstSize;
700*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrEmit();
701*03ce13f7SAndroid Build Coastguard Worker IValueT Inst = Asm.load<IValueT>(position());
702*03ce13f7SAndroid Build Coastguard Worker Str << "\t"
703*03ce13f7SAndroid Build Coastguard Worker "bl\t"
704*03ce13f7SAndroid Build Coastguard Worker << symbol() << "\t@ .word " << llvm::format_hex_no_prefix(Inst, 8)
705*03ce13f7SAndroid Build Coastguard Worker << "\n";
706*03ce13f7SAndroid Build Coastguard Worker return InstARM32::InstSize;
707*03ce13f7SAndroid Build Coastguard Worker }
708*03ce13f7SAndroid Build Coastguard Worker
emitOffset(Assembler * Asm) const709*03ce13f7SAndroid Build Coastguard Worker void BlRelocatableFixup::emitOffset(Assembler *Asm) const {
710*03ce13f7SAndroid Build Coastguard Worker // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and
711*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiiiiiiiiiiiiiii=
712*03ce13f7SAndroid Build Coastguard Worker // EncodedBranchOffset(cccc101l000000000000000000000000, Offset);
713*03ce13f7SAndroid Build Coastguard Worker const IValueT Inst = Asm->load<IValueT>(position());
714*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT OffsetMask = 0x00FFFFFF;
715*03ce13f7SAndroid Build Coastguard Worker Asm->store(position(), encodeBranchOffset(offset(), Inst & ~OffsetMask));
716*03ce13f7SAndroid Build Coastguard Worker }
717*03ce13f7SAndroid Build Coastguard Worker
padWithNop(intptr_t Padding)718*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::padWithNop(intptr_t Padding) {
719*03ce13f7SAndroid Build Coastguard Worker constexpr intptr_t InstWidth = sizeof(IValueT);
720*03ce13f7SAndroid Build Coastguard Worker assert(Padding % InstWidth == 0 &&
721*03ce13f7SAndroid Build Coastguard Worker "Padding not multiple of instruction size");
722*03ce13f7SAndroid Build Coastguard Worker for (intptr_t i = 0; i < Padding; i += InstWidth)
723*03ce13f7SAndroid Build Coastguard Worker nop();
724*03ce13f7SAndroid Build Coastguard Worker }
725*03ce13f7SAndroid Build Coastguard Worker
726*03ce13f7SAndroid Build Coastguard Worker BlRelocatableFixup *
createBlFixup(const ConstantRelocatable * BlTarget)727*03ce13f7SAndroid Build Coastguard Worker AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) {
728*03ce13f7SAndroid Build Coastguard Worker BlRelocatableFixup *F =
729*03ce13f7SAndroid Build Coastguard Worker new (allocate<BlRelocatableFixup>()) BlRelocatableFixup();
730*03ce13f7SAndroid Build Coastguard Worker F->set_kind(llvm::ELF::R_ARM_CALL);
731*03ce13f7SAndroid Build Coastguard Worker F->set_value(BlTarget);
732*03ce13f7SAndroid Build Coastguard Worker Buffer.installFixup(F);
733*03ce13f7SAndroid Build Coastguard Worker return F;
734*03ce13f7SAndroid Build Coastguard Worker }
735*03ce13f7SAndroid Build Coastguard Worker
bindCfgNodeLabel(const CfgNode * Node)736*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) {
737*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
738*03ce13f7SAndroid Build Coastguard Worker // Generate label name so that branches can find it.
739*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT InstSize = 0;
740*03ce13f7SAndroid Build Coastguard Worker emitTextInst(Node->getAsmName() + ":", InstSize);
741*03ce13f7SAndroid Build Coastguard Worker }
742*03ce13f7SAndroid Build Coastguard Worker SizeT NodeNumber = Node->getIndex();
743*03ce13f7SAndroid Build Coastguard Worker assert(!getPreliminary());
744*03ce13f7SAndroid Build Coastguard Worker Label *L = getOrCreateCfgNodeLabel(NodeNumber);
745*03ce13f7SAndroid Build Coastguard Worker this->bind(L);
746*03ce13f7SAndroid Build Coastguard Worker }
747*03ce13f7SAndroid Build Coastguard Worker
getOrCreateLabel(SizeT Number,LabelVector & Labels)748*03ce13f7SAndroid Build Coastguard Worker Label *AssemblerARM32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
749*03ce13f7SAndroid Build Coastguard Worker Label *L = nullptr;
750*03ce13f7SAndroid Build Coastguard Worker if (Number == Labels.size()) {
751*03ce13f7SAndroid Build Coastguard Worker L = new (this->allocate<Label>()) Label();
752*03ce13f7SAndroid Build Coastguard Worker Labels.push_back(L);
753*03ce13f7SAndroid Build Coastguard Worker return L;
754*03ce13f7SAndroid Build Coastguard Worker }
755*03ce13f7SAndroid Build Coastguard Worker if (Number > Labels.size()) {
756*03ce13f7SAndroid Build Coastguard Worker Labels.resize(Number + 1);
757*03ce13f7SAndroid Build Coastguard Worker }
758*03ce13f7SAndroid Build Coastguard Worker L = Labels[Number];
759*03ce13f7SAndroid Build Coastguard Worker if (!L) {
760*03ce13f7SAndroid Build Coastguard Worker L = new (this->allocate<Label>()) Label();
761*03ce13f7SAndroid Build Coastguard Worker Labels[Number] = L;
762*03ce13f7SAndroid Build Coastguard Worker }
763*03ce13f7SAndroid Build Coastguard Worker return L;
764*03ce13f7SAndroid Build Coastguard Worker }
765*03ce13f7SAndroid Build Coastguard Worker
766*03ce13f7SAndroid Build Coastguard Worker // Pull out offset from branch Inst.
decodeBranchOffset(IValueT Inst)767*03ce13f7SAndroid Build Coastguard Worker IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) {
768*03ce13f7SAndroid Build Coastguard Worker // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC.
769*03ce13f7SAndroid Build Coastguard Worker const IOffsetT Offset = (Inst & kBranchOffsetMask) << 8;
770*03ce13f7SAndroid Build Coastguard Worker return (Offset >> 6) + kPCReadOffset;
771*03ce13f7SAndroid Build Coastguard Worker }
772*03ce13f7SAndroid Build Coastguard Worker
bind(Label * L)773*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::bind(Label *L) {
774*03ce13f7SAndroid Build Coastguard Worker IOffsetT BoundPc = Buffer.size();
775*03ce13f7SAndroid Build Coastguard Worker assert(!L->isBound()); // Labels can only be bound once.
776*03ce13f7SAndroid Build Coastguard Worker while (L->isLinked()) {
777*03ce13f7SAndroid Build Coastguard Worker IOffsetT Position = L->getLinkPosition();
778*03ce13f7SAndroid Build Coastguard Worker IOffsetT Dest = BoundPc - Position;
779*03ce13f7SAndroid Build Coastguard Worker IValueT Inst = Buffer.load<IValueT>(Position);
780*03ce13f7SAndroid Build Coastguard Worker Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
781*03ce13f7SAndroid Build Coastguard Worker L->setPosition(decodeBranchOffset(Inst));
782*03ce13f7SAndroid Build Coastguard Worker }
783*03ce13f7SAndroid Build Coastguard Worker L->bindTo(BoundPc);
784*03ce13f7SAndroid Build Coastguard Worker }
785*03ce13f7SAndroid Build Coastguard Worker
emitTextInst(const std::string & Text,SizeT InstSize)786*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) {
787*03ce13f7SAndroid Build Coastguard Worker AssemblerFixup *F = createTextFixup(Text, InstSize);
788*03ce13f7SAndroid Build Coastguard Worker emitFixup(F);
789*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < InstSize; ++I) {
790*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer::EnsureCapacity ensured(&Buffer);
791*03ce13f7SAndroid Build Coastguard Worker Buffer.emit<char>(0);
792*03ce13f7SAndroid Build Coastguard Worker }
793*03ce13f7SAndroid Build Coastguard Worker }
794*03ce13f7SAndroid Build Coastguard Worker
emitType01(CondARM32::Cond Cond,IValueT InstType,IValueT Opcode,bool SetFlags,IValueT Rn,IValueT Rd,IValueT Imm12,EmitChecks RuleChecks,const char * InstName)795*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT InstType,
796*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode, bool SetFlags, IValueT Rn,
797*03ce13f7SAndroid Build Coastguard Worker IValueT Rd, IValueT Imm12,
798*03ce13f7SAndroid Build Coastguard Worker EmitChecks RuleChecks, const char *InstName) {
799*03ce13f7SAndroid Build Coastguard Worker switch (RuleChecks) {
800*03ce13f7SAndroid Build Coastguard Worker case NoChecks:
801*03ce13f7SAndroid Build Coastguard Worker break;
802*03ce13f7SAndroid Build Coastguard Worker case RdIsPcAndSetFlags:
803*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPcWhenSetFlags(Rd, SetFlags, InstName);
804*03ce13f7SAndroid Build Coastguard Worker break;
805*03ce13f7SAndroid Build Coastguard Worker }
806*03ce13f7SAndroid Build Coastguard Worker assert(Rd < RegARM32::getNumGPRegs());
807*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
808*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
809*03ce13f7SAndroid Build Coastguard Worker (InstType << kTypeShift) | (Opcode << kOpcodeShift) |
810*03ce13f7SAndroid Build Coastguard Worker (encodeBool(SetFlags) << kSShift) |
811*03ce13f7SAndroid Build Coastguard Worker (Rn << kRnShift) | (Rd << kRdShift) | Imm12;
812*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
813*03ce13f7SAndroid Build Coastguard Worker }
814*03ce13f7SAndroid Build Coastguard Worker
emitType01(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,EmitChecks RuleChecks,const char * InstName)815*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode,
816*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRd, const Operand *OpRn,
817*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
818*03ce13f7SAndroid Build Coastguard Worker EmitChecks RuleChecks, const char *InstName) {
819*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
820*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", InstName);
821*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName);
822*03ce13f7SAndroid Build Coastguard Worker }
823*03ce13f7SAndroid Build Coastguard Worker
emitType01(CondARM32::Cond Cond,IValueT Opcode,IValueT Rd,IValueT Rn,const Operand * OpSrc1,bool SetFlags,EmitChecks RuleChecks,const char * InstName)824*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode,
825*03ce13f7SAndroid Build Coastguard Worker IValueT Rd, IValueT Rn, const Operand *OpSrc1,
826*03ce13f7SAndroid Build Coastguard Worker bool SetFlags, EmitChecks RuleChecks,
827*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
828*03ce13f7SAndroid Build Coastguard Worker IValueT Src1Value;
829*03ce13f7SAndroid Build Coastguard Worker // TODO(kschimpf) Other possible decodings of data operations.
830*03ce13f7SAndroid Build Coastguard Worker switch (encodeOperand(OpSrc1, Src1Value, WantGPRegs)) {
831*03ce13f7SAndroid Build Coastguard Worker default:
832*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
833*03ce13f7SAndroid Build Coastguard Worker ": Can't encode instruction");
834*03ce13f7SAndroid Build Coastguard Worker return;
835*03ce13f7SAndroid Build Coastguard Worker case EncodedAsRegister: {
836*03ce13f7SAndroid Build Coastguard Worker // XXX (register)
837*03ce13f7SAndroid Build Coastguard Worker // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>}
838*03ce13f7SAndroid Build Coastguard Worker //
839*03ce13f7SAndroid Build Coastguard Worker // cccc000xxxxsnnnnddddiiiiitt0mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd,
840*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn, mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
841*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Imm5 = 0;
842*03ce13f7SAndroid Build Coastguard Worker Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5);
843*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value,
844*03ce13f7SAndroid Build Coastguard Worker RuleChecks, InstName);
845*03ce13f7SAndroid Build Coastguard Worker return;
846*03ce13f7SAndroid Build Coastguard Worker }
847*03ce13f7SAndroid Build Coastguard Worker case EncodedAsShiftedRegister: {
848*03ce13f7SAndroid Build Coastguard Worker // Form is defined in case EncodedAsRegister. (i.e. XXX (register)).
849*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value,
850*03ce13f7SAndroid Build Coastguard Worker RuleChecks, InstName);
851*03ce13f7SAndroid Build Coastguard Worker return;
852*03ce13f7SAndroid Build Coastguard Worker }
853*03ce13f7SAndroid Build Coastguard Worker case EncodedAsConstI32: {
854*03ce13f7SAndroid Build Coastguard Worker // See if we can convert this to an XXX (immediate).
855*03ce13f7SAndroid Build Coastguard Worker IValueT RotateAmt;
856*03ce13f7SAndroid Build Coastguard Worker IValueT Imm8;
857*03ce13f7SAndroid Build Coastguard Worker if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8))
858*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
859*03ce13f7SAndroid Build Coastguard Worker ": Immediate rotated constant not valid");
860*03ce13f7SAndroid Build Coastguard Worker Src1Value = encodeRotatedImm8(RotateAmt, Imm8);
861*03ce13f7SAndroid Build Coastguard Worker // Intentionally fall to next case!
862*03ce13f7SAndroid Build Coastguard Worker }
863*03ce13f7SAndroid Build Coastguard Worker case EncodedAsRotatedImm8: {
864*03ce13f7SAndroid Build Coastguard Worker // XXX (Immediate)
865*03ce13f7SAndroid Build Coastguard Worker // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8>
866*03ce13f7SAndroid Build Coastguard Worker //
867*03ce13f7SAndroid Build Coastguard Worker // cccc001xxxxsnnnnddddiiiiiiiiiiii where cccc=Cond, xxxx=Opcode, dddd=Rd,
868*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn, s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
869*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd,
870*03ce13f7SAndroid Build Coastguard Worker Src1Value, RuleChecks, InstName);
871*03ce13f7SAndroid Build Coastguard Worker return;
872*03ce13f7SAndroid Build Coastguard Worker }
873*03ce13f7SAndroid Build Coastguard Worker case EncodedAsRegShiftReg: {
874*03ce13f7SAndroid Build Coastguard Worker // XXX (register-shifted reg)
875*03ce13f7SAndroid Build Coastguard Worker // xxx{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
876*03ce13f7SAndroid Build Coastguard Worker //
877*03ce13f7SAndroid Build Coastguard Worker // cccc000xxxxfnnnnddddssss0tt1mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd,
878*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn, ssss=Rs, f=SetFlags, tt is encoding of type, and
879*03ce13f7SAndroid Build Coastguard Worker // Src1Value=ssss01tt1mmmm.
880*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, kInstTypeDataRegShift, Opcode, SetFlags, Rn, Rd, Src1Value,
881*03ce13f7SAndroid Build Coastguard Worker RuleChecks, InstName);
882*03ce13f7SAndroid Build Coastguard Worker return;
883*03ce13f7SAndroid Build Coastguard Worker }
884*03ce13f7SAndroid Build Coastguard Worker }
885*03ce13f7SAndroid Build Coastguard Worker }
886*03ce13f7SAndroid Build Coastguard Worker
emitType05(CondARM32::Cond Cond,IOffsetT Offset,bool Link)887*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset,
888*03ce13f7SAndroid Build Coastguard Worker bool Link) {
889*03ce13f7SAndroid Build Coastguard Worker // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and
890*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiiiiiiiiiiiiiii=
891*03ce13f7SAndroid Build Coastguard Worker // EncodedBranchOffset(cccc101l000000000000000000000000, Offset);
892*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
893*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift |
894*03ce13f7SAndroid Build Coastguard Worker 5 << kTypeShift | (Link ? 1 : 0) << kLinkShift;
895*03ce13f7SAndroid Build Coastguard Worker Encoding = encodeBranchOffset(Offset, Encoding);
896*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
897*03ce13f7SAndroid Build Coastguard Worker }
898*03ce13f7SAndroid Build Coastguard Worker
emitBranch(Label * L,CondARM32::Cond Cond,bool Link)899*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) {
900*03ce13f7SAndroid Build Coastguard Worker // TODO(kschimpf): Handle far jumps.
901*03ce13f7SAndroid Build Coastguard Worker if (L->isBound()) {
902*03ce13f7SAndroid Build Coastguard Worker const int32_t Dest = L->getPosition() - Buffer.size();
903*03ce13f7SAndroid Build Coastguard Worker emitType05(Cond, Dest, Link);
904*03ce13f7SAndroid Build Coastguard Worker return;
905*03ce13f7SAndroid Build Coastguard Worker }
906*03ce13f7SAndroid Build Coastguard Worker const IOffsetT Position = Buffer.size();
907*03ce13f7SAndroid Build Coastguard Worker // Use the offset field of the branch instruction for linking the sites.
908*03ce13f7SAndroid Build Coastguard Worker emitType05(Cond, L->getEncodedPosition(), Link);
909*03ce13f7SAndroid Build Coastguard Worker L->linkTo(*this, Position);
910*03ce13f7SAndroid Build Coastguard Worker }
911*03ce13f7SAndroid Build Coastguard Worker
emitCompareOp(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRn,const Operand * OpSrc1,const char * InstName)912*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode,
913*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRn, const Operand *OpSrc1,
914*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
915*03ce13f7SAndroid Build Coastguard Worker // XXX (register)
916*03ce13f7SAndroid Build Coastguard Worker // XXX<c> <Rn>, <Rm>{, <shift>}
917*03ce13f7SAndroid Build Coastguard Worker //
918*03ce13f7SAndroid Build Coastguard Worker // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii
919*03ce13f7SAndroid Build Coastguard Worker // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and
920*03ce13f7SAndroid Build Coastguard Worker // xxxx=Opcode.
921*03ce13f7SAndroid Build Coastguard Worker //
922*03ce13f7SAndroid Build Coastguard Worker // XXX (immediate)
923*03ce13f7SAndroid Build Coastguard Worker // XXX<c> <Rn>, #<RotatedImm8>
924*03ce13f7SAndroid Build Coastguard Worker //
925*03ce13f7SAndroid Build Coastguard Worker // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
926*03ce13f7SAndroid Build Coastguard Worker // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value
927*03ce13f7SAndroid Build Coastguard Worker // defining RotatedImm8.
928*03ce13f7SAndroid Build Coastguard Worker constexpr bool SetFlags = true;
929*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rd = RegARM32::Encoded_Reg_r0;
930*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", InstName);
931*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, NoChecks, InstName);
932*03ce13f7SAndroid Build Coastguard Worker }
933*03ce13f7SAndroid Build Coastguard Worker
emitMemOp(CondARM32::Cond Cond,IValueT InstType,bool IsLoad,bool IsByte,IValueT Rt,IValueT Address)934*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
935*03ce13f7SAndroid Build Coastguard Worker bool IsLoad, bool IsByte, IValueT Rt,
936*03ce13f7SAndroid Build Coastguard Worker IValueT Address) {
937*03ce13f7SAndroid Build Coastguard Worker assert(Rt < RegARM32::getNumGPRegs());
938*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
939*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
940*03ce13f7SAndroid Build Coastguard Worker (InstType << kTypeShift) | (IsLoad ? L : 0) |
941*03ce13f7SAndroid Build Coastguard Worker (IsByte ? B : 0) | (Rt << kRdShift) | Address;
942*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
943*03ce13f7SAndroid Build Coastguard Worker }
944*03ce13f7SAndroid Build Coastguard Worker
emitMemOp(CondARM32::Cond Cond,bool IsLoad,bool IsByte,IValueT Rt,const Operand * OpAddress,const TargetInfo & TInfo,const char * InstName)945*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte,
946*03ce13f7SAndroid Build Coastguard Worker IValueT Rt, const Operand *OpAddress,
947*03ce13f7SAndroid Build Coastguard Worker const TargetInfo &TInfo, const char *InstName) {
948*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
949*03ce13f7SAndroid Build Coastguard Worker switch (encodeAddress(OpAddress, Address, TInfo, Imm12Address)) {
950*03ce13f7SAndroid Build Coastguard Worker default:
951*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
952*03ce13f7SAndroid Build Coastguard Worker ": Memory address not understood");
953*03ce13f7SAndroid Build Coastguard Worker case EncodedAsImmRegOffset: {
954*03ce13f7SAndroid Build Coastguard Worker // XXX{B} (immediate):
955*03ce13f7SAndroid Build Coastguard Worker // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
956*03ce13f7SAndroid Build Coastguard Worker // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
957*03ce13f7SAndroid Build Coastguard Worker // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
958*03ce13f7SAndroid Build Coastguard Worker //
959*03ce13f7SAndroid Build Coastguard Worker // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
960*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and
961*03ce13f7SAndroid Build Coastguard Worker // pu0w0nnnn0000iiiiiiiiiiii=Address.
962*03ce13f7SAndroid Build Coastguard Worker RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
963*03ce13f7SAndroid Build Coastguard Worker
964*03ce13f7SAndroid Build Coastguard Worker // Check if conditions of rules violated.
965*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", InstName);
966*03ce13f7SAndroid Build Coastguard Worker verifyPOrNotW(Address, InstName);
967*03ce13f7SAndroid Build Coastguard Worker if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) &&
968*03ce13f7SAndroid Build Coastguard Worker isBitSet(U, Address) && !isBitSet(W, Address) &&
969*03ce13f7SAndroid Build Coastguard Worker (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
970*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
971*03ce13f7SAndroid Build Coastguard Worker ": Use push/pop instead");
972*03ce13f7SAndroid Build Coastguard Worker
973*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
974*03ce13f7SAndroid Build Coastguard Worker return;
975*03ce13f7SAndroid Build Coastguard Worker }
976*03ce13f7SAndroid Build Coastguard Worker case EncodedAsShiftRotateImm5: {
977*03ce13f7SAndroid Build Coastguard Worker // XXX{B} (register)
978*03ce13f7SAndroid Build Coastguard Worker // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
979*03ce13f7SAndroid Build Coastguard Worker // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
980*03ce13f7SAndroid Build Coastguard Worker //
981*03ce13f7SAndroid Build Coastguard Worker // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt,
982*03ce13f7SAndroid Build Coastguard Worker // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and
983*03ce13f7SAndroid Build Coastguard Worker // pu0w0nnnn0000iiiiiss0mmmm=Address.
984*03ce13f7SAndroid Build Coastguard Worker RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
985*03ce13f7SAndroid Build Coastguard Worker RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address);
986*03ce13f7SAndroid Build Coastguard Worker
987*03ce13f7SAndroid Build Coastguard Worker // Check if conditions of rules violated.
988*03ce13f7SAndroid Build Coastguard Worker verifyPOrNotW(Address, InstName);
989*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", InstName);
990*03ce13f7SAndroid Build Coastguard Worker if (IsByte)
991*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rt, "Rt", InstName);
992*03ce13f7SAndroid Build Coastguard Worker if (isBitSet(W, Address)) {
993*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", InstName);
994*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName);
995*03ce13f7SAndroid Build Coastguard Worker }
996*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address);
997*03ce13f7SAndroid Build Coastguard Worker return;
998*03ce13f7SAndroid Build Coastguard Worker }
999*03ce13f7SAndroid Build Coastguard Worker }
1000*03ce13f7SAndroid Build Coastguard Worker }
1001*03ce13f7SAndroid Build Coastguard Worker
emitMemOpEnc3(CondARM32::Cond Cond,IValueT Opcode,IValueT Rt,const Operand * OpAddress,const TargetInfo & TInfo,const char * InstName)1002*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
1003*03ce13f7SAndroid Build Coastguard Worker IValueT Rt, const Operand *OpAddress,
1004*03ce13f7SAndroid Build Coastguard Worker const TargetInfo &TInfo,
1005*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
1006*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
1007*03ce13f7SAndroid Build Coastguard Worker switch (encodeAddress(OpAddress, Address, TInfo, RotatedImm8Enc3Address)) {
1008*03ce13f7SAndroid Build Coastguard Worker default:
1009*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
1010*03ce13f7SAndroid Build Coastguard Worker ": Memory address not understood");
1011*03ce13f7SAndroid Build Coastguard Worker case EncodedAsImmRegOffset: {
1012*03ce13f7SAndroid Build Coastguard Worker // XXXH (immediate)
1013*03ce13f7SAndroid Build Coastguard Worker // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}]
1014*03ce13f7SAndroid Build Coastguard Worker // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]
1015*03ce13f7SAndroid Build Coastguard Worker // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1016*03ce13f7SAndroid Build Coastguard Worker //
1017*03ce13f7SAndroid Build Coastguard Worker // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt,
1018*03ce13f7SAndroid Build Coastguard Worker // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode,
1019*03ce13f7SAndroid Build Coastguard Worker // and pu0w0nnnn0000iiii0000jjjj=Address.
1020*03ce13f7SAndroid Build Coastguard Worker assert(Rt < RegARM32::getNumGPRegs());
1021*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1022*03ce13f7SAndroid Build Coastguard Worker verifyPOrNotW(Address, InstName);
1023*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rt, "Rt", InstName);
1024*03ce13f7SAndroid Build Coastguard Worker if (isBitSet(W, Address))
1025*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName);
1026*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
1027*03ce13f7SAndroid Build Coastguard Worker Opcode | (Rt << kRdShift) | Address;
1028*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1029*03ce13f7SAndroid Build Coastguard Worker return;
1030*03ce13f7SAndroid Build Coastguard Worker }
1031*03ce13f7SAndroid Build Coastguard Worker case EncodedAsShiftRotateImm5: {
1032*03ce13f7SAndroid Build Coastguard Worker // XXXH (register)
1033*03ce13f7SAndroid Build Coastguard Worker // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!}
1034*03ce13f7SAndroid Build Coastguard Worker // xxxh<c> <Rt>, [<Rn>], +/-<Rm>
1035*03ce13f7SAndroid Build Coastguard Worker //
1036*03ce13f7SAndroid Build Coastguard Worker // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn,
1037*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and
1038*03ce13f7SAndroid Build Coastguard Worker // pu0w0nnnn000000000000mmmm=Address.
1039*03ce13f7SAndroid Build Coastguard Worker assert(Rt < RegARM32::getNumGPRegs());
1040*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1041*03ce13f7SAndroid Build Coastguard Worker verifyPOrNotW(Address, InstName);
1042*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rt, "Rt", InstName);
1043*03ce13f7SAndroid Build Coastguard Worker verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName);
1044*03ce13f7SAndroid Build Coastguard Worker const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
1045*03ce13f7SAndroid Build Coastguard Worker if (isBitSet(W, Address)) {
1046*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", InstName);
1047*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName);
1048*03ce13f7SAndroid Build Coastguard Worker }
1049*03ce13f7SAndroid Build Coastguard Worker if (mask(Address, kShiftImmShift, 5) != 0)
1050*03ce13f7SAndroid Build Coastguard Worker // For encoding 3, no shift is allowed.
1051*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
1052*03ce13f7SAndroid Build Coastguard Worker ": Shift constant not allowed");
1053*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
1054*03ce13f7SAndroid Build Coastguard Worker Opcode | (Rt << kRdShift) | Address;
1055*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1056*03ce13f7SAndroid Build Coastguard Worker return;
1057*03ce13f7SAndroid Build Coastguard Worker }
1058*03ce13f7SAndroid Build Coastguard Worker }
1059*03ce13f7SAndroid Build Coastguard Worker }
1060*03ce13f7SAndroid Build Coastguard Worker
emitDivOp(CondARM32::Cond Cond,IValueT Opcode,IValueT Rd,IValueT Rn,IValueT Rm)1061*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
1062*03ce13f7SAndroid Build Coastguard Worker IValueT Rn, IValueT Rm) {
1063*03ce13f7SAndroid Build Coastguard Worker assert(Rd < RegARM32::getNumGPRegs());
1064*03ce13f7SAndroid Build Coastguard Worker assert(Rn < RegARM32::getNumGPRegs());
1065*03ce13f7SAndroid Build Coastguard Worker assert(Rm < RegARM32::getNumGPRegs());
1066*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1067*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) |
1068*03ce13f7SAndroid Build Coastguard Worker (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 |
1069*03ce13f7SAndroid Build Coastguard Worker B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 |
1070*03ce13f7SAndroid Build Coastguard Worker (Rm << kDivRmShift);
1071*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1072*03ce13f7SAndroid Build Coastguard Worker }
1073*03ce13f7SAndroid Build Coastguard Worker
emitInsertExtractInt(CondARM32::Cond Cond,const Operand * OpQn,uint32_t Index,const Operand * OpRt,bool IsExtract,const char * InstName)1074*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitInsertExtractInt(CondARM32::Cond Cond,
1075*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn, uint32_t Index,
1076*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt, bool IsExtract,
1077*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
1078*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InstName);
1079*03ce13f7SAndroid Build Coastguard Worker IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", InstName));
1080*03ce13f7SAndroid Build Coastguard Worker assert(Rt != RegARM32::Encoded_Reg_pc);
1081*03ce13f7SAndroid Build Coastguard Worker assert(Rt != RegARM32::Encoded_Reg_sp);
1082*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1083*03ce13f7SAndroid Build Coastguard Worker const uint32_t BitSize = typeWidthInBytes(OpRt->getType()) * CHAR_BIT;
1084*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode1 = 0;
1085*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode2 = 0;
1086*03ce13f7SAndroid Build Coastguard Worker switch (BitSize) {
1087*03ce13f7SAndroid Build Coastguard Worker default:
1088*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
1089*03ce13f7SAndroid Build Coastguard Worker ": Unable to process type " +
1090*03ce13f7SAndroid Build Coastguard Worker typeStdString(OpRt->getType()));
1091*03ce13f7SAndroid Build Coastguard Worker case 8:
1092*03ce13f7SAndroid Build Coastguard Worker assert(Index < 16);
1093*03ce13f7SAndroid Build Coastguard Worker Dn = Dn | mask(Index, 3, 1);
1094*03ce13f7SAndroid Build Coastguard Worker Opcode1 = B1 | mask(Index, 2, 1);
1095*03ce13f7SAndroid Build Coastguard Worker Opcode2 = mask(Index, 0, 2);
1096*03ce13f7SAndroid Build Coastguard Worker break;
1097*03ce13f7SAndroid Build Coastguard Worker case 16:
1098*03ce13f7SAndroid Build Coastguard Worker assert(Index < 8);
1099*03ce13f7SAndroid Build Coastguard Worker Dn = Dn | mask(Index, 2, 1);
1100*03ce13f7SAndroid Build Coastguard Worker Opcode1 = mask(Index, 1, 1);
1101*03ce13f7SAndroid Build Coastguard Worker Opcode2 = (mask(Index, 0, 1) << 1) | B0;
1102*03ce13f7SAndroid Build Coastguard Worker break;
1103*03ce13f7SAndroid Build Coastguard Worker case 32:
1104*03ce13f7SAndroid Build Coastguard Worker assert(Index < 4);
1105*03ce13f7SAndroid Build Coastguard Worker Dn = Dn | mask(Index, 1, 1);
1106*03ce13f7SAndroid Build Coastguard Worker Opcode1 = mask(Index, 0, 1);
1107*03ce13f7SAndroid Build Coastguard Worker break;
1108*03ce13f7SAndroid Build Coastguard Worker }
1109*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = B27 | B26 | B25 | B11 | B9 | B8 | B4 |
1110*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) |
1111*03ce13f7SAndroid Build Coastguard Worker (Opcode1 << 21) |
1112*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dn) << kRnShift) | (Rt << 12) |
1113*03ce13f7SAndroid Build Coastguard Worker (encodeBool(IsExtract) << 20) |
1114*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dn) << 7) | (Opcode2 << 5);
1115*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1116*03ce13f7SAndroid Build Coastguard Worker }
1117*03ce13f7SAndroid Build Coastguard Worker
emitMoveSS(CondARM32::Cond Cond,IValueT Sd,IValueT Sm)1118*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) {
1119*03ce13f7SAndroid Build Coastguard Worker // VMOV (register) - ARM section A8.8.340, encoding A2:
1120*03ce13f7SAndroid Build Coastguard Worker // vmov<c>.f32 <Sd>, <Sm>
1121*03ce13f7SAndroid Build Coastguard Worker //
1122*03ce13f7SAndroid Build Coastguard Worker // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
1123*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6;
1124*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
1125*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm);
1126*03ce13f7SAndroid Build Coastguard Worker }
1127*03ce13f7SAndroid Build Coastguard Worker
emitMulOp(CondARM32::Cond Cond,IValueT Opcode,IValueT Rd,IValueT Rn,IValueT Rm,IValueT Rs,bool SetFlags)1128*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
1129*03ce13f7SAndroid Build Coastguard Worker IValueT Rn, IValueT Rm, IValueT Rs,
1130*03ce13f7SAndroid Build Coastguard Worker bool SetFlags) {
1131*03ce13f7SAndroid Build Coastguard Worker assert(Rd < RegARM32::getNumGPRegs());
1132*03ce13f7SAndroid Build Coastguard Worker assert(Rn < RegARM32::getNumGPRegs());
1133*03ce13f7SAndroid Build Coastguard Worker assert(Rm < RegARM32::getNumGPRegs());
1134*03ce13f7SAndroid Build Coastguard Worker assert(Rs < RegARM32::getNumGPRegs());
1135*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1136*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) |
1137*03ce13f7SAndroid Build Coastguard Worker (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) |
1138*03ce13f7SAndroid Build Coastguard Worker (Rd << kRdShift) | (Rs << kRsShift) | B7 | B4 |
1139*03ce13f7SAndroid Build Coastguard Worker (Rm << kRmShift);
1140*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1141*03ce13f7SAndroid Build Coastguard Worker }
1142*03ce13f7SAndroid Build Coastguard Worker
emitMultiMemOp(CondARM32::Cond Cond,BlockAddressMode AddressMode,bool IsLoad,IValueT BaseReg,IValueT Registers)1143*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond,
1144*03ce13f7SAndroid Build Coastguard Worker BlockAddressMode AddressMode, bool IsLoad,
1145*03ce13f7SAndroid Build Coastguard Worker IValueT BaseReg, IValueT Registers) {
1146*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1147*03ce13f7SAndroid Build Coastguard Worker assert(BaseReg < RegARM32::getNumGPRegs());
1148*03ce13f7SAndroid Build Coastguard Worker assert(Registers < (1 << RegARM32::getNumGPRegs()));
1149*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 |
1150*03ce13f7SAndroid Build Coastguard Worker AddressMode | (IsLoad ? L : 0) | (BaseReg << kRnShift) |
1151*03ce13f7SAndroid Build Coastguard Worker Registers;
1152*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1153*03ce13f7SAndroid Build Coastguard Worker }
1154*03ce13f7SAndroid Build Coastguard Worker
emitSignExtend(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRd,const Operand * OpSrc0,const char * InstName)1155*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode,
1156*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRd, const Operand *OpSrc0,
1157*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
1158*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
1159*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpSrc0, "Rm", InstName);
1160*03ce13f7SAndroid Build Coastguard Worker // Note: For the moment, we assume no rotation is specified.
1161*03ce13f7SAndroid Build Coastguard Worker RotationValue Rotation = kRotateNone;
1162*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rn = RegARM32::Encoded_Reg_pc;
1163*03ce13f7SAndroid Build Coastguard Worker const Type Ty = OpSrc0->getType();
1164*03ce13f7SAndroid Build Coastguard Worker switch (Ty) {
1165*03ce13f7SAndroid Build Coastguard Worker default:
1166*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": Type " +
1167*03ce13f7SAndroid Build Coastguard Worker typeString(Ty) + " not allowed");
1168*03ce13f7SAndroid Build Coastguard Worker break;
1169*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
1170*03ce13f7SAndroid Build Coastguard Worker case IceType_i8: {
1171*03ce13f7SAndroid Build Coastguard Worker // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1:
1172*03ce13f7SAndroid Build Coastguard Worker // sxtb<c> <Rd>, <Rm>{, <rotate>}
1173*03ce13f7SAndroid Build Coastguard Worker // uxtb<c> <Rd>, <Rm>{, <rotate>}
1174*03ce13f7SAndroid Build Coastguard Worker //
1175*03ce13f7SAndroid Build Coastguard Worker // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
1176*03ce13f7SAndroid Build Coastguard Worker // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate.
1177*03ce13f7SAndroid Build Coastguard Worker break;
1178*03ce13f7SAndroid Build Coastguard Worker }
1179*03ce13f7SAndroid Build Coastguard Worker case IceType_i16: {
1180*03ce13f7SAndroid Build Coastguard Worker // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1:
1181*03ce13f7SAndroid Build Coastguard Worker // uxth<c> <Rd>< <Rm>{, <rotate>}
1182*03ce13f7SAndroid Build Coastguard Worker //
1183*03ce13f7SAndroid Build Coastguard Worker // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and
1184*03ce13f7SAndroid Build Coastguard Worker // rr defined (RotationValue) rotate.
1185*03ce13f7SAndroid Build Coastguard Worker Opcode |= B20;
1186*03ce13f7SAndroid Build Coastguard Worker break;
1187*03ce13f7SAndroid Build Coastguard Worker }
1188*03ce13f7SAndroid Build Coastguard Worker }
1189*03ce13f7SAndroid Build Coastguard Worker
1190*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1191*03ce13f7SAndroid Build Coastguard Worker IValueT Rot = encodeRotation(Rotation);
1192*03ce13f7SAndroid Build Coastguard Worker if (!Utils::IsUint(2, Rot))
1193*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
1194*03ce13f7SAndroid Build Coastguard Worker ": Illegal rotation value");
1195*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode |
1196*03ce13f7SAndroid Build Coastguard Worker (Rn << kRnShift) | (Rd << kRdShift) |
1197*03ce13f7SAndroid Build Coastguard Worker (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift);
1198*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1199*03ce13f7SAndroid Build Coastguard Worker }
1200*03ce13f7SAndroid Build Coastguard Worker
emitSIMDBase(IValueT Opcode,IValueT Dd,IValueT Dn,IValueT Dm,bool UseQRegs,bool IsFloatTy)1201*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn,
1202*03ce13f7SAndroid Build Coastguard Worker IValueT Dm, bool UseQRegs, bool IsFloatTy) {
1203*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
1204*03ce13f7SAndroid Build Coastguard Worker Opcode | B25 | (encodeCondition(CondARM32::kNone) << kConditionShift) |
1205*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
1206*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | (IsFloatTy ? B10 : 0) |
1207*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dn) << 7) | (encodeBool(UseQRegs) << 6) |
1208*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
1209*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1210*03ce13f7SAndroid Build Coastguard Worker }
1211*03ce13f7SAndroid Build Coastguard Worker
emitSIMD(IValueT Opcode,Type ElmtTy,IValueT Dd,IValueT Dn,IValueT Dm,bool UseQRegs)1212*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd,
1213*03ce13f7SAndroid Build Coastguard Worker IValueT Dn, IValueT Dm, bool UseQRegs) {
1214*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 20;
1215*03ce13f7SAndroid Build Coastguard Worker const IValueT ElmtSize = encodeElmtType(ElmtTy);
1216*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(2, ElmtSize));
1217*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(Opcode | (ElmtSize << ElmtShift), Dd, Dn, Dm, UseQRegs,
1218*03ce13f7SAndroid Build Coastguard Worker isFloatingType(ElmtTy));
1219*03ce13f7SAndroid Build Coastguard Worker }
1220*03ce13f7SAndroid Build Coastguard Worker
emitSIMDqqqBase(IValueT Opcode,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm,bool IsFloatTy,const char * OpcodeName)1221*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd,
1222*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn, const Operand *OpQm,
1223*03ce13f7SAndroid Build Coastguard Worker bool IsFloatTy, const char *OpcodeName) {
1224*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName);
1225*03ce13f7SAndroid Build Coastguard Worker const IValueT Qn = encodeQRegister(OpQn, "Qn", OpcodeName);
1226*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName);
1227*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
1228*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(Opcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), mapQRegToDReg(Qm),
1229*03ce13f7SAndroid Build Coastguard Worker UseQRegs, IsFloatTy);
1230*03ce13f7SAndroid Build Coastguard Worker }
1231*03ce13f7SAndroid Build Coastguard Worker
emitSIMDqqq(IValueT Opcode,Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm,const char * OpcodeName)1232*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy,
1233*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQd, const Operand *OpQn,
1234*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const char *OpcodeName) {
1235*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 20;
1236*03ce13f7SAndroid Build Coastguard Worker const IValueT ElmtSize = encodeElmtType(ElmtTy);
1237*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(2, ElmtSize));
1238*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqqBase(Opcode | (ElmtSize << ElmtShift), OpQd, OpQn, OpQm,
1239*03ce13f7SAndroid Build Coastguard Worker isFloatingType(ElmtTy), OpcodeName);
1240*03ce13f7SAndroid Build Coastguard Worker }
1241*03ce13f7SAndroid Build Coastguard Worker
emitSIMDShiftqqc(IValueT Opcode,const Operand * OpQd,const Operand * OpQm,const IValueT Imm6,const char * OpcodeName)1242*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd,
1243*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const IValueT Imm6,
1244*03ce13f7SAndroid Build Coastguard Worker const char *OpcodeName) {
1245*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName);
1246*03ce13f7SAndroid Build Coastguard Worker const IValueT Qn = 0;
1247*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName);
1248*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
1249*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
1250*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 16;
1251*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(Opcode | (Imm6 << ElmtShift), mapQRegToDReg(Qd),
1252*03ce13f7SAndroid Build Coastguard Worker mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs, IsFloatTy);
1253*03ce13f7SAndroid Build Coastguard Worker }
1254*03ce13f7SAndroid Build Coastguard Worker
emitSIMDCvtqq(IValueT Opcode,const Operand * OpQd,const Operand * OpQm,const char * OpcodeName)1255*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd,
1256*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm,
1257*03ce13f7SAndroid Build Coastguard Worker const char *OpcodeName) {
1258*03ce13f7SAndroid Build Coastguard Worker const IValueT SIMDOpcode =
1259*03ce13f7SAndroid Build Coastguard Worker B24 | B23 | B21 | B20 | B19 | B17 | B16 | B10 | B9 | Opcode;
1260*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
1261*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
1262*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName);
1263*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Qn = 0;
1264*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName);
1265*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(SIMDOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn),
1266*03ce13f7SAndroid Build Coastguard Worker mapQRegToDReg(Qm), UseQRegs, IsFloatTy);
1267*03ce13f7SAndroid Build Coastguard Worker }
1268*03ce13f7SAndroid Build Coastguard Worker
emitVFPddd(CondARM32::Cond Cond,IValueT Opcode,IValueT Dd,IValueT Dn,IValueT Dm)1269*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode,
1270*03ce13f7SAndroid Build Coastguard Worker IValueT Dd, IValueT Dn, IValueT Dm) {
1271*03ce13f7SAndroid Build Coastguard Worker assert(Dd < RegARM32::getNumDRegs());
1272*03ce13f7SAndroid Build Coastguard Worker assert(Dn < RegARM32::getNumDRegs());
1273*03ce13f7SAndroid Build Coastguard Worker assert(Dm < RegARM32::getNumDRegs());
1274*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1275*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8;
1276*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
1277*03ce13f7SAndroid Build Coastguard Worker Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
1278*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
1279*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
1280*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
1281*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1282*03ce13f7SAndroid Build Coastguard Worker }
1283*03ce13f7SAndroid Build Coastguard Worker
emitVFPddd(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,const char * InstName)1284*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode,
1285*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDd, const Operand *OpDn,
1286*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, const char *InstName) {
1287*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", InstName);
1288*03ce13f7SAndroid Build Coastguard Worker IValueT Dn = encodeDRegister(OpDn, "Dn", InstName);
1289*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", InstName);
1290*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, Opcode, Dd, Dn, Dm);
1291*03ce13f7SAndroid Build Coastguard Worker }
1292*03ce13f7SAndroid Build Coastguard Worker
emitVFPsss(CondARM32::Cond Cond,IValueT Opcode,IValueT Sd,IValueT Sn,IValueT Sm)1293*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVFPsss(CondARM32::Cond Cond, IValueT Opcode,
1294*03ce13f7SAndroid Build Coastguard Worker IValueT Sd, IValueT Sn, IValueT Sm) {
1295*03ce13f7SAndroid Build Coastguard Worker assert(Sd < RegARM32::getNumSRegs());
1296*03ce13f7SAndroid Build Coastguard Worker assert(Sn < RegARM32::getNumSRegs());
1297*03ce13f7SAndroid Build Coastguard Worker assert(Sm < RegARM32::getNumSRegs());
1298*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1299*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
1300*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
1301*03ce13f7SAndroid Build Coastguard Worker Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
1302*03ce13f7SAndroid Build Coastguard Worker (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sn) << 16) |
1303*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegXXXXY(Sd) << 12) | (getYInRegXXXXY(Sn) << 7) |
1304*03ce13f7SAndroid Build Coastguard Worker (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm);
1305*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1306*03ce13f7SAndroid Build Coastguard Worker }
1307*03ce13f7SAndroid Build Coastguard Worker
emitVFPsss(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,const char * InstName)1308*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVFPsss(CondARM32::Cond Cond, IValueT Opcode,
1309*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSd, const Operand *OpSn,
1310*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, const char *InstName) {
1311*03ce13f7SAndroid Build Coastguard Worker const IValueT Sd = encodeSRegister(OpSd, "Sd", InstName);
1312*03ce13f7SAndroid Build Coastguard Worker const IValueT Sn = encodeSRegister(OpSn, "Sn", InstName);
1313*03ce13f7SAndroid Build Coastguard Worker const IValueT Sm = encodeSRegister(OpSm, "Sm", InstName);
1314*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, Opcode, Sd, Sn, Sm);
1315*03ce13f7SAndroid Build Coastguard Worker }
1316*03ce13f7SAndroid Build Coastguard Worker
adc(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1317*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn,
1318*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1319*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1320*03ce13f7SAndroid Build Coastguard Worker // ADC (register) - ARM section 18.8.2, encoding A1:
1321*03ce13f7SAndroid Build Coastguard Worker // adc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1322*03ce13f7SAndroid Build Coastguard Worker //
1323*03ce13f7SAndroid Build Coastguard Worker // cccc0000101snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1324*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1325*03ce13f7SAndroid Build Coastguard Worker //
1326*03ce13f7SAndroid Build Coastguard Worker // ADC (Immediate) - ARM section A8.8.1, encoding A1:
1327*03ce13f7SAndroid Build Coastguard Worker // adc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1328*03ce13f7SAndroid Build Coastguard Worker //
1329*03ce13f7SAndroid Build Coastguard Worker // cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1330*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1331*03ce13f7SAndroid Build Coastguard Worker constexpr const char *AdcName = "adc";
1332*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT AdcOpcode = B2 | B0; // 0101
1333*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, AdcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1334*03ce13f7SAndroid Build Coastguard Worker AdcName);
1335*03ce13f7SAndroid Build Coastguard Worker }
1336*03ce13f7SAndroid Build Coastguard Worker
add(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1337*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
1338*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1339*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1340*03ce13f7SAndroid Build Coastguard Worker // ADD (register) - ARM section A8.8.7, encoding A1:
1341*03ce13f7SAndroid Build Coastguard Worker // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>}
1342*03ce13f7SAndroid Build Coastguard Worker // ADD (Sp plus register) - ARM section A8.8.11, encoding A1:
1343*03ce13f7SAndroid Build Coastguard Worker // add{s}<c> sp, <Rn>, <Rm>{, <shiff>}
1344*03ce13f7SAndroid Build Coastguard Worker //
1345*03ce13f7SAndroid Build Coastguard Worker // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1346*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1347*03ce13f7SAndroid Build Coastguard Worker //
1348*03ce13f7SAndroid Build Coastguard Worker // ADD (Immediate) - ARM section A8.8.5, encoding A1:
1349*03ce13f7SAndroid Build Coastguard Worker // add{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1350*03ce13f7SAndroid Build Coastguard Worker // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1.
1351*03ce13f7SAndroid Build Coastguard Worker // add{s}<c> <Rd>, sp, #<RotatedImm8>
1352*03ce13f7SAndroid Build Coastguard Worker //
1353*03ce13f7SAndroid Build Coastguard Worker // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1354*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1355*03ce13f7SAndroid Build Coastguard Worker constexpr const char *AddName = "add";
1356*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Add = B2; // 0100
1357*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, Add, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1358*03ce13f7SAndroid Build Coastguard Worker AddName);
1359*03ce13f7SAndroid Build Coastguard Worker }
1360*03ce13f7SAndroid Build Coastguard Worker
and_(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1361*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn,
1362*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1363*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1364*03ce13f7SAndroid Build Coastguard Worker // AND (register) - ARM section A8.8.14, encoding A1:
1365*03ce13f7SAndroid Build Coastguard Worker // and{s}<c> <Rd>, <Rn>{, <shift>}
1366*03ce13f7SAndroid Build Coastguard Worker //
1367*03ce13f7SAndroid Build Coastguard Worker // cccc0000000snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1368*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1369*03ce13f7SAndroid Build Coastguard Worker //
1370*03ce13f7SAndroid Build Coastguard Worker // AND (Immediate) - ARM section A8.8.13, encoding A1:
1371*03ce13f7SAndroid Build Coastguard Worker // and{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1372*03ce13f7SAndroid Build Coastguard Worker //
1373*03ce13f7SAndroid Build Coastguard Worker // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1374*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1375*03ce13f7SAndroid Build Coastguard Worker constexpr const char *AndName = "and";
1376*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT And = 0; // 0000
1377*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, And, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1378*03ce13f7SAndroid Build Coastguard Worker AndName);
1379*03ce13f7SAndroid Build Coastguard Worker }
1380*03ce13f7SAndroid Build Coastguard Worker
b(Label * L,CondARM32::Cond Cond)1381*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) {
1382*03ce13f7SAndroid Build Coastguard Worker emitBranch(L, Cond, false);
1383*03ce13f7SAndroid Build Coastguard Worker }
1384*03ce13f7SAndroid Build Coastguard Worker
bkpt(uint16_t Imm16)1385*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::bkpt(uint16_t Imm16) {
1386*03ce13f7SAndroid Build Coastguard Worker // BKPT - ARM section A*.8.24 - encoding A1:
1387*03ce13f7SAndroid Build Coastguard Worker // bkpt #<Imm16>
1388*03ce13f7SAndroid Build Coastguard Worker //
1389*03ce13f7SAndroid Build Coastguard Worker // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16
1390*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 |
1391*03ce13f7SAndroid Build Coastguard Worker ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf);
1392*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1393*03ce13f7SAndroid Build Coastguard Worker }
1394*03ce13f7SAndroid Build Coastguard Worker
bic(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1395*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::bic(const Operand *OpRd, const Operand *OpRn,
1396*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1397*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1398*03ce13f7SAndroid Build Coastguard Worker // BIC (register) - ARM section A8.8.22, encoding A1:
1399*03ce13f7SAndroid Build Coastguard Worker // bic{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1400*03ce13f7SAndroid Build Coastguard Worker //
1401*03ce13f7SAndroid Build Coastguard Worker // cccc0001110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1402*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1403*03ce13f7SAndroid Build Coastguard Worker //
1404*03ce13f7SAndroid Build Coastguard Worker // BIC (immediate) - ARM section A8.8.21, encoding A1:
1405*03ce13f7SAndroid Build Coastguard Worker // bic{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1406*03ce13f7SAndroid Build Coastguard Worker //
1407*03ce13f7SAndroid Build Coastguard Worker // cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn,
1408*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1409*03ce13f7SAndroid Build Coastguard Worker constexpr const char *BicName = "bic";
1410*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT BicOpcode = B3 | B2 | B1; // i.e. 1110
1411*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, BicOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1412*03ce13f7SAndroid Build Coastguard Worker BicName);
1413*03ce13f7SAndroid Build Coastguard Worker }
1414*03ce13f7SAndroid Build Coastguard Worker
bl(const ConstantRelocatable * Target)1415*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::bl(const ConstantRelocatable *Target) {
1416*03ce13f7SAndroid Build Coastguard Worker // BL (immediate) - ARM section A8.8.25, encoding A1:
1417*03ce13f7SAndroid Build Coastguard Worker // bl<c> <label>
1418*03ce13f7SAndroid Build Coastguard Worker //
1419*03ce13f7SAndroid Build Coastguard Worker // cccc1011iiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond (not currently allowed)
1420*03ce13f7SAndroid Build Coastguard Worker // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to.
1421*03ce13f7SAndroid Build Coastguard Worker emitFixup(createBlFixup(Target));
1422*03ce13f7SAndroid Build Coastguard Worker constexpr CondARM32::Cond Cond = CondARM32::AL;
1423*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Immed = 0;
1424*03ce13f7SAndroid Build Coastguard Worker constexpr bool Link = true;
1425*03ce13f7SAndroid Build Coastguard Worker emitType05(Cond, Immed, Link);
1426*03ce13f7SAndroid Build Coastguard Worker }
1427*03ce13f7SAndroid Build Coastguard Worker
blx(const Operand * Target)1428*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::blx(const Operand *Target) {
1429*03ce13f7SAndroid Build Coastguard Worker // BLX (register) - ARM section A8.8.26, encoding A1:
1430*03ce13f7SAndroid Build Coastguard Worker // blx<c> <Rm>
1431*03ce13f7SAndroid Build Coastguard Worker //
1432*03ce13f7SAndroid Build Coastguard Worker // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed)
1433*03ce13f7SAndroid Build Coastguard Worker // and mmmm=Rm.
1434*03ce13f7SAndroid Build Coastguard Worker constexpr const char *BlxName = "Blx";
1435*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(Target, "Rm", BlxName);
1436*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", BlxName);
1437*03ce13f7SAndroid Build Coastguard Worker constexpr CondARM32::Cond Cond = CondARM32::AL;
1438*03ce13f7SAndroid Build Coastguard Worker int32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 |
1439*03ce13f7SAndroid Build Coastguard Worker (0xfff << 8) | B5 | B4 | (Rm << kRmShift);
1440*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1441*03ce13f7SAndroid Build Coastguard Worker }
1442*03ce13f7SAndroid Build Coastguard Worker
bx(RegARM32::GPRRegister Rm,CondARM32::Cond Cond)1443*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
1444*03ce13f7SAndroid Build Coastguard Worker // BX - ARM section A8.8.27, encoding A1:
1445*03ce13f7SAndroid Build Coastguard Worker // bx<c> <Rm>
1446*03ce13f7SAndroid Build Coastguard Worker //
1447*03ce13f7SAndroid Build Coastguard Worker // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond.
1448*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1449*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 |
1450*03ce13f7SAndroid Build Coastguard Worker B21 | (0xfff << 8) | B4 |
1451*03ce13f7SAndroid Build Coastguard Worker (encodeGPRRegister(Rm) << kRmShift);
1452*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1453*03ce13f7SAndroid Build Coastguard Worker }
1454*03ce13f7SAndroid Build Coastguard Worker
clz(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1455*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::clz(const Operand *OpRd, const Operand *OpSrc,
1456*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1457*03ce13f7SAndroid Build Coastguard Worker // CLZ - ARM section A8.8.33, encoding A1:
1458*03ce13f7SAndroid Build Coastguard Worker // clz<c> <Rd> <Rm>
1459*03ce13f7SAndroid Build Coastguard Worker //
1460*03ce13f7SAndroid Build Coastguard Worker // cccc000101101111dddd11110001mmmm where cccc=Cond, dddd=Rd, and mmmm=Rm.
1461*03ce13f7SAndroid Build Coastguard Worker constexpr const char *ClzName = "clz";
1462*03ce13f7SAndroid Build Coastguard Worker constexpr const char *RdName = "Rd";
1463*03ce13f7SAndroid Build Coastguard Worker constexpr const char *RmName = "Rm";
1464*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, RdName, ClzName);
1465*03ce13f7SAndroid Build Coastguard Worker assert(Rd < RegARM32::getNumGPRegs());
1466*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, RdName, ClzName);
1467*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpSrc, RmName, ClzName);
1468*03ce13f7SAndroid Build Coastguard Worker assert(Rm < RegARM32::getNumGPRegs());
1469*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, RmName, ClzName);
1470*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1471*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT PredefinedBits =
1472*03ce13f7SAndroid Build Coastguard Worker B24 | B22 | B21 | (0xF << 16) | (0xf << 8) | B4;
1473*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = PredefinedBits | (Cond << kConditionShift) |
1474*03ce13f7SAndroid Build Coastguard Worker (Rd << kRdShift) | (Rm << kRmShift);
1475*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1476*03ce13f7SAndroid Build Coastguard Worker }
1477*03ce13f7SAndroid Build Coastguard Worker
cmn(const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)1478*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::cmn(const Operand *OpRn, const Operand *OpSrc1,
1479*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1480*03ce13f7SAndroid Build Coastguard Worker // CMN (immediate) - ARM section A8.8.34, encoding A1:
1481*03ce13f7SAndroid Build Coastguard Worker // cmn<c> <Rn>, #<RotatedImm8>
1482*03ce13f7SAndroid Build Coastguard Worker //
1483*03ce13f7SAndroid Build Coastguard Worker // cccc00110111nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1484*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1485*03ce13f7SAndroid Build Coastguard Worker //
1486*03ce13f7SAndroid Build Coastguard Worker // CMN (register) - ARM section A8.8.35, encodeing A1:
1487*03ce13f7SAndroid Build Coastguard Worker // cmn<c> <Rn>, <Rm>{, <shift>}
1488*03ce13f7SAndroid Build Coastguard Worker //
1489*03ce13f7SAndroid Build Coastguard Worker // cccc00010111nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
1490*03ce13f7SAndroid Build Coastguard Worker // iiiii=Shift, and tt=ShiftKind.
1491*03ce13f7SAndroid Build Coastguard Worker constexpr const char *CmnName = "cmn";
1492*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT CmnOpcode = B3 | B1 | B0; // ie. 1011
1493*03ce13f7SAndroid Build Coastguard Worker emitCompareOp(Cond, CmnOpcode, OpRn, OpSrc1, CmnName);
1494*03ce13f7SAndroid Build Coastguard Worker }
1495*03ce13f7SAndroid Build Coastguard Worker
cmp(const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)1496*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1,
1497*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1498*03ce13f7SAndroid Build Coastguard Worker // CMP (register) - ARM section A8.8.38, encoding A1:
1499*03ce13f7SAndroid Build Coastguard Worker // cmp<c> <Rn>, <Rm>{, <shift>}
1500*03ce13f7SAndroid Build Coastguard Worker //
1501*03ce13f7SAndroid Build Coastguard Worker // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
1502*03ce13f7SAndroid Build Coastguard Worker // iiiii=Shift, and tt=ShiftKind.
1503*03ce13f7SAndroid Build Coastguard Worker //
1504*03ce13f7SAndroid Build Coastguard Worker // CMP (immediate) - ARM section A8.8.37
1505*03ce13f7SAndroid Build Coastguard Worker // cmp<c: <Rn>, #<RotatedImm8>
1506*03ce13f7SAndroid Build Coastguard Worker //
1507*03ce13f7SAndroid Build Coastguard Worker // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1508*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1509*03ce13f7SAndroid Build Coastguard Worker constexpr const char *CmpName = "cmp";
1510*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT CmpOpcode = B3 | B1; // ie. 1010
1511*03ce13f7SAndroid Build Coastguard Worker emitCompareOp(Cond, CmpOpcode, OpRn, OpSrc1, CmpName);
1512*03ce13f7SAndroid Build Coastguard Worker }
1513*03ce13f7SAndroid Build Coastguard Worker
dmb(IValueT Option)1514*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::dmb(IValueT Option) {
1515*03ce13f7SAndroid Build Coastguard Worker // DMB - ARM section A8.8.43, encoding A1:
1516*03ce13f7SAndroid Build Coastguard Worker // dmb <option>
1517*03ce13f7SAndroid Build Coastguard Worker //
1518*03ce13f7SAndroid Build Coastguard Worker // 1111010101111111111100000101xxxx where xxxx=Option.
1519*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(4, Option) && "Bad dmb option");
1520*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
1521*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(CondARM32::kNone) << kConditionShift) | B26 | B24 | B22 |
1522*03ce13f7SAndroid Build Coastguard Worker B21 | B20 | B19 | B18 | B17 | B16 | B15 | B14 | B13 | B12 | B6 | B4 |
1523*03ce13f7SAndroid Build Coastguard Worker Option;
1524*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1525*03ce13f7SAndroid Build Coastguard Worker }
1526*03ce13f7SAndroid Build Coastguard Worker
eor(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1527*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn,
1528*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1529*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1530*03ce13f7SAndroid Build Coastguard Worker // EOR (register) - ARM section A*.8.47, encoding A1:
1531*03ce13f7SAndroid Build Coastguard Worker // eor{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1532*03ce13f7SAndroid Build Coastguard Worker //
1533*03ce13f7SAndroid Build Coastguard Worker // cccc0000001snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1534*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1535*03ce13f7SAndroid Build Coastguard Worker //
1536*03ce13f7SAndroid Build Coastguard Worker // EOR (Immediate) - ARM section A8.*.46, encoding A1:
1537*03ce13f7SAndroid Build Coastguard Worker // eor{s}<c> <Rd>, <Rn>, #RotatedImm8
1538*03ce13f7SAndroid Build Coastguard Worker //
1539*03ce13f7SAndroid Build Coastguard Worker // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1540*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1541*03ce13f7SAndroid Build Coastguard Worker constexpr const char *EorName = "eor";
1542*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT EorOpcode = B0; // 0001
1543*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1544*03ce13f7SAndroid Build Coastguard Worker EorName);
1545*03ce13f7SAndroid Build Coastguard Worker }
1546*03ce13f7SAndroid Build Coastguard Worker
ldr(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1547*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
1548*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
1549*03ce13f7SAndroid Build Coastguard Worker constexpr const char *LdrName = "ldr";
1550*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = true;
1551*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", LdrName);
1552*03ce13f7SAndroid Build Coastguard Worker const Type Ty = OpRt->getType();
1553*03ce13f7SAndroid Build Coastguard Worker switch (Ty) {
1554*03ce13f7SAndroid Build Coastguard Worker case IceType_i64:
1555*03ce13f7SAndroid Build Coastguard Worker // LDRD is not implemented because target lowering handles i64 and double by
1556*03ce13f7SAndroid Build Coastguard Worker // using two (32-bit) load instructions. Note: Intentionally drop to default
1557*03ce13f7SAndroid Build Coastguard Worker // case.
1558*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1559*03ce13f7SAndroid Build Coastguard Worker " not implemented");
1560*03ce13f7SAndroid Build Coastguard Worker default:
1561*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
1562*03ce13f7SAndroid Build Coastguard Worker " not allowed");
1563*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
1564*03ce13f7SAndroid Build Coastguard Worker case IceType_i8: {
1565*03ce13f7SAndroid Build Coastguard Worker // LDRB (immediate) - ARM section A8.8.68, encoding A1:
1566*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1567*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1568*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1569*03ce13f7SAndroid Build Coastguard Worker //
1570*03ce13f7SAndroid Build Coastguard Worker // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1571*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
1572*03ce13f7SAndroid Build Coastguard Worker // pu0w0nnnn0000iiiiiiiiiiii=Address.
1573*03ce13f7SAndroid Build Coastguard Worker //
1574*03ce13f7SAndroid Build Coastguard Worker // LDRB (register) - ARM section A8.8.66, encoding A1:
1575*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
1576*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
1577*03ce13f7SAndroid Build Coastguard Worker //
1578*03ce13f7SAndroid Build Coastguard Worker // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1579*03ce13f7SAndroid Build Coastguard Worker // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1580*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsByte = true;
1581*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1582*03ce13f7SAndroid Build Coastguard Worker return;
1583*03ce13f7SAndroid Build Coastguard Worker }
1584*03ce13f7SAndroid Build Coastguard Worker case IceType_i16: {
1585*03ce13f7SAndroid Build Coastguard Worker // LDRH (immediate) - ARM section A8.8.80, encoding A1:
1586*03ce13f7SAndroid Build Coastguard Worker // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
1587*03ce13f7SAndroid Build Coastguard Worker // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8>
1588*03ce13f7SAndroid Build Coastguard Worker // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1589*03ce13f7SAndroid Build Coastguard Worker //
1590*03ce13f7SAndroid Build Coastguard Worker // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1591*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
1592*03ce13f7SAndroid Build Coastguard Worker // pu0w0nnnn0000iiiiiiiiiiii=Address.
1593*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Ldrh = "ldrh";
1594*03ce13f7SAndroid Build Coastguard Worker emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh);
1595*03ce13f7SAndroid Build Coastguard Worker return;
1596*03ce13f7SAndroid Build Coastguard Worker }
1597*03ce13f7SAndroid Build Coastguard Worker case IceType_i32: {
1598*03ce13f7SAndroid Build Coastguard Worker // LDR (immediate) - ARM section A8.8.63, encoding A1:
1599*03ce13f7SAndroid Build Coastguard Worker // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1600*03ce13f7SAndroid Build Coastguard Worker // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1601*03ce13f7SAndroid Build Coastguard Worker // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1602*03ce13f7SAndroid Build Coastguard Worker //
1603*03ce13f7SAndroid Build Coastguard Worker // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1604*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
1605*03ce13f7SAndroid Build Coastguard Worker //
1606*03ce13f7SAndroid Build Coastguard Worker // LDR (register) - ARM section A8.8.70, encoding A1:
1607*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
1608*03ce13f7SAndroid Build Coastguard Worker // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>}
1609*03ce13f7SAndroid Build Coastguard Worker //
1610*03ce13f7SAndroid Build Coastguard Worker // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
1611*03ce13f7SAndroid Build Coastguard Worker // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
1612*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsByte = false;
1613*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
1614*03ce13f7SAndroid Build Coastguard Worker return;
1615*03ce13f7SAndroid Build Coastguard Worker }
1616*03ce13f7SAndroid Build Coastguard Worker }
1617*03ce13f7SAndroid Build Coastguard Worker }
1618*03ce13f7SAndroid Build Coastguard Worker
emitMemExOp(CondARM32::Cond Cond,Type Ty,bool IsLoad,const Operand * OpRd,IValueT Rt,const Operand * OpAddress,const TargetInfo & TInfo,const char * InstName)1619*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad,
1620*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRd, IValueT Rt,
1621*03ce13f7SAndroid Build Coastguard Worker const Operand *OpAddress,
1622*03ce13f7SAndroid Build Coastguard Worker const TargetInfo &TInfo,
1623*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
1624*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
1625*03ce13f7SAndroid Build Coastguard Worker IValueT MemExOpcode = IsLoad ? B0 : 0;
1626*03ce13f7SAndroid Build Coastguard Worker switch (Ty) {
1627*03ce13f7SAndroid Build Coastguard Worker default:
1628*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": Type " +
1629*03ce13f7SAndroid Build Coastguard Worker typeString(Ty) + " not allowed");
1630*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
1631*03ce13f7SAndroid Build Coastguard Worker case IceType_i8:
1632*03ce13f7SAndroid Build Coastguard Worker MemExOpcode |= B2;
1633*03ce13f7SAndroid Build Coastguard Worker break;
1634*03ce13f7SAndroid Build Coastguard Worker case IceType_i16:
1635*03ce13f7SAndroid Build Coastguard Worker MemExOpcode |= B2 | B1;
1636*03ce13f7SAndroid Build Coastguard Worker break;
1637*03ce13f7SAndroid Build Coastguard Worker case IceType_i32:
1638*03ce13f7SAndroid Build Coastguard Worker break;
1639*03ce13f7SAndroid Build Coastguard Worker case IceType_i64:
1640*03ce13f7SAndroid Build Coastguard Worker MemExOpcode |= B1;
1641*03ce13f7SAndroid Build Coastguard Worker }
1642*03ce13f7SAndroid Build Coastguard Worker IValueT AddressRn;
1643*03ce13f7SAndroid Build Coastguard Worker if (encodeAddress(OpAddress, AddressRn, TInfo, NoImmOffsetAddress) !=
1644*03ce13f7SAndroid Build Coastguard Worker EncodedAsImmRegOffset)
1645*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
1646*03ce13f7SAndroid Build Coastguard Worker ": Can't extract Rn from address");
1647*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsAbsoluteUint(3, MemExOpcode));
1648*03ce13f7SAndroid Build Coastguard Worker assert(Rd < RegARM32::getNumGPRegs());
1649*03ce13f7SAndroid Build Coastguard Worker assert(Rt < RegARM32::getNumGPRegs());
1650*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1651*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 |
1652*03ce13f7SAndroid Build Coastguard Worker B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) |
1653*03ce13f7SAndroid Build Coastguard Worker AddressRn | (Rd << kRdShift) | (Rt << kRmShift);
1654*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1655*03ce13f7SAndroid Build Coastguard Worker return;
1656*03ce13f7SAndroid Build Coastguard Worker }
1657*03ce13f7SAndroid Build Coastguard Worker
ldrex(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1658*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress,
1659*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
1660*03ce13f7SAndroid Build Coastguard Worker // LDREXB - ARM section A8.8.76, encoding A1:
1661*03ce13f7SAndroid Build Coastguard Worker // ldrexb<c> <Rt>, [<Rn>]
1662*03ce13f7SAndroid Build Coastguard Worker //
1663*03ce13f7SAndroid Build Coastguard Worker // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1664*03ce13f7SAndroid Build Coastguard Worker //
1665*03ce13f7SAndroid Build Coastguard Worker // LDREXH - ARM section A8.8.78, encoding A1:
1666*03ce13f7SAndroid Build Coastguard Worker // ldrexh<c> <Rt>, [<Rn>]
1667*03ce13f7SAndroid Build Coastguard Worker //
1668*03ce13f7SAndroid Build Coastguard Worker // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1669*03ce13f7SAndroid Build Coastguard Worker //
1670*03ce13f7SAndroid Build Coastguard Worker // LDREX - ARM section A8.8.75, encoding A1:
1671*03ce13f7SAndroid Build Coastguard Worker // ldrex<c> <Rt>, [<Rn>]
1672*03ce13f7SAndroid Build Coastguard Worker //
1673*03ce13f7SAndroid Build Coastguard Worker // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1674*03ce13f7SAndroid Build Coastguard Worker //
1675*03ce13f7SAndroid Build Coastguard Worker // LDREXD - ARM section A8.
1676*03ce13f7SAndroid Build Coastguard Worker // ldrexd<c> <Rt>, [<Rn>]
1677*03ce13f7SAndroid Build Coastguard Worker //
1678*03ce13f7SAndroid Build Coastguard Worker // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn.
1679*03ce13f7SAndroid Build Coastguard Worker constexpr const char *LdrexName = "ldrex";
1680*03ce13f7SAndroid Build Coastguard Worker const Type Ty = OpRt->getType();
1681*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = true;
1682*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rm = RegARM32::Encoded_Reg_pc;
1683*03ce13f7SAndroid Build Coastguard Worker emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName);
1684*03ce13f7SAndroid Build Coastguard Worker }
1685*03ce13f7SAndroid Build Coastguard Worker
emitShift(const CondARM32::Cond Cond,const OperandARM32::ShiftKind Shift,const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,const bool SetFlags,const char * InstName)1686*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
1687*03ce13f7SAndroid Build Coastguard Worker const OperandARM32::ShiftKind Shift,
1688*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRd, const Operand *OpRm,
1689*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, const bool SetFlags,
1690*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
1691*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
1692*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
1693*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpRm, "Rm", InstName);
1694*03ce13f7SAndroid Build Coastguard Worker IValueT Value;
1695*03ce13f7SAndroid Build Coastguard Worker switch (encodeOperand(OpSrc1, Value, WantGPRegs)) {
1696*03ce13f7SAndroid Build Coastguard Worker default:
1697*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) +
1698*03ce13f7SAndroid Build Coastguard Worker ": Last operand not understood");
1699*03ce13f7SAndroid Build Coastguard Worker case EncodedAsShiftImm5: {
1700*03ce13f7SAndroid Build Coastguard Worker // XXX (immediate)
1701*03ce13f7SAndroid Build Coastguard Worker // xxx{s}<c> <Rd>, <Rm>, #imm5
1702*03ce13f7SAndroid Build Coastguard Worker //
1703*03ce13f7SAndroid Build Coastguard Worker // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
1704*03ce13f7SAndroid Build Coastguard Worker // iiiii=imm5, and mmmm=Rm.
1705*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rn = 0; // Rn field is not used.
1706*03ce13f7SAndroid Build Coastguard Worker Value = Value | (Rm << kRmShift) | (Shift << kShiftShift);
1707*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
1708*03ce13f7SAndroid Build Coastguard Worker Value, RdIsPcAndSetFlags, InstName);
1709*03ce13f7SAndroid Build Coastguard Worker return;
1710*03ce13f7SAndroid Build Coastguard Worker }
1711*03ce13f7SAndroid Build Coastguard Worker case EncodedAsRegister: {
1712*03ce13f7SAndroid Build Coastguard Worker // XXX (register)
1713*03ce13f7SAndroid Build Coastguard Worker // xxx{S}<c> <Rd>, <Rm>, <Rs>
1714*03ce13f7SAndroid Build Coastguard Worker //
1715*03ce13f7SAndroid Build Coastguard Worker // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
1716*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, and ssss=Rs.
1717*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rn = 0; // Rn field is not used.
1718*03ce13f7SAndroid Build Coastguard Worker IValueT Rs = encodeGPRegister(OpSrc1, "Rs", InstName);
1719*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, "Rd", InstName);
1720*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", InstName);
1721*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rs, "Rs", InstName);
1722*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
1723*03ce13f7SAndroid Build Coastguard Worker encodeShiftRotateReg(Rm, Shift, Rs), NoChecks, InstName);
1724*03ce13f7SAndroid Build Coastguard Worker return;
1725*03ce13f7SAndroid Build Coastguard Worker }
1726*03ce13f7SAndroid Build Coastguard Worker }
1727*03ce13f7SAndroid Build Coastguard Worker }
1728*03ce13f7SAndroid Build Coastguard Worker
asr(const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1729*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::asr(const Operand *OpRd, const Operand *OpRm,
1730*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1731*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1732*03ce13f7SAndroid Build Coastguard Worker constexpr const char *AsrName = "asr";
1733*03ce13f7SAndroid Build Coastguard Worker emitShift(Cond, OperandARM32::ASR, OpRd, OpRm, OpSrc1, SetFlags, AsrName);
1734*03ce13f7SAndroid Build Coastguard Worker }
1735*03ce13f7SAndroid Build Coastguard Worker
lsl(const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1736*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm,
1737*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1738*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1739*03ce13f7SAndroid Build Coastguard Worker constexpr const char *LslName = "lsl";
1740*03ce13f7SAndroid Build Coastguard Worker emitShift(Cond, OperandARM32::LSL, OpRd, OpRm, OpSrc1, SetFlags, LslName);
1741*03ce13f7SAndroid Build Coastguard Worker }
1742*03ce13f7SAndroid Build Coastguard Worker
lsr(const Operand * OpRd,const Operand * OpRm,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1743*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::lsr(const Operand *OpRd, const Operand *OpRm,
1744*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1745*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1746*03ce13f7SAndroid Build Coastguard Worker constexpr const char *LsrName = "lsr";
1747*03ce13f7SAndroid Build Coastguard Worker emitShift(Cond, OperandARM32::LSR, OpRd, OpRm, OpSrc1, SetFlags, LsrName);
1748*03ce13f7SAndroid Build Coastguard Worker }
1749*03ce13f7SAndroid Build Coastguard Worker
mov(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1750*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
1751*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1752*03ce13f7SAndroid Build Coastguard Worker // MOV (register) - ARM section A8.8.104, encoding A1:
1753*03ce13f7SAndroid Build Coastguard Worker // mov{S}<c> <Rd>, <Rn>
1754*03ce13f7SAndroid Build Coastguard Worker //
1755*03ce13f7SAndroid Build Coastguard Worker // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
1756*03ce13f7SAndroid Build Coastguard Worker // and nnnn=Rn.
1757*03ce13f7SAndroid Build Coastguard Worker //
1758*03ce13f7SAndroid Build Coastguard Worker // MOV (immediate) - ARM section A8.8.102, encoding A1:
1759*03ce13f7SAndroid Build Coastguard Worker // mov{S}<c> <Rd>, #<RotatedImm8>
1760*03ce13f7SAndroid Build Coastguard Worker //
1761*03ce13f7SAndroid Build Coastguard Worker // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd,
1762*03ce13f7SAndroid Build Coastguard Worker // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this
1763*03ce13f7SAndroid Build Coastguard Worker // assembler.
1764*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MovName = "mov";
1765*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", MovName);
1766*03ce13f7SAndroid Build Coastguard Worker constexpr bool SetFlags = false;
1767*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rn = 0;
1768*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT MovOpcode = B3 | B2 | B0; // 1101.
1769*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, MovOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags,
1770*03ce13f7SAndroid Build Coastguard Worker MovName);
1771*03ce13f7SAndroid Build Coastguard Worker }
1772*03ce13f7SAndroid Build Coastguard Worker
emitMovwt(CondARM32::Cond Cond,bool IsMovW,const Operand * OpRd,const Operand * OpSrc,const char * MovName)1773*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitMovwt(CondARM32::Cond Cond, bool IsMovW,
1774*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRd, const Operand *OpSrc,
1775*03ce13f7SAndroid Build Coastguard Worker const char *MovName) {
1776*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = B25 | B24 | (IsMovW ? 0 : B22);
1777*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", MovName);
1778*03ce13f7SAndroid Build Coastguard Worker IValueT Imm16;
1779*03ce13f7SAndroid Build Coastguard Worker if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) {
1780*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMoveFixup(IsMovW, Src));
1781*03ce13f7SAndroid Build Coastguard Worker // Use 0 for the lower 16 bits of the relocatable, and add a fixup to
1782*03ce13f7SAndroid Build Coastguard Worker // install the correct bits.
1783*03ce13f7SAndroid Build Coastguard Worker Imm16 = 0;
1784*03ce13f7SAndroid Build Coastguard Worker } else if (encodeOperand(OpSrc, Imm16, WantGPRegs) != EncodedAsConstI32) {
1785*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(MovName) + ": Not i32 constant");
1786*03ce13f7SAndroid Build Coastguard Worker }
1787*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
1788*03ce13f7SAndroid Build Coastguard Worker if (!Utils::IsAbsoluteUint(16, Imm16))
1789*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(MovName) + ": Constant not i16");
1790*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode |
1791*03ce13f7SAndroid Build Coastguard Worker ((Imm16 >> 12) << 16) | Rd << kRdShift |
1792*03ce13f7SAndroid Build Coastguard Worker (Imm16 & 0xfff);
1793*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1794*03ce13f7SAndroid Build Coastguard Worker }
1795*03ce13f7SAndroid Build Coastguard Worker
movw(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1796*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
1797*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1798*03ce13f7SAndroid Build Coastguard Worker // MOV (immediate) - ARM section A8.8.102, encoding A2:
1799*03ce13f7SAndroid Build Coastguard Worker // movw<c> <Rd>, #<imm16>
1800*03ce13f7SAndroid Build Coastguard Worker //
1801*03ce13f7SAndroid Build Coastguard Worker // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
1802*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiiiiiii=imm16.
1803*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MovwName = "movw";
1804*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsMovW = true;
1805*03ce13f7SAndroid Build Coastguard Worker emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovwName);
1806*03ce13f7SAndroid Build Coastguard Worker }
1807*03ce13f7SAndroid Build Coastguard Worker
movt(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1808*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc,
1809*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1810*03ce13f7SAndroid Build Coastguard Worker // MOVT - ARM section A8.8.106, encoding A1:
1811*03ce13f7SAndroid Build Coastguard Worker // movt<c> <Rd>, #<imm16>
1812*03ce13f7SAndroid Build Coastguard Worker //
1813*03ce13f7SAndroid Build Coastguard Worker // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
1814*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiiiiiii=imm16.
1815*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MovtName = "movt";
1816*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsMovW = false;
1817*03ce13f7SAndroid Build Coastguard Worker emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovtName);
1818*03ce13f7SAndroid Build Coastguard Worker }
1819*03ce13f7SAndroid Build Coastguard Worker
mvn(const Operand * OpRd,const Operand * OpSrc,CondARM32::Cond Cond)1820*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc,
1821*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1822*03ce13f7SAndroid Build Coastguard Worker // MVN (immediate) - ARM section A8.8.115, encoding A1:
1823*03ce13f7SAndroid Build Coastguard Worker // mvn{s}<c> <Rd>, #<const>
1824*03ce13f7SAndroid Build Coastguard Worker //
1825*03ce13f7SAndroid Build Coastguard Worker // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd,
1826*03ce13f7SAndroid Build Coastguard Worker // and iiiiiiiiiiii=const
1827*03ce13f7SAndroid Build Coastguard Worker //
1828*03ce13f7SAndroid Build Coastguard Worker // MVN (register) - ARM section A8.8.116, encoding A1:
1829*03ce13f7SAndroid Build Coastguard Worker // mvn{s}<c> <Rd>, <Rm>{, <shift>
1830*03ce13f7SAndroid Build Coastguard Worker //
1831*03ce13f7SAndroid Build Coastguard Worker // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd,
1832*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind.
1833*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MvnName = "mvn";
1834*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", MvnName);
1835*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111
1836*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rn = 0;
1837*03ce13f7SAndroid Build Coastguard Worker constexpr bool SetFlags = false;
1838*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags,
1839*03ce13f7SAndroid Build Coastguard Worker MvnName);
1840*03ce13f7SAndroid Build Coastguard Worker }
1841*03ce13f7SAndroid Build Coastguard Worker
nop()1842*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::nop() {
1843*03ce13f7SAndroid Build Coastguard Worker // NOP - Section A8.8.119, encoding A1:
1844*03ce13f7SAndroid Build Coastguard Worker // nop<c>
1845*03ce13f7SAndroid Build Coastguard Worker //
1846*03ce13f7SAndroid Build Coastguard Worker // cccc0011001000001111000000000000 where cccc=Cond.
1847*03ce13f7SAndroid Build Coastguard Worker constexpr CondARM32::Cond Cond = CondARM32::AL;
1848*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B25 |
1849*03ce13f7SAndroid Build Coastguard Worker B24 | B21 | B15 | B14 | B13 | B12;
1850*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
1851*03ce13f7SAndroid Build Coastguard Worker }
1852*03ce13f7SAndroid Build Coastguard Worker
sbc(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1853*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn,
1854*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1855*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1856*03ce13f7SAndroid Build Coastguard Worker // SBC (register) - ARM section 18.8.162, encoding A1:
1857*03ce13f7SAndroid Build Coastguard Worker // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
1858*03ce13f7SAndroid Build Coastguard Worker //
1859*03ce13f7SAndroid Build Coastguard Worker // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1860*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
1861*03ce13f7SAndroid Build Coastguard Worker //
1862*03ce13f7SAndroid Build Coastguard Worker // SBC (Immediate) - ARM section A8.8.161, encoding A1:
1863*03ce13f7SAndroid Build Coastguard Worker // sbc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1864*03ce13f7SAndroid Build Coastguard Worker //
1865*03ce13f7SAndroid Build Coastguard Worker // cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1866*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
1867*03ce13f7SAndroid Build Coastguard Worker constexpr const char *SbcName = "sbc";
1868*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT SbcOpcode = B2 | B1; // 0110
1869*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, SbcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
1870*03ce13f7SAndroid Build Coastguard Worker SbcName);
1871*03ce13f7SAndroid Build Coastguard Worker }
1872*03ce13f7SAndroid Build Coastguard Worker
sdiv(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)1873*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn,
1874*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, CondARM32::Cond Cond) {
1875*03ce13f7SAndroid Build Coastguard Worker // SDIV - ARM section A8.8.165, encoding A1.
1876*03ce13f7SAndroid Build Coastguard Worker // sdiv<c> <Rd>, <Rn>, <Rm>
1877*03ce13f7SAndroid Build Coastguard Worker //
1878*03ce13f7SAndroid Build Coastguard Worker // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
1879*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm.
1880*03ce13f7SAndroid Build Coastguard Worker constexpr const char *SdivName = "sdiv";
1881*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", SdivName);
1882*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", SdivName);
1883*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpSrc1, "Rm", SdivName);
1884*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, "Rd", SdivName);
1885*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", SdivName);
1886*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", SdivName);
1887*03ce13f7SAndroid Build Coastguard Worker // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
1888*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT SdivOpcode = 0;
1889*03ce13f7SAndroid Build Coastguard Worker emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm);
1890*03ce13f7SAndroid Build Coastguard Worker }
1891*03ce13f7SAndroid Build Coastguard Worker
str(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1892*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
1893*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
1894*03ce13f7SAndroid Build Coastguard Worker constexpr const char *StrName = "str";
1895*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = false;
1896*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", StrName);
1897*03ce13f7SAndroid Build Coastguard Worker const Type Ty = OpRt->getType();
1898*03ce13f7SAndroid Build Coastguard Worker switch (Ty) {
1899*03ce13f7SAndroid Build Coastguard Worker case IceType_i64:
1900*03ce13f7SAndroid Build Coastguard Worker // STRD is not implemented because target lowering handles i64 and double by
1901*03ce13f7SAndroid Build Coastguard Worker // using two (32-bit) store instructions. Note: Intentionally drop to
1902*03ce13f7SAndroid Build Coastguard Worker // default case.
1903*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1904*03ce13f7SAndroid Build Coastguard Worker " not implemented");
1905*03ce13f7SAndroid Build Coastguard Worker default:
1906*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
1907*03ce13f7SAndroid Build Coastguard Worker " not allowed");
1908*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
1909*03ce13f7SAndroid Build Coastguard Worker case IceType_i8: {
1910*03ce13f7SAndroid Build Coastguard Worker // STRB (immediate) - ARM section A8.8.207, encoding A1:
1911*03ce13f7SAndroid Build Coastguard Worker // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1912*03ce13f7SAndroid Build Coastguard Worker // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1913*03ce13f7SAndroid Build Coastguard Worker // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1914*03ce13f7SAndroid Build Coastguard Worker //
1915*03ce13f7SAndroid Build Coastguard Worker // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1916*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiii=imm12, u=1 if +.
1917*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsByte = true;
1918*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1919*03ce13f7SAndroid Build Coastguard Worker return;
1920*03ce13f7SAndroid Build Coastguard Worker }
1921*03ce13f7SAndroid Build Coastguard Worker case IceType_i16: {
1922*03ce13f7SAndroid Build Coastguard Worker // STRH (immediate) - ARM section A8.*.217, encoding A1:
1923*03ce13f7SAndroid Build Coastguard Worker // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
1924*03ce13f7SAndroid Build Coastguard Worker // strh<c> <Rt>, [<Rn>], #+/-<Imm8>
1925*03ce13f7SAndroid Build Coastguard Worker // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
1926*03ce13f7SAndroid Build Coastguard Worker //
1927*03ce13f7SAndroid Build Coastguard Worker // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1928*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
1929*03ce13f7SAndroid Build Coastguard Worker // pu0w0nnnn0000iiiiiiiiiiii=Address.
1930*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Strh = "strh";
1931*03ce13f7SAndroid Build Coastguard Worker emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh);
1932*03ce13f7SAndroid Build Coastguard Worker return;
1933*03ce13f7SAndroid Build Coastguard Worker }
1934*03ce13f7SAndroid Build Coastguard Worker case IceType_i32: {
1935*03ce13f7SAndroid Build Coastguard Worker // Note: Handles i32 and float stores. Target lowering handles i64 and
1936*03ce13f7SAndroid Build Coastguard Worker // double by using two (32 bit) store instructions.
1937*03ce13f7SAndroid Build Coastguard Worker //
1938*03ce13f7SAndroid Build Coastguard Worker // STR (immediate) - ARM section A8.8.207, encoding A1:
1939*03ce13f7SAndroid Build Coastguard Worker // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
1940*03ce13f7SAndroid Build Coastguard Worker // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
1941*03ce13f7SAndroid Build Coastguard Worker // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
1942*03ce13f7SAndroid Build Coastguard Worker //
1943*03ce13f7SAndroid Build Coastguard Worker // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
1944*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiii=imm12, u=1 if +.
1945*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsByte = false;
1946*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
1947*03ce13f7SAndroid Build Coastguard Worker return;
1948*03ce13f7SAndroid Build Coastguard Worker }
1949*03ce13f7SAndroid Build Coastguard Worker }
1950*03ce13f7SAndroid Build Coastguard Worker }
1951*03ce13f7SAndroid Build Coastguard Worker
strex(const Operand * OpRd,const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)1952*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt,
1953*03ce13f7SAndroid Build Coastguard Worker const Operand *OpAddress, CondARM32::Cond Cond,
1954*03ce13f7SAndroid Build Coastguard Worker const TargetInfo &TInfo) {
1955*03ce13f7SAndroid Build Coastguard Worker // STREXB - ARM section A8.8.213, encoding A1:
1956*03ce13f7SAndroid Build Coastguard Worker // strexb<c> <Rd>, <Rt>, [<Rn>]
1957*03ce13f7SAndroid Build Coastguard Worker //
1958*03ce13f7SAndroid Build Coastguard Worker // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1959*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn.
1960*03ce13f7SAndroid Build Coastguard Worker //
1961*03ce13f7SAndroid Build Coastguard Worker // STREXH - ARM section A8.8.215, encoding A1:
1962*03ce13f7SAndroid Build Coastguard Worker // strexh<c> <Rd>, <Rt>, [<Rn>]
1963*03ce13f7SAndroid Build Coastguard Worker //
1964*03ce13f7SAndroid Build Coastguard Worker // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1965*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn.
1966*03ce13f7SAndroid Build Coastguard Worker //
1967*03ce13f7SAndroid Build Coastguard Worker // STREX - ARM section A8.8.212, encoding A1:
1968*03ce13f7SAndroid Build Coastguard Worker // strex<c> <Rd>, <Rt>, [<Rn>]
1969*03ce13f7SAndroid Build Coastguard Worker //
1970*03ce13f7SAndroid Build Coastguard Worker // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1971*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn.
1972*03ce13f7SAndroid Build Coastguard Worker //
1973*03ce13f7SAndroid Build Coastguard Worker // STREXD - ARM section A8.8.214, encoding A1:
1974*03ce13f7SAndroid Build Coastguard Worker // strexd<c> <Rd>, <Rt>, [<Rn>]
1975*03ce13f7SAndroid Build Coastguard Worker //
1976*03ce13f7SAndroid Build Coastguard Worker // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and
1977*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn.
1978*03ce13f7SAndroid Build Coastguard Worker constexpr const char *StrexName = "strex";
1979*03ce13f7SAndroid Build Coastguard Worker // Note: Rt uses Rm shift in encoding.
1980*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", StrexName);
1981*03ce13f7SAndroid Build Coastguard Worker const Type Ty = OpRt->getType();
1982*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = true;
1983*03ce13f7SAndroid Build Coastguard Worker emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName);
1984*03ce13f7SAndroid Build Coastguard Worker }
1985*03ce13f7SAndroid Build Coastguard Worker
orr(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)1986*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
1987*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
1988*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
1989*03ce13f7SAndroid Build Coastguard Worker // ORR (register) - ARM Section A8.8.123, encoding A1:
1990*03ce13f7SAndroid Build Coastguard Worker // orr{s}<c> <Rd>, <Rn>, <Rm>
1991*03ce13f7SAndroid Build Coastguard Worker //
1992*03ce13f7SAndroid Build Coastguard Worker // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
1993*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags.
1994*03ce13f7SAndroid Build Coastguard Worker //
1995*03ce13f7SAndroid Build Coastguard Worker // ORR (register) - ARM Section A8.8.123, encoding A1:
1996*03ce13f7SAndroid Build Coastguard Worker // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8>
1997*03ce13f7SAndroid Build Coastguard Worker //
1998*03ce13f7SAndroid Build Coastguard Worker // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
1999*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
2000*03ce13f7SAndroid Build Coastguard Worker constexpr const char *OrrName = "orr";
2001*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100
2002*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2003*03ce13f7SAndroid Build Coastguard Worker OrrName);
2004*03ce13f7SAndroid Build Coastguard Worker }
2005*03ce13f7SAndroid Build Coastguard Worker
pop(const Variable * OpRt,CondARM32::Cond Cond)2006*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::pop(const Variable *OpRt, CondARM32::Cond Cond) {
2007*03ce13f7SAndroid Build Coastguard Worker // POP - ARM section A8.8.132, encoding A2:
2008*03ce13f7SAndroid Build Coastguard Worker // pop<c> {Rt}
2009*03ce13f7SAndroid Build Coastguard Worker //
2010*03ce13f7SAndroid Build Coastguard Worker // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond.
2011*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Pop = "pop";
2012*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", Pop);
2013*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop);
2014*03ce13f7SAndroid Build Coastguard Worker // Same as load instruction.
2015*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = true;
2016*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsByte = false;
2017*03ce13f7SAndroid Build Coastguard Worker constexpr IOffsetT MaxOffset = (1 << 8) - 1;
2018*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT NoShiftRight = 0;
2019*03ce13f7SAndroid Build Coastguard Worker IValueT Address =
2020*03ce13f7SAndroid Build Coastguard Worker encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize,
2021*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem::PostIndex, MaxOffset, NoShiftRight);
2022*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
2023*03ce13f7SAndroid Build Coastguard Worker }
2024*03ce13f7SAndroid Build Coastguard Worker
popList(const IValueT Registers,CondARM32::Cond Cond)2025*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) {
2026*03ce13f7SAndroid Build Coastguard Worker // POP - ARM section A8.*.131, encoding A1:
2027*03ce13f7SAndroid Build Coastguard Worker // pop<c> <registers>
2028*03ce13f7SAndroid Build Coastguard Worker //
2029*03ce13f7SAndroid Build Coastguard Worker // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and
2030*03ce13f7SAndroid Build Coastguard Worker // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register).
2031*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = true;
2032*03ce13f7SAndroid Build Coastguard Worker emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers);
2033*03ce13f7SAndroid Build Coastguard Worker }
2034*03ce13f7SAndroid Build Coastguard Worker
push(const Operand * OpRt,CondARM32::Cond Cond)2035*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) {
2036*03ce13f7SAndroid Build Coastguard Worker // PUSH - ARM section A8.8.133, encoding A2:
2037*03ce13f7SAndroid Build Coastguard Worker // push<c> {Rt}
2038*03ce13f7SAndroid Build Coastguard Worker //
2039*03ce13f7SAndroid Build Coastguard Worker // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond.
2040*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Push = "push";
2041*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", Push);
2042*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push);
2043*03ce13f7SAndroid Build Coastguard Worker // Same as store instruction.
2044*03ce13f7SAndroid Build Coastguard Worker constexpr bool isLoad = false;
2045*03ce13f7SAndroid Build Coastguard Worker constexpr bool isByte = false;
2046*03ce13f7SAndroid Build Coastguard Worker constexpr IOffsetT MaxOffset = (1 << 8) - 1;
2047*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT NoShiftRight = 0;
2048*03ce13f7SAndroid Build Coastguard Worker IValueT Address =
2049*03ce13f7SAndroid Build Coastguard Worker encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize,
2050*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem::PreIndex, MaxOffset, NoShiftRight);
2051*03ce13f7SAndroid Build Coastguard Worker emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address);
2052*03ce13f7SAndroid Build Coastguard Worker }
2053*03ce13f7SAndroid Build Coastguard Worker
pushList(const IValueT Registers,CondARM32::Cond Cond)2054*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) {
2055*03ce13f7SAndroid Build Coastguard Worker // PUSH - ARM section A8.8.133, encoding A1:
2056*03ce13f7SAndroid Build Coastguard Worker // push<c> <Registers>
2057*03ce13f7SAndroid Build Coastguard Worker //
2058*03ce13f7SAndroid Build Coastguard Worker // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and
2059*03ce13f7SAndroid Build Coastguard Worker // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register).
2060*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLoad = false;
2061*03ce13f7SAndroid Build Coastguard Worker emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers);
2062*03ce13f7SAndroid Build Coastguard Worker }
2063*03ce13f7SAndroid Build Coastguard Worker
mla(const Operand * OpRd,const Operand * OpRn,const Operand * OpRm,const Operand * OpRa,CondARM32::Cond Cond)2064*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn,
2065*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRm, const Operand *OpRa,
2066*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2067*03ce13f7SAndroid Build Coastguard Worker // MLA - ARM section A8.8.114, encoding A1.
2068*03ce13f7SAndroid Build Coastguard Worker // mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra>
2069*03ce13f7SAndroid Build Coastguard Worker //
2070*03ce13f7SAndroid Build Coastguard Worker // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd,
2071*03ce13f7SAndroid Build Coastguard Worker // aaaa=Ra, mmmm=Rm, and nnnn=Rn.
2072*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MlaName = "mla";
2073*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", MlaName);
2074*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", MlaName);
2075*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpRm, "Rm", MlaName);
2076*03ce13f7SAndroid Build Coastguard Worker IValueT Ra = encodeGPRegister(OpRa, "Ra", MlaName);
2077*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, "Rd", MlaName);
2078*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", MlaName);
2079*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", MlaName);
2080*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Ra, "Ra", MlaName);
2081*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT MlaOpcode = B21;
2082*03ce13f7SAndroid Build Coastguard Worker constexpr bool SetFlags = true;
2083*03ce13f7SAndroid Build Coastguard Worker // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
2084*03ce13f7SAndroid Build Coastguard Worker emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, !SetFlags);
2085*03ce13f7SAndroid Build Coastguard Worker }
2086*03ce13f7SAndroid Build Coastguard Worker
mls(const Operand * OpRd,const Operand * OpRn,const Operand * OpRm,const Operand * OpRa,CondARM32::Cond Cond)2087*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::mls(const Operand *OpRd, const Operand *OpRn,
2088*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRm, const Operand *OpRa,
2089*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2090*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MlsName = "mls";
2091*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", MlsName);
2092*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", MlsName);
2093*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpRm, "Rm", MlsName);
2094*03ce13f7SAndroid Build Coastguard Worker IValueT Ra = encodeGPRegister(OpRa, "Ra", MlsName);
2095*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, "Rd", MlsName);
2096*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", MlsName);
2097*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", MlsName);
2098*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Ra, "Ra", MlsName);
2099*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT MlsOpcode = B22 | B21;
2100*03ce13f7SAndroid Build Coastguard Worker constexpr bool SetFlags = true;
2101*03ce13f7SAndroid Build Coastguard Worker // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
2102*03ce13f7SAndroid Build Coastguard Worker emitMulOp(Cond, MlsOpcode, Ra, Rd, Rn, Rm, !SetFlags);
2103*03ce13f7SAndroid Build Coastguard Worker }
2104*03ce13f7SAndroid Build Coastguard Worker
mul(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2105*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
2106*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
2107*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2108*03ce13f7SAndroid Build Coastguard Worker // MUL - ARM section A8.8.114, encoding A1.
2109*03ce13f7SAndroid Build Coastguard Worker // mul{s}<c> <Rd>, <Rn>, <Rm>
2110*03ce13f7SAndroid Build Coastguard Worker //
2111*03ce13f7SAndroid Build Coastguard Worker // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn,
2112*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, and s=SetFlags.
2113*03ce13f7SAndroid Build Coastguard Worker constexpr const char *MulName = "mul";
2114*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", MulName);
2115*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", MulName);
2116*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpSrc1, "Rm", MulName);
2117*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, "Rd", MulName);
2118*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", MulName);
2119*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", MulName);
2120*03ce13f7SAndroid Build Coastguard Worker // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
2121*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT MulOpcode = 0;
2122*03ce13f7SAndroid Build Coastguard Worker emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags);
2123*03ce13f7SAndroid Build Coastguard Worker }
2124*03ce13f7SAndroid Build Coastguard Worker
emitRdRm(CondARM32::Cond Cond,IValueT Opcode,const Operand * OpRd,const Operand * OpRm,const char * InstName)2125*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitRdRm(CondARM32::Cond Cond, IValueT Opcode,
2126*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRd, const Operand *OpRm,
2127*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
2128*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName);
2129*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpRm, "Rm", InstName);
2130*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding =
2131*03ce13f7SAndroid Build Coastguard Worker (Cond << kConditionShift) | Opcode | (Rd << kRdShift) | (Rm << kRmShift);
2132*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2133*03ce13f7SAndroid Build Coastguard Worker }
2134*03ce13f7SAndroid Build Coastguard Worker
rbit(const Operand * OpRd,const Operand * OpRm,CondARM32::Cond Cond)2135*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::rbit(const Operand *OpRd, const Operand *OpRm,
2136*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2137*03ce13f7SAndroid Build Coastguard Worker // RBIT - ARM section A8.8.144, encoding A1:
2138*03ce13f7SAndroid Build Coastguard Worker // rbit<c> <Rd>, <Rm>
2139*03ce13f7SAndroid Build Coastguard Worker //
2140*03ce13f7SAndroid Build Coastguard Worker // cccc011011111111dddd11110011mmmm where cccc=Cond, dddd=Rn, and mmmm=Rm.
2141*03ce13f7SAndroid Build Coastguard Worker constexpr const char *RbitName = "rev";
2142*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT RbitOpcode = B26 | B25 | B23 | B22 | B21 | B20 | B19 | B18 |
2143*03ce13f7SAndroid Build Coastguard Worker B17 | B16 | B11 | B10 | B9 | B8 | B5 | B4;
2144*03ce13f7SAndroid Build Coastguard Worker emitRdRm(Cond, RbitOpcode, OpRd, OpRm, RbitName);
2145*03ce13f7SAndroid Build Coastguard Worker }
2146*03ce13f7SAndroid Build Coastguard Worker
rev(const Operand * OpRd,const Operand * OpRm,CondARM32::Cond Cond)2147*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::rev(const Operand *OpRd, const Operand *OpRm,
2148*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2149*03ce13f7SAndroid Build Coastguard Worker // REV - ARM section A8.8.145, encoding A1:
2150*03ce13f7SAndroid Build Coastguard Worker // rev<c> <Rd>, <Rm>
2151*03ce13f7SAndroid Build Coastguard Worker //
2152*03ce13f7SAndroid Build Coastguard Worker // cccc011010111111dddd11110011mmmm where cccc=Cond, dddd=Rn, and mmmm=Rm.
2153*03ce13f7SAndroid Build Coastguard Worker constexpr const char *RevName = "rev";
2154*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT RevOpcode = B26 | B25 | B23 | B21 | B20 | B19 | B18 | B17 |
2155*03ce13f7SAndroid Build Coastguard Worker B16 | B11 | B10 | B9 | B8 | B5 | B4;
2156*03ce13f7SAndroid Build Coastguard Worker emitRdRm(Cond, RevOpcode, OpRd, OpRm, RevName);
2157*03ce13f7SAndroid Build Coastguard Worker }
2158*03ce13f7SAndroid Build Coastguard Worker
rsb(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2159*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::rsb(const Operand *OpRd, const Operand *OpRn,
2160*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
2161*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2162*03ce13f7SAndroid Build Coastguard Worker // RSB (immediate) - ARM section A8.8.152, encoding A1.
2163*03ce13f7SAndroid Build Coastguard Worker // rsb{s}<c> <Rd>, <Rn>, #<RotatedImm8>
2164*03ce13f7SAndroid Build Coastguard Worker //
2165*03ce13f7SAndroid Build Coastguard Worker // cccc0010011snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
2166*03ce13f7SAndroid Build Coastguard Worker // s=setFlags and iiiiiiiiiiii defines the RotatedImm8 value.
2167*03ce13f7SAndroid Build Coastguard Worker //
2168*03ce13f7SAndroid Build Coastguard Worker // RSB (register) - ARM section A8.8.163, encoding A1.
2169*03ce13f7SAndroid Build Coastguard Worker // rsb{s}<c> <Rd>, <Rn>, <Rm>{, <Shift>}
2170*03ce13f7SAndroid Build Coastguard Worker //
2171*03ce13f7SAndroid Build Coastguard Worker // cccc0000011snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2172*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=shift, tt==ShiftKind, and s=SetFlags.
2173*03ce13f7SAndroid Build Coastguard Worker constexpr const char *RsbName = "rsb";
2174*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT RsbOpcode = B1 | B0; // 0011
2175*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, RsbOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2176*03ce13f7SAndroid Build Coastguard Worker RsbName);
2177*03ce13f7SAndroid Build Coastguard Worker }
2178*03ce13f7SAndroid Build Coastguard Worker
rsc(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2179*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::rsc(const Operand *OpRd, const Operand *OpRn,
2180*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
2181*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2182*03ce13f7SAndroid Build Coastguard Worker // RSC (immediate) - ARM section A8.8.155, encoding A1:
2183*03ce13f7SAndroid Build Coastguard Worker // rsc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
2184*03ce13f7SAndroid Build Coastguard Worker //
2185*03ce13f7SAndroid Build Coastguard Worker // cccc0010111snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
2186*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
2187*03ce13f7SAndroid Build Coastguard Worker //
2188*03ce13f7SAndroid Build Coastguard Worker // RSC (register) - ARM section A8.8.156, encoding A1:
2189*03ce13f7SAndroid Build Coastguard Worker // rsc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
2190*03ce13f7SAndroid Build Coastguard Worker //
2191*03ce13f7SAndroid Build Coastguard Worker // cccc0000111snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2192*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
2193*03ce13f7SAndroid Build Coastguard Worker //
2194*03ce13f7SAndroid Build Coastguard Worker // RSC (register-shifted register) - ARM section A8.8.157, encoding A1:
2195*03ce13f7SAndroid Build Coastguard Worker // rsc{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
2196*03ce13f7SAndroid Build Coastguard Worker //
2197*03ce13f7SAndroid Build Coastguard Worker // cccc0000111fnnnnddddssss0tt1mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2198*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, ssss=Rs, tt defined <type>, and f=SetFlags.
2199*03ce13f7SAndroid Build Coastguard Worker constexpr const char *RscName = "rsc";
2200*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT RscOpcode = B2 | B1 | B0; // i.e. 0111.
2201*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, RscOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2202*03ce13f7SAndroid Build Coastguard Worker RscName);
2203*03ce13f7SAndroid Build Coastguard Worker }
2204*03ce13f7SAndroid Build Coastguard Worker
sxt(const Operand * OpRd,const Operand * OpSrc0,CondARM32::Cond Cond)2205*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::sxt(const Operand *OpRd, const Operand *OpSrc0,
2206*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2207*03ce13f7SAndroid Build Coastguard Worker constexpr const char *SxtName = "sxt";
2208*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT SxtOpcode = B26 | B25 | B23 | B21;
2209*03ce13f7SAndroid Build Coastguard Worker emitSignExtend(Cond, SxtOpcode, OpRd, OpSrc0, SxtName);
2210*03ce13f7SAndroid Build Coastguard Worker }
2211*03ce13f7SAndroid Build Coastguard Worker
sub(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,bool SetFlags,CondARM32::Cond Cond)2212*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
2213*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, bool SetFlags,
2214*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2215*03ce13f7SAndroid Build Coastguard Worker // SUB (register) - ARM section A8.8.223, encoding A1:
2216*03ce13f7SAndroid Build Coastguard Worker // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
2217*03ce13f7SAndroid Build Coastguard Worker // SUB (SP minus register): See ARM section 8.8.226, encoding A1:
2218*03ce13f7SAndroid Build Coastguard Worker // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>}
2219*03ce13f7SAndroid Build Coastguard Worker //
2220*03ce13f7SAndroid Build Coastguard Worker // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
2221*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
2222*03ce13f7SAndroid Build Coastguard Worker //
2223*03ce13f7SAndroid Build Coastguard Worker // Sub (Immediate) - ARM section A8.8.222, encoding A1:
2224*03ce13f7SAndroid Build Coastguard Worker // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8>
2225*03ce13f7SAndroid Build Coastguard Worker // Sub (Sp minus immediate) - ARM section A8.8.225, encoding A1:
2226*03ce13f7SAndroid Build Coastguard Worker // sub{s}<c> sp, <Rn>, #<RotatedImm8>
2227*03ce13f7SAndroid Build Coastguard Worker //
2228*03ce13f7SAndroid Build Coastguard Worker // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
2229*03ce13f7SAndroid Build Coastguard Worker // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8
2230*03ce13f7SAndroid Build Coastguard Worker constexpr const char *SubName = "sub";
2231*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT SubOpcode = B1; // 0010
2232*03ce13f7SAndroid Build Coastguard Worker emitType01(Cond, SubOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
2233*03ce13f7SAndroid Build Coastguard Worker SubName);
2234*03ce13f7SAndroid Build Coastguard Worker }
2235*03ce13f7SAndroid Build Coastguard Worker
2236*03ce13f7SAndroid Build Coastguard Worker namespace {
2237*03ce13f7SAndroid Build Coastguard Worker
2238*03ce13f7SAndroid Build Coastguard Worker // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0
2239*03ce13f7SAndroid Build Coastguard Worker // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943
2240*03ce13f7SAndroid Build Coastguard Worker const uint8_t TrapBytesRaw[] = {0xE7, 0xFE, 0xDE, 0xF0};
2241*03ce13f7SAndroid Build Coastguard Worker
2242*03ce13f7SAndroid Build Coastguard Worker const auto TrapBytes =
2243*03ce13f7SAndroid Build Coastguard Worker llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw));
2244*03ce13f7SAndroid Build Coastguard Worker
2245*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
2246*03ce13f7SAndroid Build Coastguard Worker
getNonExecBundlePadding() const2247*03ce13f7SAndroid Build Coastguard Worker llvm::ArrayRef<uint8_t> AssemblerARM32::getNonExecBundlePadding() const {
2248*03ce13f7SAndroid Build Coastguard Worker return TrapBytes;
2249*03ce13f7SAndroid Build Coastguard Worker }
2250*03ce13f7SAndroid Build Coastguard Worker
trap()2251*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::trap() {
2252*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2253*03ce13f7SAndroid Build Coastguard Worker for (const uint8_t &Byte : reverse_range(TrapBytes))
2254*03ce13f7SAndroid Build Coastguard Worker Buffer.emit<uint8_t>(Byte);
2255*03ce13f7SAndroid Build Coastguard Worker }
2256*03ce13f7SAndroid Build Coastguard Worker
tst(const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)2257*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1,
2258*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2259*03ce13f7SAndroid Build Coastguard Worker // TST (register) - ARM section A8.8.241, encoding A1:
2260*03ce13f7SAndroid Build Coastguard Worker // tst<c> <Rn>, <Rm>(, <shift>}
2261*03ce13f7SAndroid Build Coastguard Worker //
2262*03ce13f7SAndroid Build Coastguard Worker // cccc00010001nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
2263*03ce13f7SAndroid Build Coastguard Worker // iiiii=Shift, and tt=ShiftKind.
2264*03ce13f7SAndroid Build Coastguard Worker //
2265*03ce13f7SAndroid Build Coastguard Worker // TST (immediate) - ARM section A8.8.240, encoding A1:
2266*03ce13f7SAndroid Build Coastguard Worker // tst<c> <Rn>, #<RotatedImm8>
2267*03ce13f7SAndroid Build Coastguard Worker //
2268*03ce13f7SAndroid Build Coastguard Worker // cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and
2269*03ce13f7SAndroid Build Coastguard Worker // iiiiiiiiiiii defines RotatedImm8.
2270*03ce13f7SAndroid Build Coastguard Worker constexpr const char *TstName = "tst";
2271*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT TstOpcode = B3; // ie. 1000
2272*03ce13f7SAndroid Build Coastguard Worker emitCompareOp(Cond, TstOpcode, OpRn, OpSrc1, TstName);
2273*03ce13f7SAndroid Build Coastguard Worker }
2274*03ce13f7SAndroid Build Coastguard Worker
udiv(const Operand * OpRd,const Operand * OpRn,const Operand * OpSrc1,CondARM32::Cond Cond)2275*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn,
2276*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSrc1, CondARM32::Cond Cond) {
2277*03ce13f7SAndroid Build Coastguard Worker // UDIV - ARM section A8.8.248, encoding A1.
2278*03ce13f7SAndroid Build Coastguard Worker // udiv<c> <Rd>, <Rn>, <Rm>
2279*03ce13f7SAndroid Build Coastguard Worker //
2280*03ce13f7SAndroid Build Coastguard Worker // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
2281*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm.
2282*03ce13f7SAndroid Build Coastguard Worker constexpr const char *UdivName = "udiv";
2283*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", UdivName);
2284*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", UdivName);
2285*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpSrc1, "Rm", UdivName);
2286*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rd, "Rd", UdivName);
2287*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", UdivName);
2288*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", UdivName);
2289*03ce13f7SAndroid Build Coastguard Worker // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
2290*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT UdivOpcode = B21;
2291*03ce13f7SAndroid Build Coastguard Worker emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm);
2292*03ce13f7SAndroid Build Coastguard Worker }
2293*03ce13f7SAndroid Build Coastguard Worker
umull(const Operand * OpRdLo,const Operand * OpRdHi,const Operand * OpRn,const Operand * OpRm,CondARM32::Cond Cond)2294*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi,
2295*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRn, const Operand *OpRm,
2296*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2297*03ce13f7SAndroid Build Coastguard Worker // UMULL - ARM section A8.8.257, encoding A1:
2298*03ce13f7SAndroid Build Coastguard Worker // umull<c> <RdLo>, <RdHi>, <Rn>, <Rm>
2299*03ce13f7SAndroid Build Coastguard Worker //
2300*03ce13f7SAndroid Build Coastguard Worker // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn,
2301*03ce13f7SAndroid Build Coastguard Worker // mmmm=Rm, and s=SetFlags
2302*03ce13f7SAndroid Build Coastguard Worker constexpr const char *UmullName = "umull";
2303*03ce13f7SAndroid Build Coastguard Worker IValueT RdLo = encodeGPRegister(OpRdLo, "RdLo", UmullName);
2304*03ce13f7SAndroid Build Coastguard Worker IValueT RdHi = encodeGPRegister(OpRdHi, "RdHi", UmullName);
2305*03ce13f7SAndroid Build Coastguard Worker IValueT Rn = encodeGPRegister(OpRn, "Rn", UmullName);
2306*03ce13f7SAndroid Build Coastguard Worker IValueT Rm = encodeGPRegister(OpRm, "Rm", UmullName);
2307*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(RdLo, "RdLo", UmullName);
2308*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(RdHi, "RdHi", UmullName);
2309*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rn, "Rn", UmullName);
2310*03ce13f7SAndroid Build Coastguard Worker verifyRegNotPc(Rm, "Rm", UmullName);
2311*03ce13f7SAndroid Build Coastguard Worker verifyRegsNotEq(RdHi, "RdHi", RdLo, "RdLo", UmullName);
2312*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT UmullOpcode = B23;
2313*03ce13f7SAndroid Build Coastguard Worker constexpr bool SetFlags = false;
2314*03ce13f7SAndroid Build Coastguard Worker emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags);
2315*03ce13f7SAndroid Build Coastguard Worker }
2316*03ce13f7SAndroid Build Coastguard Worker
uxt(const Operand * OpRd,const Operand * OpSrc0,CondARM32::Cond Cond)2317*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
2318*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2319*03ce13f7SAndroid Build Coastguard Worker constexpr const char *UxtName = "uxt";
2320*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21;
2321*03ce13f7SAndroid Build Coastguard Worker emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName);
2322*03ce13f7SAndroid Build Coastguard Worker }
2323*03ce13f7SAndroid Build Coastguard Worker
vabss(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2324*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vabss(const Operand *OpSd, const Operand *OpSm,
2325*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2326*03ce13f7SAndroid Build Coastguard Worker // VABS - ARM section A8.8.280, encoding A2:
2327*03ce13f7SAndroid Build Coastguard Worker // vabs<c>.f32 <Sd>, <Sm>
2328*03ce13f7SAndroid Build Coastguard Worker //
2329*03ce13f7SAndroid Build Coastguard Worker // cccc11101D110000dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2330*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vabss = "vabss";
2331*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vabss);
2332*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vabss);
2333*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
2334*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VabssOpcode = B23 | B21 | B20 | B7 | B6;
2335*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VabssOpcode, Sd, S0, Sm);
2336*03ce13f7SAndroid Build Coastguard Worker }
2337*03ce13f7SAndroid Build Coastguard Worker
vabsd(const Operand * OpDd,const Operand * OpDm,CondARM32::Cond Cond)2338*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vabsd(const Operand *OpDd, const Operand *OpDm,
2339*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2340*03ce13f7SAndroid Build Coastguard Worker // VABS - ARM section A8.8.280, encoding A2:
2341*03ce13f7SAndroid Build Coastguard Worker // vabs<c>.f64 <Dd>, <Dm>
2342*03ce13f7SAndroid Build Coastguard Worker //
2343*03ce13f7SAndroid Build Coastguard Worker // cccc11101D110000dddd101111M0mmmm where cccc=Cond, Ddddd=Dd, and Mmmmm=Dm.
2344*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vabsd = "vabsd";
2345*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = encodeDRegister(OpDd, "Dd", Vabsd);
2346*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = encodeDRegister(OpDm, "Dm", Vabsd);
2347*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT D0 = 0;
2348*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VabsdOpcode = B23 | B21 | B20 | B7 | B6;
2349*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VabsdOpcode, Dd, D0, Dm);
2350*03ce13f7SAndroid Build Coastguard Worker }
2351*03ce13f7SAndroid Build Coastguard Worker
vabsq(const Operand * OpQd,const Operand * OpQm)2352*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vabsq(const Operand *OpQd, const Operand *OpQm) {
2353*03ce13f7SAndroid Build Coastguard Worker // VABS - ARM section A8.8.280, encoding A1:
2354*03ce13f7SAndroid Build Coastguard Worker // vabs.<dt> <Qd>, <Qm>
2355*03ce13f7SAndroid Build Coastguard Worker //
2356*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss01ddd0f1101M0mmm0 where Dddd=OpQd, Mddd=OpQm, and
2357*03ce13f7SAndroid Build Coastguard Worker // <dt> in {s8, s16, s32, f32} and ss is the encoding of <dt>.
2358*03ce13f7SAndroid Build Coastguard Worker const Type ElmtTy = typeElementType(OpQd->getType());
2359*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy != IceType_i64 && "vabsq doesn't allow i64!");
2360*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vabsq = "vabsq";
2361*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vabsq));
2362*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vabsq));
2363*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Dn = 0;
2364*03ce13f7SAndroid Build Coastguard Worker const IValueT VabsqOpcode =
2365*03ce13f7SAndroid Build Coastguard Worker B24 | B23 | B21 | B20 | B16 | B9 | B8 | (encodeElmtType(ElmtTy) << 18);
2366*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
2367*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VabsqOpcode, Dd, Dn, Dm, UseQRegs, isFloatingType(ElmtTy));
2368*03ce13f7SAndroid Build Coastguard Worker }
2369*03ce13f7SAndroid Build Coastguard Worker
vadds(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)2370*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vadds(const Operand *OpSd, const Operand *OpSn,
2371*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
2372*03ce13f7SAndroid Build Coastguard Worker // VADD (floating-point) - ARM section A8.8.283, encoding A2:
2373*03ce13f7SAndroid Build Coastguard Worker // vadd<c>.f32 <Sd>, <Sn>, <Sm>
2374*03ce13f7SAndroid Build Coastguard Worker //
2375*03ce13f7SAndroid Build Coastguard Worker // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
2376*03ce13f7SAndroid Build Coastguard Worker // and mmmmM=Rm.
2377*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vadds = "vadds";
2378*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VaddsOpcode = B21 | B20;
2379*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds);
2380*03ce13f7SAndroid Build Coastguard Worker }
2381*03ce13f7SAndroid Build Coastguard Worker
vaddqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2382*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vaddqi(Type ElmtTy, const Operand *OpQd,
2383*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
2384*03ce13f7SAndroid Build Coastguard Worker // VADD (integer) - ARM section A8.8.282, encoding A1:
2385*03ce13f7SAndroid Build Coastguard Worker // vadd.<dt> <Qd>, <Qn>, <Qm>
2386*03ce13f7SAndroid Build Coastguard Worker //
2387*03ce13f7SAndroid Build Coastguard Worker // 111100100Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2388*03ce13f7SAndroid Build Coastguard Worker // and dt in [i8, i16, i32, i64] where ss is the index.
2389*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
2390*03ce13f7SAndroid Build Coastguard Worker "vaddqi expects vector with integer element type");
2391*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vaddqi = "vaddqi";
2392*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VaddqiOpcode = B11;
2393*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vaddqi);
2394*03ce13f7SAndroid Build Coastguard Worker }
2395*03ce13f7SAndroid Build Coastguard Worker
vaddqf(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)2396*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vaddqf(const Operand *OpQd, const Operand *OpQn,
2397*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
2398*03ce13f7SAndroid Build Coastguard Worker // VADD (floating-point) - ARM section A8.8.283, Encoding A1:
2399*03ce13f7SAndroid Build Coastguard Worker // vadd.f32 <Qd>, <Qn>, <Qm>
2400*03ce13f7SAndroid Build Coastguard Worker //
2401*03ce13f7SAndroid Build Coastguard Worker // 111100100D00nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
2402*03ce13f7SAndroid Build Coastguard Worker assert(OpQd->getType() == IceType_v4f32 && "vaddqf expects type <4 x float>");
2403*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vaddqf = "vaddqf";
2404*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VaddqfOpcode = B11 | B8;
2405*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = true;
2406*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqqBase(VaddqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vaddqf);
2407*03ce13f7SAndroid Build Coastguard Worker }
2408*03ce13f7SAndroid Build Coastguard Worker
vaddd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)2409*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
2410*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
2411*03ce13f7SAndroid Build Coastguard Worker // VADD (floating-point) - ARM section A8.8.283, encoding A2:
2412*03ce13f7SAndroid Build Coastguard Worker // vadd<c>.f64 <Dd>, <Dn>, <Dm>
2413*03ce13f7SAndroid Build Coastguard Worker //
2414*03ce13f7SAndroid Build Coastguard Worker // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
2415*03ce13f7SAndroid Build Coastguard Worker // and Mmmmm=Rm.
2416*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vaddd = "vaddd";
2417*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VadddOpcode = B21 | B20;
2418*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VadddOpcode, OpDd, OpDn, OpDm, Vaddd);
2419*03ce13f7SAndroid Build Coastguard Worker }
2420*03ce13f7SAndroid Build Coastguard Worker
vandq(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2421*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vandq(const Operand *OpQd, const Operand *OpQm,
2422*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn) {
2423*03ce13f7SAndroid Build Coastguard Worker // VAND (register) - ARM section A8.8.287, encoding A1:
2424*03ce13f7SAndroid Build Coastguard Worker // vand <Qd>, <Qn>, <Qm>
2425*03ce13f7SAndroid Build Coastguard Worker //
2426*03ce13f7SAndroid Build Coastguard Worker // 111100100D00nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2427*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vandq = "vandq";
2428*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VandqOpcode = B8 | B4;
2429*03ce13f7SAndroid Build Coastguard Worker constexpr Type ElmtTy = IceType_i8;
2430*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VandqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vandq);
2431*03ce13f7SAndroid Build Coastguard Worker }
2432*03ce13f7SAndroid Build Coastguard Worker
vbslq(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2433*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vbslq(const Operand *OpQd, const Operand *OpQm,
2434*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn) {
2435*03ce13f7SAndroid Build Coastguard Worker // VBSL (register) - ARM section A8.8.290, encoding A1:
2436*03ce13f7SAndroid Build Coastguard Worker // vbsl <Qd>, <Qn>, <Qm>
2437*03ce13f7SAndroid Build Coastguard Worker //
2438*03ce13f7SAndroid Build Coastguard Worker // 111100110D01nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2439*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vbslq = "vbslq";
2440*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VbslqOpcode = B24 | B20 | B8 | B4;
2441*03ce13f7SAndroid Build Coastguard Worker constexpr Type ElmtTy = IceType_i8; // emits sz=0
2442*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VbslqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vbslq);
2443*03ce13f7SAndroid Build Coastguard Worker }
2444*03ce13f7SAndroid Build Coastguard Worker
vceqqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2445*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vceqqi(const Type ElmtTy, const Operand *OpQd,
2446*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
2447*03ce13f7SAndroid Build Coastguard Worker // vceq (register) - ARM section A8.8.291, encoding A1:
2448*03ce13f7SAndroid Build Coastguard Worker // vceq.<st> <Qd>, <Qn>, <Qm>
2449*03ce13f7SAndroid Build Coastguard Worker //
2450*03ce13f7SAndroid Build Coastguard Worker // 111100110Dssnnnndddd1000NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, and
2451*03ce13f7SAndroid Build Coastguard Worker // st in [i8, i16, i32] where ss is the index.
2452*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vceq = "vceq";
2453*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VceqOpcode = B24 | B11 | B4;
2454*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VceqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vceq);
2455*03ce13f7SAndroid Build Coastguard Worker }
2456*03ce13f7SAndroid Build Coastguard Worker
vceqqs(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2457*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vceqqs(const Operand *OpQd, const Operand *OpQm,
2458*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn) {
2459*03ce13f7SAndroid Build Coastguard Worker // vceq (register) - ARM section A8.8.291, encoding A2:
2460*03ce13f7SAndroid Build Coastguard Worker // vceq.f32 <Qd>, <Qn>, <Qm>
2461*03ce13f7SAndroid Build Coastguard Worker //
2462*03ce13f7SAndroid Build Coastguard Worker // 111100100D00nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2463*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vceq = "vceq";
2464*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VceqOpcode = B11 | B10 | B9;
2465*03ce13f7SAndroid Build Coastguard Worker constexpr Type ElmtTy = IceType_i8; // encoded as 0b00
2466*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VceqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vceq);
2467*03ce13f7SAndroid Build Coastguard Worker }
2468*03ce13f7SAndroid Build Coastguard Worker
vcgeqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2469*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcgeqi(const Type ElmtTy, const Operand *OpQd,
2470*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
2471*03ce13f7SAndroid Build Coastguard Worker // vcge (register) - ARM section A8.8.293, encoding A1:
2472*03ce13f7SAndroid Build Coastguard Worker // vcge.<st> <Qd>, <Qn>, <Qm>
2473*03ce13f7SAndroid Build Coastguard Worker //
2474*03ce13f7SAndroid Build Coastguard Worker // 1111001U0Dssnnnndddd0011NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2475*03ce13f7SAndroid Build Coastguard Worker // 0=U, and st in [s8, s16, s32] where ss is the index.
2476*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcge = "vcge";
2477*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcgeOpcode = B9 | B8 | B4;
2478*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2479*03ce13f7SAndroid Build Coastguard Worker }
2480*03ce13f7SAndroid Build Coastguard Worker
vcugeqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2481*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcugeqi(const Type ElmtTy, const Operand *OpQd,
2482*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
2483*03ce13f7SAndroid Build Coastguard Worker // vcge (register) - ARM section A8.8.293, encoding A1:
2484*03ce13f7SAndroid Build Coastguard Worker // vcge.<st> <Qd>, <Qn>, <Qm>
2485*03ce13f7SAndroid Build Coastguard Worker //
2486*03ce13f7SAndroid Build Coastguard Worker // 1111001U0Dssnnnndddd0011NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2487*03ce13f7SAndroid Build Coastguard Worker // 1=U, and st in [u8, u16, u32] where ss is the index.
2488*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcge = "vcge";
2489*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcgeOpcode = B24 | B9 | B8 | B4;
2490*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2491*03ce13f7SAndroid Build Coastguard Worker }
2492*03ce13f7SAndroid Build Coastguard Worker
vcgeqs(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2493*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcgeqs(const Operand *OpQd, const Operand *OpQm,
2494*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn) {
2495*03ce13f7SAndroid Build Coastguard Worker // vcge (register) - ARM section A8.8.293, encoding A2:
2496*03ce13f7SAndroid Build Coastguard Worker // vcge.f32 <Qd>, <Qn>, <Qm>
2497*03ce13f7SAndroid Build Coastguard Worker //
2498*03ce13f7SAndroid Build Coastguard Worker // 111100110D00nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2499*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcge = "vcge";
2500*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcgeOpcode = B24 | B11 | B10 | B9;
2501*03ce13f7SAndroid Build Coastguard Worker constexpr Type ElmtTy = IceType_i8; // encoded as 0b00.
2502*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2503*03ce13f7SAndroid Build Coastguard Worker }
2504*03ce13f7SAndroid Build Coastguard Worker
vcgtqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2505*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcgtqi(const Type ElmtTy, const Operand *OpQd,
2506*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
2507*03ce13f7SAndroid Build Coastguard Worker // vcgt (register) - ARM section A8.8.295, encoding A1:
2508*03ce13f7SAndroid Build Coastguard Worker // vcgt.<st> <Qd>, <Qn>, <Qm>
2509*03ce13f7SAndroid Build Coastguard Worker //
2510*03ce13f7SAndroid Build Coastguard Worker // 1111001U0Dssnnnndddd0011NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2511*03ce13f7SAndroid Build Coastguard Worker // 0=U, and st in [s8, s16, s32] where ss is the index.
2512*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcge = "vcgt";
2513*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcgeOpcode = B9 | B8;
2514*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2515*03ce13f7SAndroid Build Coastguard Worker }
2516*03ce13f7SAndroid Build Coastguard Worker
vcugtqi(const Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2517*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcugtqi(const Type ElmtTy, const Operand *OpQd,
2518*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
2519*03ce13f7SAndroid Build Coastguard Worker // vcgt (register) - ARM section A8.8.295, encoding A1:
2520*03ce13f7SAndroid Build Coastguard Worker // vcgt.<st> <Qd>, <Qn>, <Qm>
2521*03ce13f7SAndroid Build Coastguard Worker //
2522*03ce13f7SAndroid Build Coastguard Worker // 111100110Dssnnnndddd0011NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
2523*03ce13f7SAndroid Build Coastguard Worker // 1=U, and st in [u8, u16, u32] where ss is the index.
2524*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcge = "vcgt";
2525*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcgeOpcode = B24 | B9 | B8;
2526*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2527*03ce13f7SAndroid Build Coastguard Worker }
2528*03ce13f7SAndroid Build Coastguard Worker
vcgtqs(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)2529*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcgtqs(const Operand *OpQd, const Operand *OpQm,
2530*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn) {
2531*03ce13f7SAndroid Build Coastguard Worker // vcgt (register) - ARM section A8.8.295, encoding A2:
2532*03ce13f7SAndroid Build Coastguard Worker // vcgt.f32 <Qd>, <Qn>, <Qm>
2533*03ce13f7SAndroid Build Coastguard Worker //
2534*03ce13f7SAndroid Build Coastguard Worker // 111100110D10nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
2535*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcge = "vcgt";
2536*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcgeOpcode = B24 | B21 | B11 | B10 | B9;
2537*03ce13f7SAndroid Build Coastguard Worker constexpr Type ElmtTy = IceType_i8; // encoded as 0b00.
2538*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge);
2539*03ce13f7SAndroid Build Coastguard Worker }
2540*03ce13f7SAndroid Build Coastguard Worker
vcmpd(const Operand * OpDd,const Operand * OpDm,CondARM32::Cond Cond)2541*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcmpd(const Operand *OpDd, const Operand *OpDm,
2542*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2543*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcmpd = "vcmpd";
2544*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpd);
2545*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vcmpd);
2546*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcmpdOpcode = B23 | B21 | B20 | B18 | B6;
2547*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Dn = 0;
2548*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VcmpdOpcode, Dd, Dn, Dm);
2549*03ce13f7SAndroid Build Coastguard Worker }
2550*03ce13f7SAndroid Build Coastguard Worker
vcmpdz(const Operand * OpDd,CondARM32::Cond Cond)2551*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcmpdz(const Operand *OpDd, CondARM32::Cond Cond) {
2552*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcmpdz = "vcmpdz";
2553*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpdz);
2554*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcmpdzOpcode = B23 | B21 | B20 | B18 | B16 | B6;
2555*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Dn = 0;
2556*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Dm = 0;
2557*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VcmpdzOpcode, Dd, Dn, Dm);
2558*03ce13f7SAndroid Build Coastguard Worker }
2559*03ce13f7SAndroid Build Coastguard Worker
vcmps(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2560*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcmps(const Operand *OpSd, const Operand *OpSm,
2561*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2562*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcmps = "vcmps";
2563*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmps);
2564*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcmps);
2565*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcmpsOpcode = B23 | B21 | B20 | B18 | B6;
2566*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Sn = 0;
2567*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VcmpsOpcode, Sd, Sn, Sm);
2568*03ce13f7SAndroid Build Coastguard Worker }
2569*03ce13f7SAndroid Build Coastguard Worker
vcmpsz(const Operand * OpSd,CondARM32::Cond Cond)2570*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcmpsz(const Operand *OpSd, CondARM32::Cond Cond) {
2571*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcmpsz = "vcmps";
2572*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmpsz);
2573*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcmpszOpcode = B23 | B21 | B20 | B18 | B16 | B6;
2574*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Sn = 0;
2575*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Sm = 0;
2576*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VcmpszOpcode, Sd, Sn, Sm);
2577*03ce13f7SAndroid Build Coastguard Worker }
2578*03ce13f7SAndroid Build Coastguard Worker
emitVFPsd(CondARM32::Cond Cond,IValueT Opcode,IValueT Sd,IValueT Dm)2579*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
2580*03ce13f7SAndroid Build Coastguard Worker IValueT Dm) {
2581*03ce13f7SAndroid Build Coastguard Worker assert(Sd < RegARM32::getNumSRegs());
2582*03ce13f7SAndroid Build Coastguard Worker assert(Dm < RegARM32::getNumDRegs());
2583*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
2584*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
2585*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
2586*03ce13f7SAndroid Build Coastguard Worker Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
2587*03ce13f7SAndroid Build Coastguard Worker (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) |
2588*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
2589*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2590*03ce13f7SAndroid Build Coastguard Worker }
2591*03ce13f7SAndroid Build Coastguard Worker
vcvtdi(const Operand * OpDd,const Operand * OpSm,CondARM32::Cond Cond)2592*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtdi(const Operand *OpDd, const Operand *OpSm,
2593*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2594*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2595*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2596*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f64.s32 <Dd>, <Sm>
2597*03ce13f7SAndroid Build Coastguard Worker //
2598*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111000dddd10111M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm.
2599*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtdi = "vcvtdi";
2600*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdi);
2601*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdi);
2602*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtdiOpcode = B23 | B21 | B20 | B19 | B8 | B7 | B6;
2603*03ce13f7SAndroid Build Coastguard Worker emitVFPds(Cond, VcvtdiOpcode, Dd, Sm);
2604*03ce13f7SAndroid Build Coastguard Worker }
2605*03ce13f7SAndroid Build Coastguard Worker
vcvtdu(const Operand * OpDd,const Operand * OpSm,CondARM32::Cond Cond)2606*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtdu(const Operand *OpDd, const Operand *OpSm,
2607*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2608*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2609*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2610*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f64.u32 <Dd>, <Sm>
2611*03ce13f7SAndroid Build Coastguard Worker //
2612*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111000dddd10101M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm.
2613*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtdu = "vcvtdu";
2614*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdu);
2615*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdu);
2616*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtduOpcode = B23 | B21 | B20 | B19 | B8 | B6;
2617*03ce13f7SAndroid Build Coastguard Worker emitVFPds(Cond, VcvtduOpcode, Dd, Sm);
2618*03ce13f7SAndroid Build Coastguard Worker }
2619*03ce13f7SAndroid Build Coastguard Worker
vcvtsd(const Operand * OpSd,const Operand * OpDm,CondARM32::Cond Cond)2620*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtsd(const Operand *OpSd, const Operand *OpDm,
2621*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2622*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtsd = "vcvtsd";
2623*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsd);
2624*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtsd);
2625*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtsdOpcode =
2626*03ce13f7SAndroid Build Coastguard Worker B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6;
2627*03ce13f7SAndroid Build Coastguard Worker emitVFPsd(Cond, VcvtsdOpcode, Sd, Dm);
2628*03ce13f7SAndroid Build Coastguard Worker }
2629*03ce13f7SAndroid Build Coastguard Worker
vcvtis(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2630*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtis(const Operand *OpSd, const Operand *OpSm,
2631*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2632*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2633*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2634*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.s32.f32 <Sd>, <Sm>
2635*03ce13f7SAndroid Build Coastguard Worker //
2636*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111101dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2637*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtis = "vcvtis";
2638*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtis);
2639*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtis);
2640*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtisOpcode = B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6;
2641*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
2642*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VcvtisOpcode, Sd, S0, Sm);
2643*03ce13f7SAndroid Build Coastguard Worker }
2644*03ce13f7SAndroid Build Coastguard Worker
vcvtid(const Operand * OpSd,const Operand * OpDm,CondARM32::Cond Cond)2645*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtid(const Operand *OpSd, const Operand *OpDm,
2646*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2647*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2648*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2649*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.s32.f64 <Sd>, <Dm>
2650*03ce13f7SAndroid Build Coastguard Worker //
2651*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111101dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm.
2652*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtid = "vcvtid";
2653*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtid);
2654*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtid);
2655*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtidOpcode =
2656*03ce13f7SAndroid Build Coastguard Worker B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6;
2657*03ce13f7SAndroid Build Coastguard Worker emitVFPsd(Cond, VcvtidOpcode, Sd, Dm);
2658*03ce13f7SAndroid Build Coastguard Worker }
2659*03ce13f7SAndroid Build Coastguard Worker
vcvtsi(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2660*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtsi(const Operand *OpSd, const Operand *OpSm,
2661*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2662*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2663*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2664*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f32.s32 <Sd>, <Sm>
2665*03ce13f7SAndroid Build Coastguard Worker //
2666*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111000dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2667*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtsi = "vcvtsi";
2668*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsi);
2669*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsi);
2670*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B7 | B6;
2671*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
2672*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm);
2673*03ce13f7SAndroid Build Coastguard Worker }
2674*03ce13f7SAndroid Build Coastguard Worker
vcvtsu(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2675*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtsu(const Operand *OpSd, const Operand *OpSm,
2676*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2677*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2678*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2679*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f32.u32 <Sd>, <Sm>
2680*03ce13f7SAndroid Build Coastguard Worker //
2681*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111000dddd10001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2682*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtsu = "vcvtsu";
2683*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsu);
2684*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsu);
2685*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtsuOpcode = B23 | B21 | B20 | B19 | B6;
2686*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
2687*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VcvtsuOpcode, Sd, S0, Sm);
2688*03ce13f7SAndroid Build Coastguard Worker }
2689*03ce13f7SAndroid Build Coastguard Worker
vcvtud(const Operand * OpSd,const Operand * OpDm,CondARM32::Cond Cond)2690*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtud(const Operand *OpSd, const Operand *OpDm,
2691*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2692*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2693*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2694*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.u32.f64 <Sd>, <Dm>
2695*03ce13f7SAndroid Build Coastguard Worker //
2696*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111100dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm.
2697*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtud = "vcvtud";
2698*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtud);
2699*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtud);
2700*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtudOpcode = B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6;
2701*03ce13f7SAndroid Build Coastguard Worker emitVFPsd(Cond, VcvtudOpcode, Sd, Dm);
2702*03ce13f7SAndroid Build Coastguard Worker }
2703*03ce13f7SAndroid Build Coastguard Worker
vcvtus(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)2704*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtus(const Operand *OpSd, const Operand *OpSm,
2705*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2706*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Floating-point)
2707*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.306, encoding A1:
2708*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.u32.f32 <Sd>, <Sm>
2709*03ce13f7SAndroid Build Coastguard Worker //
2710*03ce13f7SAndroid Build Coastguard Worker // cccc11101D111100dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
2711*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtus = "vcvtus";
2712*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtus);
2713*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtus);
2714*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B18 | B7 | B6;
2715*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
2716*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm);
2717*03ce13f7SAndroid Build Coastguard Worker }
2718*03ce13f7SAndroid Build Coastguard Worker
vcvtqsi(const Operand * OpQd,const Operand * OpQm)2719*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtqsi(const Operand *OpQd, const Operand *OpQm) {
2720*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Advanced SIMD)
2721*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.305, encoding A1:
2722*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f32.s32 <Qd>, <Qm>
2723*03ce13f7SAndroid Build Coastguard Worker //
2724*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 10=op.
2725*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtqsi = "vcvt.s32.f32";
2726*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtqsiOpcode = B8;
2727*03ce13f7SAndroid Build Coastguard Worker emitSIMDCvtqq(VcvtqsiOpcode, OpQd, OpQm, Vcvtqsi);
2728*03ce13f7SAndroid Build Coastguard Worker }
2729*03ce13f7SAndroid Build Coastguard Worker
vcvtqsu(const Operand * OpQd,const Operand * OpQm)2730*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtqsu(const Operand *OpQd, const Operand *OpQm) {
2731*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Advanced SIMD)
2732*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.305, encoding A1:
2733*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f32.u32 <Qd>, <Qm>
2734*03ce13f7SAndroid Build Coastguard Worker //
2735*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 11=op.
2736*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtqsu = "vcvt.u32.f32";
2737*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtqsuOpcode = B8 | B7;
2738*03ce13f7SAndroid Build Coastguard Worker emitSIMDCvtqq(VcvtqsuOpcode, OpQd, OpQm, Vcvtqsu);
2739*03ce13f7SAndroid Build Coastguard Worker }
2740*03ce13f7SAndroid Build Coastguard Worker
vcvtqis(const Operand * OpQd,const Operand * OpQm)2741*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtqis(const Operand *OpQd, const Operand *OpQm) {
2742*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Advanced SIMD)
2743*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.305, encoding A1:
2744*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f32.s32 <Qd>, <Qm>
2745*03ce13f7SAndroid Build Coastguard Worker //
2746*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op.
2747*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtqis = "vcvt.f32.s32";
2748*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtqisOpcode = 0;
2749*03ce13f7SAndroid Build Coastguard Worker emitSIMDCvtqq(VcvtqisOpcode, OpQd, OpQm, Vcvtqis);
2750*03ce13f7SAndroid Build Coastguard Worker }
2751*03ce13f7SAndroid Build Coastguard Worker
vcvtqus(const Operand * OpQd,const Operand * OpQm)2752*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtqus(const Operand *OpQd, const Operand *OpQm) {
2753*03ce13f7SAndroid Build Coastguard Worker // VCVT (between floating-point and integer, Advanced SIMD)
2754*03ce13f7SAndroid Build Coastguard Worker // - ARM Section A8.8.305, encoding A1:
2755*03ce13f7SAndroid Build Coastguard Worker // vcvt<c>.f32.u32 <Qd>, <Qm>
2756*03ce13f7SAndroid Build Coastguard Worker //
2757*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op.
2758*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtqus = "vcvt.f32.u32";
2759*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtqusOpcode = B7;
2760*03ce13f7SAndroid Build Coastguard Worker emitSIMDCvtqq(VcvtqusOpcode, OpQd, OpQm, Vcvtqus);
2761*03ce13f7SAndroid Build Coastguard Worker }
2762*03ce13f7SAndroid Build Coastguard Worker
emitVFPds(CondARM32::Cond Cond,IValueT Opcode,IValueT Dd,IValueT Sm)2763*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd,
2764*03ce13f7SAndroid Build Coastguard Worker IValueT Sm) {
2765*03ce13f7SAndroid Build Coastguard Worker assert(Dd < RegARM32::getNumDRegs());
2766*03ce13f7SAndroid Build Coastguard Worker assert(Sm < RegARM32::getNumSRegs());
2767*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
2768*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
2769*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
2770*03ce13f7SAndroid Build Coastguard Worker Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
2771*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dd) << 12) |
2772*03ce13f7SAndroid Build Coastguard Worker (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm);
2773*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2774*03ce13f7SAndroid Build Coastguard Worker }
2775*03ce13f7SAndroid Build Coastguard Worker
vcvtds(const Operand * OpDd,const Operand * OpSm,CondARM32::Cond Cond)2776*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vcvtds(const Operand *OpDd, const Operand *OpSm,
2777*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
2778*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vcvtds = "Vctds";
2779*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtds);
2780*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtds);
2781*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VcvtdsOpcode = B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6;
2782*03ce13f7SAndroid Build Coastguard Worker emitVFPds(Cond, VcvtdsOpcode, Dd, Sm);
2783*03ce13f7SAndroid Build Coastguard Worker }
2784*03ce13f7SAndroid Build Coastguard Worker
vdivs(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)2785*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vdivs(const Operand *OpSd, const Operand *OpSn,
2786*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
2787*03ce13f7SAndroid Build Coastguard Worker // VDIV (floating-point) - ARM section A8.8.283, encoding A2:
2788*03ce13f7SAndroid Build Coastguard Worker // vdiv<c>.f32 <Sd>, <Sn>, <Sm>
2789*03ce13f7SAndroid Build Coastguard Worker //
2790*03ce13f7SAndroid Build Coastguard Worker // cccc11101D00nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
2791*03ce13f7SAndroid Build Coastguard Worker // and mmmmM=Rm.
2792*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vdivs = "vdivs";
2793*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VdivsOpcode = B23;
2794*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VdivsOpcode, OpSd, OpSn, OpSm, Vdivs);
2795*03ce13f7SAndroid Build Coastguard Worker }
2796*03ce13f7SAndroid Build Coastguard Worker
vdivd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)2797*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vdivd(const Operand *OpDd, const Operand *OpDn,
2798*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
2799*03ce13f7SAndroid Build Coastguard Worker // VDIV (floating-point) - ARM section A8.8.283, encoding A2:
2800*03ce13f7SAndroid Build Coastguard Worker // vdiv<c>.f64 <Dd>, <Dn>, <Dm>
2801*03ce13f7SAndroid Build Coastguard Worker //
2802*03ce13f7SAndroid Build Coastguard Worker // cccc11101D00nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
2803*03ce13f7SAndroid Build Coastguard Worker // and Mmmmm=Rm.
2804*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vdivd = "vdivd";
2805*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VdivdOpcode = B23;
2806*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VdivdOpcode, OpDd, OpDn, OpDm, Vdivd);
2807*03ce13f7SAndroid Build Coastguard Worker }
2808*03ce13f7SAndroid Build Coastguard Worker
veord(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm)2809*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::veord(const Operand *OpDd, const Operand *OpDn,
2810*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm) {
2811*03ce13f7SAndroid Build Coastguard Worker // VEOR - ARM secdtion A8.8.315, encoding A1:
2812*03ce13f7SAndroid Build Coastguard Worker // veor<c> <Dd>, <Dn>, <Dm>
2813*03ce13f7SAndroid Build Coastguard Worker //
2814*03ce13f7SAndroid Build Coastguard Worker // 111100110D00nnnndddd0001N0M1mmmm where Ddddd=Dd, Nnnnn=Dn, and Mmmmm=Dm.
2815*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Veord = "veord";
2816*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Veord);
2817*03ce13f7SAndroid Build Coastguard Worker IValueT Dn = encodeDRegister(OpDn, "Dn", Veord);
2818*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Veord);
2819*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
2820*03ce13f7SAndroid Build Coastguard Worker B25 | B24 | B8 | B4 |
2821*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(CondARM32::Cond::kNone) << kConditionShift) |
2822*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
2823*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
2824*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
2825*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2826*03ce13f7SAndroid Build Coastguard Worker }
2827*03ce13f7SAndroid Build Coastguard Worker
veorq(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)2828*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::veorq(const Operand *OpQd, const Operand *OpQn,
2829*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
2830*03ce13f7SAndroid Build Coastguard Worker // VEOR - ARM section A8.8.316, encoding A1:
2831*03ce13f7SAndroid Build Coastguard Worker // veor <Qd>, <Qn>, <Qm>
2832*03ce13f7SAndroid Build Coastguard Worker //
2833*03ce13f7SAndroid Build Coastguard Worker // 111100110D00nnn0ddd00001N1M1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
2834*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Veorq = "veorq";
2835*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VeorqOpcode = B24 | B8 | B4;
2836*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VeorqOpcode, IceType_i8, OpQd, OpQn, OpQm, Veorq);
2837*03ce13f7SAndroid Build Coastguard Worker }
2838*03ce13f7SAndroid Build Coastguard Worker
vldrd(const Operand * OpDd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)2839*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress,
2840*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
2841*03ce13f7SAndroid Build Coastguard Worker // VLDR - ARM section A8.8.333, encoding A1.
2842*03ce13f7SAndroid Build Coastguard Worker // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}]
2843*03ce13f7SAndroid Build Coastguard Worker //
2844*03ce13f7SAndroid Build Coastguard Worker // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
2845*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0.
2846*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vldrd = "vldrd";
2847*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd);
2848*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
2849*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
2850*03ce13f7SAndroid Build Coastguard Worker EncodedOperand AddressEncoding =
2851*03ce13f7SAndroid Build Coastguard Worker encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
2852*03ce13f7SAndroid Build Coastguard Worker (void)AddressEncoding;
2853*03ce13f7SAndroid Build Coastguard Worker assert(AddressEncoding == EncodedAsImmRegOffset);
2854*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 |
2855*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) |
2856*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) |
2857*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | Address;
2858*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2859*03ce13f7SAndroid Build Coastguard Worker }
2860*03ce13f7SAndroid Build Coastguard Worker
vldrq(const Operand * OpQd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)2861*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vldrq(const Operand *OpQd, const Operand *OpAddress,
2862*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
2863*03ce13f7SAndroid Build Coastguard Worker // This is a pseudo-instruction which loads 64-bit data into a quadword
2864*03ce13f7SAndroid Build Coastguard Worker // vector register. It is implemented by loading into the lower doubleword.
2865*03ce13f7SAndroid Build Coastguard Worker
2866*03ce13f7SAndroid Build Coastguard Worker // VLDR - ARM section A8.8.333, encoding A1.
2867*03ce13f7SAndroid Build Coastguard Worker // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}]
2868*03ce13f7SAndroid Build Coastguard Worker //
2869*03ce13f7SAndroid Build Coastguard Worker // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
2870*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0.
2871*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vldrd = "vldrd";
2872*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vldrd));
2873*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
2874*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
2875*03ce13f7SAndroid Build Coastguard Worker EncodedOperand AddressEncoding =
2876*03ce13f7SAndroid Build Coastguard Worker encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
2877*03ce13f7SAndroid Build Coastguard Worker (void)AddressEncoding;
2878*03ce13f7SAndroid Build Coastguard Worker assert(AddressEncoding == EncodedAsImmRegOffset);
2879*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 |
2880*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) |
2881*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) |
2882*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | Address;
2883*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2884*03ce13f7SAndroid Build Coastguard Worker }
2885*03ce13f7SAndroid Build Coastguard Worker
vldrs(const Operand * OpSd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)2886*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
2887*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
2888*03ce13f7SAndroid Build Coastguard Worker // VDLR - ARM section A8.8.333, encoding A2.
2889*03ce13f7SAndroid Build Coastguard Worker // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]]
2890*03ce13f7SAndroid Build Coastguard Worker //
2891*03ce13f7SAndroid Build Coastguard Worker // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd,
2892*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0;
2893*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vldrs = "vldrs";
2894*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs);
2895*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
2896*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
2897*03ce13f7SAndroid Build Coastguard Worker EncodedOperand AddressEncoding =
2898*03ce13f7SAndroid Build Coastguard Worker encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
2899*03ce13f7SAndroid Build Coastguard Worker (void)AddressEncoding;
2900*03ce13f7SAndroid Build Coastguard Worker assert(AddressEncoding == EncodedAsImmRegOffset);
2901*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 |
2902*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) |
2903*03ce13f7SAndroid Build Coastguard Worker (getYInRegXXXXY(Sd) << 22) |
2904*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegXXXXY(Sd) << 12) | Address;
2905*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2906*03ce13f7SAndroid Build Coastguard Worker }
2907*03ce13f7SAndroid Build Coastguard Worker
emitVMem1Op(IValueT Opcode,IValueT Dd,IValueT Rn,IValueT Rm,DRegListSize NumDRegs,size_t ElmtSize,IValueT Align,const char * InstName)2908*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn,
2909*03ce13f7SAndroid Build Coastguard Worker IValueT Rm, DRegListSize NumDRegs,
2910*03ce13f7SAndroid Build Coastguard Worker size_t ElmtSize, IValueT Align,
2911*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
2912*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsAbsoluteUint(2, Align));
2913*03ce13f7SAndroid Build Coastguard Worker IValueT EncodedElmtSize;
2914*03ce13f7SAndroid Build Coastguard Worker switch (ElmtSize) {
2915*03ce13f7SAndroid Build Coastguard Worker default: {
2916*03ce13f7SAndroid Build Coastguard Worker std::string Buffer;
2917*03ce13f7SAndroid Build Coastguard Worker llvm::raw_string_ostream StrBuf(Buffer);
2918*03ce13f7SAndroid Build Coastguard Worker StrBuf << InstName << ": found invalid vector element size " << ElmtSize;
2919*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(StrBuf.str());
2920*03ce13f7SAndroid Build Coastguard Worker }
2921*03ce13f7SAndroid Build Coastguard Worker case 8:
2922*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 0;
2923*03ce13f7SAndroid Build Coastguard Worker break;
2924*03ce13f7SAndroid Build Coastguard Worker case 16:
2925*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 1;
2926*03ce13f7SAndroid Build Coastguard Worker break;
2927*03ce13f7SAndroid Build Coastguard Worker case 32:
2928*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 2;
2929*03ce13f7SAndroid Build Coastguard Worker break;
2930*03ce13f7SAndroid Build Coastguard Worker case 64:
2931*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 3;
2932*03ce13f7SAndroid Build Coastguard Worker }
2933*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
2934*03ce13f7SAndroid Build Coastguard Worker Opcode | (encodeCondition(CondARM32::kNone) << kConditionShift) |
2935*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) | (Rn << kRnShift) |
2936*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << kRdShift) | (NumDRegs << 8) |
2937*03ce13f7SAndroid Build Coastguard Worker (EncodedElmtSize << 6) | (Align << 4) | Rm;
2938*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2939*03ce13f7SAndroid Build Coastguard Worker }
2940*03ce13f7SAndroid Build Coastguard Worker
emitVMem1Op(IValueT Opcode,IValueT Dd,IValueT Rn,IValueT Rm,size_t ElmtSize,IValueT Align,const char * InstName)2941*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn,
2942*03ce13f7SAndroid Build Coastguard Worker IValueT Rm, size_t ElmtSize, IValueT Align,
2943*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
2944*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsAbsoluteUint(2, Align));
2945*03ce13f7SAndroid Build Coastguard Worker IValueT EncodedElmtSize;
2946*03ce13f7SAndroid Build Coastguard Worker switch (ElmtSize) {
2947*03ce13f7SAndroid Build Coastguard Worker default: {
2948*03ce13f7SAndroid Build Coastguard Worker std::string Buffer;
2949*03ce13f7SAndroid Build Coastguard Worker llvm::raw_string_ostream StrBuf(Buffer);
2950*03ce13f7SAndroid Build Coastguard Worker StrBuf << InstName << ": found invalid vector element size " << ElmtSize;
2951*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(StrBuf.str());
2952*03ce13f7SAndroid Build Coastguard Worker }
2953*03ce13f7SAndroid Build Coastguard Worker case 8:
2954*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 0;
2955*03ce13f7SAndroid Build Coastguard Worker break;
2956*03ce13f7SAndroid Build Coastguard Worker case 16:
2957*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 1;
2958*03ce13f7SAndroid Build Coastguard Worker break;
2959*03ce13f7SAndroid Build Coastguard Worker case 32:
2960*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 2;
2961*03ce13f7SAndroid Build Coastguard Worker break;
2962*03ce13f7SAndroid Build Coastguard Worker case 64:
2963*03ce13f7SAndroid Build Coastguard Worker EncodedElmtSize = 3;
2964*03ce13f7SAndroid Build Coastguard Worker }
2965*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
2966*03ce13f7SAndroid Build Coastguard Worker Opcode | (encodeCondition(CondARM32::kNone) << kConditionShift) |
2967*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) | (Rn << kRnShift) |
2968*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << kRdShift) | (EncodedElmtSize << 10) |
2969*03ce13f7SAndroid Build Coastguard Worker (Align << 4) | Rm;
2970*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
2971*03ce13f7SAndroid Build Coastguard Worker }
2972*03ce13f7SAndroid Build Coastguard Worker
vld1qr(size_t ElmtSize,const Operand * OpQd,const Operand * OpAddress,const TargetInfo & TInfo)2973*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vld1qr(size_t ElmtSize, const Operand *OpQd,
2974*03ce13f7SAndroid Build Coastguard Worker const Operand *OpAddress, const TargetInfo &TInfo) {
2975*03ce13f7SAndroid Build Coastguard Worker // VLD1 (multiple single elements) - ARM section A8.8.320, encoding A1:
2976*03ce13f7SAndroid Build Coastguard Worker // vld1.<size> <Qd>, [<Rn>]
2977*03ce13f7SAndroid Build Coastguard Worker //
2978*03ce13f7SAndroid Build Coastguard Worker // 111101000D10nnnnddd0ttttssaammmm where tttt=DRegListSize2, Dddd=Qd,
2979*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the
2980*03ce13f7SAndroid Build Coastguard Worker // encoding of ElmtSize.
2981*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vld1qr = "vld1qr";
2982*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vld1qr);
2983*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(Qd);
2984*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
2985*03ce13f7SAndroid Build Coastguard Worker if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) !=
2986*03ce13f7SAndroid Build Coastguard Worker EncodedAsImmRegOffset)
2987*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(Vld1qr) + ": malform memory address");
2988*03ce13f7SAndroid Build Coastguard Worker const IValueT Rn = mask(Address, kRnShift, 4);
2989*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rm = RegARM32::Reg_pc;
2990*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Opcode = B26 | B21;
2991*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Align = 0; // use default alignment.
2992*03ce13f7SAndroid Build Coastguard Worker emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vld1qr);
2993*03ce13f7SAndroid Build Coastguard Worker }
2994*03ce13f7SAndroid Build Coastguard Worker
vld1(size_t ElmtSize,const Operand * OpQd,const Operand * OpAddress,const TargetInfo & TInfo)2995*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vld1(size_t ElmtSize, const Operand *OpQd,
2996*03ce13f7SAndroid Build Coastguard Worker const Operand *OpAddress, const TargetInfo &TInfo) {
2997*03ce13f7SAndroid Build Coastguard Worker // This is a pseudo-instruction for loading a single element of a quadword
2998*03ce13f7SAndroid Build Coastguard Worker // vector. For 64-bit the lower doubleword vector is loaded.
2999*03ce13f7SAndroid Build Coastguard Worker
3000*03ce13f7SAndroid Build Coastguard Worker if (ElmtSize == 64) {
3001*03ce13f7SAndroid Build Coastguard Worker return vldrq(OpQd, OpAddress, Ice::CondARM32::AL, TInfo);
3002*03ce13f7SAndroid Build Coastguard Worker }
3003*03ce13f7SAndroid Build Coastguard Worker
3004*03ce13f7SAndroid Build Coastguard Worker // VLD1 (single elements to one lane) - ARMv7-A/R section A8.6.308, encoding
3005*03ce13f7SAndroid Build Coastguard Worker // A1:
3006*03ce13f7SAndroid Build Coastguard Worker // VLD1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>
3007*03ce13f7SAndroid Build Coastguard Worker //
3008*03ce13f7SAndroid Build Coastguard Worker // 111101001D10nnnnddddss00aaaammmm where tttt=DRegListSize2, Dddd=Qd,
3009*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the
3010*03ce13f7SAndroid Build Coastguard Worker // encoding of ElmtSize.
3011*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vld1qr = "vld1qr";
3012*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vld1qr);
3013*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(Qd);
3014*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
3015*03ce13f7SAndroid Build Coastguard Worker if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) !=
3016*03ce13f7SAndroid Build Coastguard Worker EncodedAsImmRegOffset)
3017*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(Vld1qr) + ": malform memory address");
3018*03ce13f7SAndroid Build Coastguard Worker const IValueT Rn = mask(Address, kRnShift, 4);
3019*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rm = RegARM32::Reg_pc;
3020*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Opcode = B26 | B23 | B21;
3021*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Align = 0; // use default alignment.
3022*03ce13f7SAndroid Build Coastguard Worker emitVMem1Op(Opcode, Dd, Rn, Rm, ElmtSize, Align, Vld1qr);
3023*03ce13f7SAndroid Build Coastguard Worker }
3024*03ce13f7SAndroid Build Coastguard Worker
vmovqc(const Operand * OpQd,const ConstantInteger32 * Imm)3025*03ce13f7SAndroid Build Coastguard Worker bool AssemblerARM32::vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm) {
3026*03ce13f7SAndroid Build Coastguard Worker // VMOV (immediate) - ARM section A8.8.320, encoding A1:
3027*03ce13f7SAndroid Build Coastguard Worker // VMOV.<dt> <Qd>, #<Imm>
3028*03ce13f7SAndroid Build Coastguard Worker // 1111001x1D000yyyddddcccc01p1zzzz where Qd=Ddddd, Imm=xyyyzzzz, cmode=cccc,
3029*03ce13f7SAndroid Build Coastguard Worker // and Op=p.
3030*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovc = "vmovc";
3031*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmovc));
3032*03ce13f7SAndroid Build Coastguard Worker IValueT Value = Imm->getValue();
3033*03ce13f7SAndroid Build Coastguard Worker const Type VecTy = OpQd->getType();
3034*03ce13f7SAndroid Build Coastguard Worker if (!isVectorType(VecTy))
3035*03ce13f7SAndroid Build Coastguard Worker return false;
3036*03ce13f7SAndroid Build Coastguard Worker
3037*03ce13f7SAndroid Build Coastguard Worker IValueT Op;
3038*03ce13f7SAndroid Build Coastguard Worker IValueT Cmode;
3039*03ce13f7SAndroid Build Coastguard Worker IValueT Imm8;
3040*03ce13f7SAndroid Build Coastguard Worker if (!encodeAdvSIMDExpandImm(Value, typeElementType(VecTy), Op, Cmode, Imm8))
3041*03ce13f7SAndroid Build Coastguard Worker return false;
3042*03ce13f7SAndroid Build Coastguard Worker if (Op == 0 && mask(Cmode, 0, 1) == 1)
3043*03ce13f7SAndroid Build Coastguard Worker return false;
3044*03ce13f7SAndroid Build Coastguard Worker if (Op == 1 && Cmode != 13)
3045*03ce13f7SAndroid Build Coastguard Worker return false;
3046*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding =
3047*03ce13f7SAndroid Build Coastguard Worker (0xF << kConditionShift) | B25 | B23 | B6 | B4 |
3048*03ce13f7SAndroid Build Coastguard Worker (mask(Imm8, 7, 1) << 24) | (getYInRegYXXXX(Dd) << 22) |
3049*03ce13f7SAndroid Build Coastguard Worker (mask(Imm8, 4, 3) << 16) | (getXXXXInRegYXXXX(Dd) << 12) | (Cmode << 8) |
3050*03ce13f7SAndroid Build Coastguard Worker (Op << 5) | mask(Imm8, 0, 4);
3051*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3052*03ce13f7SAndroid Build Coastguard Worker return true;
3053*03ce13f7SAndroid Build Coastguard Worker }
3054*03ce13f7SAndroid Build Coastguard Worker
vmovd(const Operand * OpDd,const OperandARM32FlexFpImm * OpFpImm,CondARM32::Cond Cond)3055*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovd(const Operand *OpDd,
3056*03ce13f7SAndroid Build Coastguard Worker const OperandARM32FlexFpImm *OpFpImm,
3057*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3058*03ce13f7SAndroid Build Coastguard Worker // VMOV (immediate) - ARM section A8.8.339, encoding A2:
3059*03ce13f7SAndroid Build Coastguard Worker // vmov<c>.f64 <Dd>, #<imm>
3060*03ce13f7SAndroid Build Coastguard Worker //
3061*03ce13f7SAndroid Build Coastguard Worker // cccc11101D11xxxxdddd10110000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm.
3062*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovd = "vmovd";
3063*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovd);
3064*03ce13f7SAndroid Build Coastguard Worker IValueT Imm8 = OpFpImm->getModifiedImm();
3065*03ce13f7SAndroid Build Coastguard Worker assert(Imm8 < (1 << 8));
3066*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmovsOpcode = B23 | B21 | B20 | B8;
3067*03ce13f7SAndroid Build Coastguard Worker IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf);
3068*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT D0 = 0;
3069*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, OpcodePlusImm8, Dd, D0, D0);
3070*03ce13f7SAndroid Build Coastguard Worker }
3071*03ce13f7SAndroid Build Coastguard Worker
vmovdd(const Operand * OpDd,const Variable * OpDm,CondARM32::Cond Cond)3072*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovdd(const Operand *OpDd, const Variable *OpDm,
3073*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3074*03ce13f7SAndroid Build Coastguard Worker // VMOV (register) - ARM section A8.8.340, encoding A2:
3075*03ce13f7SAndroid Build Coastguard Worker // vmov<c>.f64 <Dd>, <Sm>
3076*03ce13f7SAndroid Build Coastguard Worker //
3077*03ce13f7SAndroid Build Coastguard Worker // cccc11101D110000dddd101101M0mmmm where cccc=Cond, Ddddd=Sd, and Mmmmm=Sm.
3078*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovdd = "Vmovdd";
3079*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovdd);
3080*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeSRegister(OpDm, "Dm", Vmovdd);
3081*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmovddOpcode = B23 | B21 | B20 | B6;
3082*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT D0 = 0;
3083*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VmovddOpcode, Dd, D0, Dm);
3084*03ce13f7SAndroid Build Coastguard Worker }
3085*03ce13f7SAndroid Build Coastguard Worker
vmovdrr(const Operand * OpDm,const Operand * OpRt,const Operand * OpRt2,CondARM32::Cond Cond)3086*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovdrr(const Operand *OpDm, const Operand *OpRt,
3087*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt2, CondARM32::Cond Cond) {
3088*03ce13f7SAndroid Build Coastguard Worker // VMOV (between two ARM core registers and a doubleword extension register).
3089*03ce13f7SAndroid Build Coastguard Worker // ARM section A8.8.345, encoding A1:
3090*03ce13f7SAndroid Build Coastguard Worker // vmov<c> <Dm>, <Rt>, <Rt2>
3091*03ce13f7SAndroid Build Coastguard Worker //
3092*03ce13f7SAndroid Build Coastguard Worker // cccc11000100xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and
3093*03ce13f7SAndroid Build Coastguard Worker // Mmmmm=Dm.
3094*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovdrr = "vmovdrr";
3095*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vmovdrr);
3096*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovdrr);
3097*03ce13f7SAndroid Build Coastguard Worker IValueT Rt2 = encodeGPRegister(OpRt2, "Rt", Vmovdrr);
3098*03ce13f7SAndroid Build Coastguard Worker assert(Rt != RegARM32::Encoded_Reg_sp);
3099*03ce13f7SAndroid Build Coastguard Worker assert(Rt != RegARM32::Encoded_Reg_pc);
3100*03ce13f7SAndroid Build Coastguard Worker assert(Rt2 != RegARM32::Encoded_Reg_sp);
3101*03ce13f7SAndroid Build Coastguard Worker assert(Rt2 != RegARM32::Encoded_Reg_pc);
3102*03ce13f7SAndroid Build Coastguard Worker assert(Rt != Rt2);
3103*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3104*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 |
3105*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) |
3106*03ce13f7SAndroid Build Coastguard Worker (Rt << 12) | (getYInRegYXXXX(Dm) << 5) |
3107*03ce13f7SAndroid Build Coastguard Worker getXXXXInRegYXXXX(Dm);
3108*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3109*03ce13f7SAndroid Build Coastguard Worker }
3110*03ce13f7SAndroid Build Coastguard Worker
vmovqir(const Operand * OpQn,uint32_t Index,const Operand * OpRt,CondARM32::Cond Cond)3111*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovqir(const Operand *OpQn, uint32_t Index,
3112*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt, CondARM32::Cond Cond) {
3113*03ce13f7SAndroid Build Coastguard Worker // VMOV (ARM core register to scalar) - ARM section A8.8.341, encoding A1:
3114*03ce13f7SAndroid Build Coastguard Worker // vmov<c>.<size> <Dn[x]>, <Rt>
3115*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovdr = "vmovdr";
3116*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsExtract = true;
3117*03ce13f7SAndroid Build Coastguard Worker emitInsertExtractInt(Cond, OpQn, Index, OpRt, !IsExtract, Vmovdr);
3118*03ce13f7SAndroid Build Coastguard Worker }
3119*03ce13f7SAndroid Build Coastguard Worker
vmovqis(const Operand * OpQd,uint32_t Index,const Operand * OpSm,CondARM32::Cond Cond)3120*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovqis(const Operand *OpQd, uint32_t Index,
3121*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
3122*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovqis = "vmovqis";
3123*03ce13f7SAndroid Build Coastguard Worker assert(Index < 4);
3124*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = mapQRegToSReg(encodeQRegister(OpQd, "Qd", Vmovqis)) + Index;
3125*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovqis);
3126*03ce13f7SAndroid Build Coastguard Worker emitMoveSS(Cond, Sd, Sm);
3127*03ce13f7SAndroid Build Coastguard Worker }
3128*03ce13f7SAndroid Build Coastguard Worker
vmovrqi(const Operand * OpRt,const Operand * OpQn,uint32_t Index,CondARM32::Cond Cond)3129*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovrqi(const Operand *OpRt, const Operand *OpQn,
3130*03ce13f7SAndroid Build Coastguard Worker uint32_t Index, CondARM32::Cond Cond) {
3131*03ce13f7SAndroid Build Coastguard Worker // VMOV (scalar to ARM core register) - ARM section A8.8.342, encoding A1:
3132*03ce13f7SAndroid Build Coastguard Worker // vmov<c>.<dt> <Rt>, <Dn[x]>
3133*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovrd = "vmovrd";
3134*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsExtract = true;
3135*03ce13f7SAndroid Build Coastguard Worker emitInsertExtractInt(Cond, OpQn, Index, OpRt, IsExtract, Vmovrd);
3136*03ce13f7SAndroid Build Coastguard Worker }
3137*03ce13f7SAndroid Build Coastguard Worker
vmovrrd(const Operand * OpRt,const Operand * OpRt2,const Operand * OpDm,CondARM32::Cond Cond)3138*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2,
3139*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
3140*03ce13f7SAndroid Build Coastguard Worker // VMOV (between two ARM core registers and a doubleword extension register).
3141*03ce13f7SAndroid Build Coastguard Worker // ARM section A8.8.345, encoding A1:
3142*03ce13f7SAndroid Build Coastguard Worker // vmov<c> <Rt>, <Rt2>, <Dm>
3143*03ce13f7SAndroid Build Coastguard Worker //
3144*03ce13f7SAndroid Build Coastguard Worker // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and
3145*03ce13f7SAndroid Build Coastguard Worker // Mmmmm=Dm.
3146*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovrrd = "vmovrrd";
3147*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd);
3148*03ce13f7SAndroid Build Coastguard Worker IValueT Rt2 = encodeGPRegister(OpRt2, "Rt", Vmovrrd);
3149*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vmovrrd);
3150*03ce13f7SAndroid Build Coastguard Worker assert(Rt != RegARM32::Encoded_Reg_sp);
3151*03ce13f7SAndroid Build Coastguard Worker assert(Rt != RegARM32::Encoded_Reg_pc);
3152*03ce13f7SAndroid Build Coastguard Worker assert(Rt2 != RegARM32::Encoded_Reg_sp);
3153*03ce13f7SAndroid Build Coastguard Worker assert(Rt2 != RegARM32::Encoded_Reg_pc);
3154*03ce13f7SAndroid Build Coastguard Worker assert(Rt != Rt2);
3155*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3156*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B22 | B20 | B11 | B9 | B8 | B4 |
3157*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) |
3158*03ce13f7SAndroid Build Coastguard Worker (Rt << 12) | (getYInRegYXXXX(Dm) << 5) |
3159*03ce13f7SAndroid Build Coastguard Worker getXXXXInRegYXXXX(Dm);
3160*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3161*03ce13f7SAndroid Build Coastguard Worker }
3162*03ce13f7SAndroid Build Coastguard Worker
vmovrs(const Operand * OpRt,const Operand * OpSn,CondARM32::Cond Cond)3163*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovrs(const Operand *OpRt, const Operand *OpSn,
3164*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3165*03ce13f7SAndroid Build Coastguard Worker // VMOV (between ARM core register and single-precision register)
3166*03ce13f7SAndroid Build Coastguard Worker // ARM section A8.8.343, encoding A1.
3167*03ce13f7SAndroid Build Coastguard Worker //
3168*03ce13f7SAndroid Build Coastguard Worker // vmov<c> <Rt>, <Sn>
3169*03ce13f7SAndroid Build Coastguard Worker //
3170*03ce13f7SAndroid Build Coastguard Worker // cccc11100001nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt.
3171*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovrs = "vmovrs";
3172*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrs);
3173*03ce13f7SAndroid Build Coastguard Worker IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovrs);
3174*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3175*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 |
3176*03ce13f7SAndroid Build Coastguard Worker B25 | B20 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) |
3177*03ce13f7SAndroid Build Coastguard Worker (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7);
3178*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3179*03ce13f7SAndroid Build Coastguard Worker }
3180*03ce13f7SAndroid Build Coastguard Worker
vmovs(const Operand * OpSd,const OperandARM32FlexFpImm * OpFpImm,CondARM32::Cond Cond)3181*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovs(const Operand *OpSd,
3182*03ce13f7SAndroid Build Coastguard Worker const OperandARM32FlexFpImm *OpFpImm,
3183*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3184*03ce13f7SAndroid Build Coastguard Worker // VMOV (immediate) - ARM section A8.8.339, encoding A2:
3185*03ce13f7SAndroid Build Coastguard Worker // vmov<c>.f32 <Sd>, #<imm>
3186*03ce13f7SAndroid Build Coastguard Worker //
3187*03ce13f7SAndroid Build Coastguard Worker // cccc11101D11xxxxdddd10100000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm.
3188*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovs = "vmovs";
3189*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovs);
3190*03ce13f7SAndroid Build Coastguard Worker IValueT Imm8 = OpFpImm->getModifiedImm();
3191*03ce13f7SAndroid Build Coastguard Worker assert(Imm8 < (1 << 8));
3192*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmovsOpcode = B23 | B21 | B20;
3193*03ce13f7SAndroid Build Coastguard Worker IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf);
3194*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
3195*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0);
3196*03ce13f7SAndroid Build Coastguard Worker }
3197*03ce13f7SAndroid Build Coastguard Worker
vmovss(const Operand * OpSd,const Variable * OpSm,CondARM32::Cond Cond)3198*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm,
3199*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3200*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovss = "Vmovss";
3201*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss);
3202*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss);
3203*03ce13f7SAndroid Build Coastguard Worker emitMoveSS(Cond, Sd, Sm);
3204*03ce13f7SAndroid Build Coastguard Worker }
3205*03ce13f7SAndroid Build Coastguard Worker
vmovsqi(const Operand * OpSd,const Operand * OpQm,uint32_t Index,CondARM32::Cond Cond)3206*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovsqi(const Operand *OpSd, const Operand *OpQm,
3207*03ce13f7SAndroid Build Coastguard Worker uint32_t Index, CondARM32::Cond Cond) {
3208*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovsqi = "vmovsqi";
3209*03ce13f7SAndroid Build Coastguard Worker const IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovsqi);
3210*03ce13f7SAndroid Build Coastguard Worker assert(Index < 4);
3211*03ce13f7SAndroid Build Coastguard Worker const IValueT Sm =
3212*03ce13f7SAndroid Build Coastguard Worker mapQRegToSReg(encodeQRegister(OpQm, "Qm", Vmovsqi)) + Index;
3213*03ce13f7SAndroid Build Coastguard Worker emitMoveSS(Cond, Sd, Sm);
3214*03ce13f7SAndroid Build Coastguard Worker }
3215*03ce13f7SAndroid Build Coastguard Worker
vmovsr(const Operand * OpSn,const Operand * OpRt,CondARM32::Cond Cond)3216*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
3217*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3218*03ce13f7SAndroid Build Coastguard Worker // VMOV (between ARM core register and single-precision register)
3219*03ce13f7SAndroid Build Coastguard Worker // ARM section A8.8.343, encoding A1.
3220*03ce13f7SAndroid Build Coastguard Worker //
3221*03ce13f7SAndroid Build Coastguard Worker // vmov<c> <Sn>, <Rt>
3222*03ce13f7SAndroid Build Coastguard Worker //
3223*03ce13f7SAndroid Build Coastguard Worker // cccc11100000nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt.
3224*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmovsr = "vmovsr";
3225*03ce13f7SAndroid Build Coastguard Worker IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovsr);
3226*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovsr);
3227*03ce13f7SAndroid Build Coastguard Worker assert(Sn < RegARM32::getNumSRegs());
3228*03ce13f7SAndroid Build Coastguard Worker assert(Rt < RegARM32::getNumGPRegs());
3229*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3230*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 |
3231*03ce13f7SAndroid Build Coastguard Worker B25 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) |
3232*03ce13f7SAndroid Build Coastguard Worker (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7);
3233*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3234*03ce13f7SAndroid Build Coastguard Worker }
3235*03ce13f7SAndroid Build Coastguard Worker
vmlad(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3236*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmlad(const Operand *OpDd, const Operand *OpDn,
3237*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
3238*03ce13f7SAndroid Build Coastguard Worker // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3239*03ce13f7SAndroid Build Coastguard Worker // vmla<c>.f64 <Dd>, <Dn>, <Dm>
3240*03ce13f7SAndroid Build Coastguard Worker //
3241*03ce13f7SAndroid Build Coastguard Worker // cccc11100d00nnnndddd1011n0M0mmmm where cccc=Cond, Ddddd=Dd, Nnnnn=Dn, and
3242*03ce13f7SAndroid Build Coastguard Worker // Mmmmm=Dm
3243*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmlad = "vmlad";
3244*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmladOpcode = 0;
3245*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VmladOpcode, OpDd, OpDn, OpDm, Vmlad);
3246*03ce13f7SAndroid Build Coastguard Worker }
3247*03ce13f7SAndroid Build Coastguard Worker
vmlas(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3248*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmlas(const Operand *OpSd, const Operand *OpSn,
3249*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
3250*03ce13f7SAndroid Build Coastguard Worker // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3251*03ce13f7SAndroid Build Coastguard Worker // vmla<c>.f32 <Sd>, <Sn>, <Sm>
3252*03ce13f7SAndroid Build Coastguard Worker //
3253*03ce13f7SAndroid Build Coastguard Worker // cccc11100d00nnnndddd1010n0M0mmmm where cccc=Cond, ddddD=Sd, nnnnN=Sn, and
3254*03ce13f7SAndroid Build Coastguard Worker // mmmmM=Sm
3255*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmlas = "vmlas";
3256*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmlasOpcode = 0;
3257*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VmlasOpcode, OpSd, OpSn, OpSm, Vmlas);
3258*03ce13f7SAndroid Build Coastguard Worker }
3259*03ce13f7SAndroid Build Coastguard Worker
vmlsd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3260*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmlsd(const Operand *OpDd, const Operand *OpDn,
3261*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
3262*03ce13f7SAndroid Build Coastguard Worker // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3263*03ce13f7SAndroid Build Coastguard Worker // vmls<c>.f64 <Dd>, <Dn>, <Dm>
3264*03ce13f7SAndroid Build Coastguard Worker //
3265*03ce13f7SAndroid Build Coastguard Worker // cccc11100d00nnnndddd1011n1M0mmmm where cccc=Cond, Ddddd=Dd, Nnnnn=Dn, and
3266*03ce13f7SAndroid Build Coastguard Worker // Mmmmm=Dm
3267*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmlad = "vmlad";
3268*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmladOpcode = B6;
3269*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VmladOpcode, OpDd, OpDn, OpDm, Vmlad);
3270*03ce13f7SAndroid Build Coastguard Worker }
3271*03ce13f7SAndroid Build Coastguard Worker
vmlss(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3272*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmlss(const Operand *OpSd, const Operand *OpSn,
3273*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
3274*03ce13f7SAndroid Build Coastguard Worker // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2:
3275*03ce13f7SAndroid Build Coastguard Worker // vmls<c>.f32 <Sd>, <Sn>, <Sm>
3276*03ce13f7SAndroid Build Coastguard Worker //
3277*03ce13f7SAndroid Build Coastguard Worker // cccc11100d00nnnndddd1010n1M0mmmm where cccc=Cond, ddddD=Sd, nnnnN=Sn, and
3278*03ce13f7SAndroid Build Coastguard Worker // mmmmM=Sm
3279*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmlas = "vmlas";
3280*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmlasOpcode = B6;
3281*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VmlasOpcode, OpSd, OpSn, OpSm, Vmlas);
3282*03ce13f7SAndroid Build Coastguard Worker }
3283*03ce13f7SAndroid Build Coastguard Worker
vmrsAPSR_nzcv(CondARM32::Cond Cond)3284*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmrsAPSR_nzcv(CondARM32::Cond Cond) {
3285*03ce13f7SAndroid Build Coastguard Worker // MVRS - ARM section A*.8.348, encoding A1:
3286*03ce13f7SAndroid Build Coastguard Worker // vmrs<c> APSR_nzcv, FPSCR
3287*03ce13f7SAndroid Build Coastguard Worker //
3288*03ce13f7SAndroid Build Coastguard Worker // cccc111011110001tttt101000010000 where tttt=0x15 (i.e. when Rt=pc, use
3289*03ce13f7SAndroid Build Coastguard Worker // APSR_nzcv instead).
3290*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3291*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | B15 | B14 |
3292*03ce13f7SAndroid Build Coastguard Worker B13 | B12 | B11 | B9 | B4 |
3293*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift);
3294*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3295*03ce13f7SAndroid Build Coastguard Worker }
3296*03ce13f7SAndroid Build Coastguard Worker
vmuls(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3297*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn,
3298*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
3299*03ce13f7SAndroid Build Coastguard Worker // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
3300*03ce13f7SAndroid Build Coastguard Worker // vmul<c>.f32 <Sd>, <Sn>, <Sm>
3301*03ce13f7SAndroid Build Coastguard Worker //
3302*03ce13f7SAndroid Build Coastguard Worker // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
3303*03ce13f7SAndroid Build Coastguard Worker // and mmmmM=Rm.
3304*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmuls = "vmuls";
3305*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmulsOpcode = B21;
3306*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VmulsOpcode, OpSd, OpSn, OpSm, Vmuls);
3307*03ce13f7SAndroid Build Coastguard Worker }
3308*03ce13f7SAndroid Build Coastguard Worker
vmuld(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3309*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn,
3310*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
3311*03ce13f7SAndroid Build Coastguard Worker // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
3312*03ce13f7SAndroid Build Coastguard Worker // vmul<c>.f64 <Dd>, <Dn>, <Dm>
3313*03ce13f7SAndroid Build Coastguard Worker //
3314*03ce13f7SAndroid Build Coastguard Worker // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
3315*03ce13f7SAndroid Build Coastguard Worker // and Mmmmm=Rm.
3316*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmuld = "vmuld";
3317*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmuldOpcode = B21;
3318*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VmuldOpcode, OpDd, OpDn, OpDm, Vmuld);
3319*03ce13f7SAndroid Build Coastguard Worker }
3320*03ce13f7SAndroid Build Coastguard Worker
vmulqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3321*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmulqi(Type ElmtTy, const Operand *OpQd,
3322*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn, const Operand *OpQm) {
3323*03ce13f7SAndroid Build Coastguard Worker // VMUL, VMULL (integer and polynomial) - ARM section A8.8.350, encoding A1:
3324*03ce13f7SAndroid Build Coastguard Worker // vmul<c>.<dt> <Qd>, <Qn>, <Qm>
3325*03ce13f7SAndroid Build Coastguard Worker //
3326*03ce13f7SAndroid Build Coastguard Worker // 111100100Dssnnn0ddd01001NqM1mmm0 where Dddd=Qd, Nnnn=Qn, Mmmm=Qm, and
3327*03ce13f7SAndroid Build Coastguard Worker // dt in [i8, i16, i32] where ss is the index.
3328*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3329*03ce13f7SAndroid Build Coastguard Worker "vmulqi expects vector with integer element type");
3330*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy != IceType_i64 && "vmulqi on i64 vector not allowed");
3331*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmulqi = "vmulqi";
3332*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmulqiOpcode = B11 | B8 | B4;
3333*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VmulqiOpcode, ElmtTy, OpQd, OpQn, OpQm, Vmulqi);
3334*03ce13f7SAndroid Build Coastguard Worker }
3335*03ce13f7SAndroid Build Coastguard Worker
vmulh(Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm,bool Unsigned)3336*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmulh(Type ElmtTy, const Operand *OpQd,
3337*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn, const Operand *OpQm,
3338*03ce13f7SAndroid Build Coastguard Worker bool Unsigned) {
3339*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction for multiplying the corresponding elements in the lower
3340*03ce13f7SAndroid Build Coastguard Worker // halves of two quadword vectors, and returning the high halves.
3341*03ce13f7SAndroid Build Coastguard Worker
3342*03ce13f7SAndroid Build Coastguard Worker // VMULL (integer and polynomial) - ARMv7-A/R section A8.6.337, encoding A1:
3343*03ce13f7SAndroid Build Coastguard Worker // VMUL<c>.<dt> <Dd>, <Dn>, <Dm>
3344*03ce13f7SAndroid Build Coastguard Worker //
3345*03ce13f7SAndroid Build Coastguard Worker // 1111001U1Dssnnnndddd11o0N0M0mmmm
3346*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3347*03ce13f7SAndroid Build Coastguard Worker "vmull expects vector with integer element type");
3348*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy != IceType_i64 && "vmull on i64 vector not allowed");
3349*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmull = "vmull";
3350*03ce13f7SAndroid Build Coastguard Worker
3351*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 20;
3352*03ce13f7SAndroid Build Coastguard Worker const IValueT ElmtSize = encodeElmtType(ElmtTy);
3353*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(2, ElmtSize));
3354*03ce13f7SAndroid Build Coastguard Worker
3355*03ce13f7SAndroid Build Coastguard Worker const IValueT VmullOpcode =
3356*03ce13f7SAndroid Build Coastguard Worker B25 | (Unsigned ? B24 : 0) | B23 | (B20) | B11 | B10;
3357*03ce13f7SAndroid Build Coastguard Worker
3358*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vmull);
3359*03ce13f7SAndroid Build Coastguard Worker const IValueT Qn = encodeQRegister(OpQn, "Qn", Vmull);
3360*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", Vmull);
3361*03ce13f7SAndroid Build Coastguard Worker
3362*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(Qd);
3363*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(Qn);
3364*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(Qm);
3365*03ce13f7SAndroid Build Coastguard Worker
3366*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3367*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
3368*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmullOpcode | (ElmtSize << ElmtShift), Dd, Dn, Dm, UseQRegs,
3369*03ce13f7SAndroid Build Coastguard Worker IsFloatTy);
3370*03ce13f7SAndroid Build Coastguard Worker
3371*03ce13f7SAndroid Build Coastguard Worker // Shift and narrow to obtain high halves.
3372*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VshrnOpcode = B25 | B23 | B11 | B4;
3373*03ce13f7SAndroid Build Coastguard Worker const IValueT Imm6 = encodeSIMDShiftImm6(ST_Vshr, IceType_i16, 16);
3374*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ImmShift = 16;
3375*03ce13f7SAndroid Build Coastguard Worker
3376*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VshrnOpcode | (Imm6 << ImmShift), Dd, 0, Dd, UseQRegs,
3377*03ce13f7SAndroid Build Coastguard Worker IsFloatTy);
3378*03ce13f7SAndroid Build Coastguard Worker }
3379*03ce13f7SAndroid Build Coastguard Worker
vmlap(Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3380*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmlap(Type ElmtTy, const Operand *OpQd,
3381*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn, const Operand *OpQm) {
3382*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction for multiplying the corresponding elements in the lower
3383*03ce13f7SAndroid Build Coastguard Worker // halves of two quadword vectors, and pairwise-adding the results.
3384*03ce13f7SAndroid Build Coastguard Worker
3385*03ce13f7SAndroid Build Coastguard Worker // VMULL (integer and polynomial) - ARM section A8.8.350, encoding A1:
3386*03ce13f7SAndroid Build Coastguard Worker // vmull<c>.<dt> <Qd>, <Qn>, <Qm>
3387*03ce13f7SAndroid Build Coastguard Worker //
3388*03ce13f7SAndroid Build Coastguard Worker // 1111001U1Dssnnnndddd11o0N0M0mmmm
3389*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3390*03ce13f7SAndroid Build Coastguard Worker "vmull expects vector with integer element type");
3391*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy != IceType_i64 && "vmull on i64 vector not allowed");
3392*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmull = "vmull";
3393*03ce13f7SAndroid Build Coastguard Worker
3394*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 20;
3395*03ce13f7SAndroid Build Coastguard Worker const IValueT ElmtSize = encodeElmtType(ElmtTy);
3396*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(2, ElmtSize));
3397*03ce13f7SAndroid Build Coastguard Worker
3398*03ce13f7SAndroid Build Coastguard Worker bool Unsigned = false;
3399*03ce13f7SAndroid Build Coastguard Worker const IValueT VmullOpcode =
3400*03ce13f7SAndroid Build Coastguard Worker B25 | (Unsigned ? B24 : 0) | B23 | (B20) | B11 | B10;
3401*03ce13f7SAndroid Build Coastguard Worker
3402*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmull));
3403*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmull));
3404*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmull));
3405*03ce13f7SAndroid Build Coastguard Worker
3406*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3407*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
3408*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmullOpcode | (ElmtSize << ElmtShift), Dd, Dn, Dm, UseQRegs,
3409*03ce13f7SAndroid Build Coastguard Worker IsFloatTy);
3410*03ce13f7SAndroid Build Coastguard Worker
3411*03ce13f7SAndroid Build Coastguard Worker // VPADD - ARM section A8.8.280, encoding A1:
3412*03ce13f7SAndroid Build Coastguard Worker // vpadd.<dt> <Dd>, <Dm>, <Dn>
3413*03ce13f7SAndroid Build Coastguard Worker //
3414*03ce13f7SAndroid Build Coastguard Worker // 111100100Dssnnnndddd1011NQM1mmmm where Ddddd=<Dd>, Mmmmm=<Dm>, and
3415*03ce13f7SAndroid Build Coastguard Worker // Nnnnn=<Dn> and ss is the encoding of <dt>.
3416*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy != IceType_i64 && "vpadd doesn't allow i64!");
3417*03ce13f7SAndroid Build Coastguard Worker const IValueT VpaddOpcode =
3418*03ce13f7SAndroid Build Coastguard Worker B25 | B11 | B9 | B8 | B4 | ((encodeElmtType(ElmtTy) + 1) << 20);
3419*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VpaddOpcode, Dd, Dd, Dd + 1, UseQRegs, IsFloatTy);
3420*03ce13f7SAndroid Build Coastguard Worker }
3421*03ce13f7SAndroid Build Coastguard Worker
vdup(Type ElmtTy,const Operand * OpQd,const Operand * OpQn,IValueT Idx)3422*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vdup(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
3423*03ce13f7SAndroid Build Coastguard Worker IValueT Idx) {
3424*03ce13f7SAndroid Build Coastguard Worker // VDUP (scalar) - ARMv7-A/R section A8.6.302, encoding A1:
3425*03ce13f7SAndroid Build Coastguard Worker // VDUP<c>.<size> <Qd>, <Dm[x]>
3426*03ce13f7SAndroid Build Coastguard Worker //
3427*03ce13f7SAndroid Build Coastguard Worker // 111100111D11iiiiddd011000QM0mmmm where Dddd=<Qd>, Mmmmm=<Dm>, and
3428*03ce13f7SAndroid Build Coastguard Worker // iiii=imm4 encodes <size> and [x].
3429*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vdup = "vdup";
3430*03ce13f7SAndroid Build Coastguard Worker
3431*03ce13f7SAndroid Build Coastguard Worker const IValueT VdupOpcode = B25 | B24 | B23 | B21 | B20 | B11 | B10;
3432*03ce13f7SAndroid Build Coastguard Worker
3433*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vdup));
3434*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vdup));
3435*03ce13f7SAndroid Build Coastguard Worker
3436*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
3437*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
3438*03ce13f7SAndroid Build Coastguard Worker
3439*03ce13f7SAndroid Build Coastguard Worker IValueT Imm4 = 0;
3440*03ce13f7SAndroid Build Coastguard Worker bool Lower = true;
3441*03ce13f7SAndroid Build Coastguard Worker switch (ElmtTy) {
3442*03ce13f7SAndroid Build Coastguard Worker case IceType_i8:
3443*03ce13f7SAndroid Build Coastguard Worker assert(Idx < 16);
3444*03ce13f7SAndroid Build Coastguard Worker Lower = Idx < 8;
3445*03ce13f7SAndroid Build Coastguard Worker Imm4 = 1 | ((Idx & 0x7) << 1);
3446*03ce13f7SAndroid Build Coastguard Worker break;
3447*03ce13f7SAndroid Build Coastguard Worker case IceType_i16:
3448*03ce13f7SAndroid Build Coastguard Worker assert(Idx < 8);
3449*03ce13f7SAndroid Build Coastguard Worker Lower = Idx < 4;
3450*03ce13f7SAndroid Build Coastguard Worker Imm4 = 2 | ((Idx & 0x3) << 2);
3451*03ce13f7SAndroid Build Coastguard Worker break;
3452*03ce13f7SAndroid Build Coastguard Worker case IceType_i32:
3453*03ce13f7SAndroid Build Coastguard Worker case IceType_f32:
3454*03ce13f7SAndroid Build Coastguard Worker assert(Idx < 4);
3455*03ce13f7SAndroid Build Coastguard Worker Lower = Idx < 2;
3456*03ce13f7SAndroid Build Coastguard Worker Imm4 = 4 | ((Idx & 0x1) << 3);
3457*03ce13f7SAndroid Build Coastguard Worker break;
3458*03ce13f7SAndroid Build Coastguard Worker default:
3459*03ce13f7SAndroid Build Coastguard Worker assert(false && "vdup only supports 8, 16, and 32-bit elements");
3460*03ce13f7SAndroid Build Coastguard Worker break;
3461*03ce13f7SAndroid Build Coastguard Worker }
3462*03ce13f7SAndroid Build Coastguard Worker
3463*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VdupOpcode, Dd, Imm4, Dn + (Lower ? 0 : 1), UseQRegs, IsFloatTy);
3464*03ce13f7SAndroid Build Coastguard Worker }
3465*03ce13f7SAndroid Build Coastguard Worker
vzip(Type ElmtTy,const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3466*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vzip(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
3467*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3468*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction which interleaves the elements of the lower halves of
3469*03ce13f7SAndroid Build Coastguard Worker // two quadword registers.
3470*03ce13f7SAndroid Build Coastguard Worker
3471*03ce13f7SAndroid Build Coastguard Worker // Vzip - ARMv7-A/R section A8.6.410, encoding A1:
3472*03ce13f7SAndroid Build Coastguard Worker // VZIP<c>.<size> <Dd>, <Dm>
3473*03ce13f7SAndroid Build Coastguard Worker //
3474*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss10dddd00011QM0mmmm where Ddddd=<Dd>, Mmmmm=<Dm>, and
3475*03ce13f7SAndroid Build Coastguard Worker // ss=<size>
3476*03ce13f7SAndroid Build Coastguard Worker assert(ElmtTy != IceType_i64 && "vzip on i64 vector not allowed");
3477*03ce13f7SAndroid Build Coastguard Worker
3478*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vzip = "vzip";
3479*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vzip));
3480*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vzip));
3481*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vzip));
3482*03ce13f7SAndroid Build Coastguard Worker
3483*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3484*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
3485*03ce13f7SAndroid Build Coastguard Worker
3486*03ce13f7SAndroid Build Coastguard Worker // VMOV Dd, Dm
3487*03ce13f7SAndroid Build Coastguard Worker // 111100100D10mmmmdddd0001MQM1mmmm
3488*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmovOpcode = B25 | B21 | B8 | B4;
3489*03ce13f7SAndroid Build Coastguard Worker
3490*03ce13f7SAndroid Build Coastguard Worker // Copy lower half of second source to upper half of destination.
3491*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd + 1, Dm, Dm, UseQRegs, IsFloatTy);
3492*03ce13f7SAndroid Build Coastguard Worker
3493*03ce13f7SAndroid Build Coastguard Worker // Copy lower half of first source to lower half of destination.
3494*03ce13f7SAndroid Build Coastguard Worker if (Dd != Dn)
3495*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd, Dn, Dn, UseQRegs, IsFloatTy);
3496*03ce13f7SAndroid Build Coastguard Worker
3497*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 18;
3498*03ce13f7SAndroid Build Coastguard Worker const IValueT ElmtSize = encodeElmtType(ElmtTy);
3499*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(2, ElmtSize));
3500*03ce13f7SAndroid Build Coastguard Worker
3501*03ce13f7SAndroid Build Coastguard Worker if (ElmtTy != IceType_i32 && ElmtTy != IceType_f32) {
3502*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VzipOpcode = B25 | B24 | B23 | B21 | B20 | B17 | B8 | B7;
3503*03ce13f7SAndroid Build Coastguard Worker // Zip the lower and upper half of destination.
3504*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VzipOpcode | (ElmtSize << ElmtShift), Dd, 0, Dd + 1, UseQRegs,
3505*03ce13f7SAndroid Build Coastguard Worker IsFloatTy);
3506*03ce13f7SAndroid Build Coastguard Worker } else {
3507*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VtrnOpcode = B25 | B24 | B23 | B21 | B20 | B17 | B7;
3508*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VtrnOpcode | (ElmtSize << ElmtShift), Dd, 0, Dd + 1, UseQRegs,
3509*03ce13f7SAndroid Build Coastguard Worker IsFloatTy);
3510*03ce13f7SAndroid Build Coastguard Worker }
3511*03ce13f7SAndroid Build Coastguard Worker }
3512*03ce13f7SAndroid Build Coastguard Worker
vmulqf(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3513*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmulqf(const Operand *OpQd, const Operand *OpQn,
3514*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3515*03ce13f7SAndroid Build Coastguard Worker // VMUL (floating-point) - ARM section A8.8.351, encoding A1:
3516*03ce13f7SAndroid Build Coastguard Worker // vmul.f32 <Qd>, <Qn>, <Qm>
3517*03ce13f7SAndroid Build Coastguard Worker //
3518*03ce13f7SAndroid Build Coastguard Worker // 111100110D00nnn0ddd01101MqM1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
3519*03ce13f7SAndroid Build Coastguard Worker assert(OpQd->getType() == IceType_v4f32 && "vmulqf expects type <4 x float>");
3520*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmulqf = "vmulqf";
3521*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmulqfOpcode = B24 | B11 | B8 | B4;
3522*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = true;
3523*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqqBase(VmulqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vmulqf);
3524*03ce13f7SAndroid Build Coastguard Worker }
3525*03ce13f7SAndroid Build Coastguard Worker
vmvnq(const Operand * OpQd,const Operand * OpQm)3526*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmvnq(const Operand *OpQd, const Operand *OpQm) {
3527*03ce13f7SAndroid Build Coastguard Worker // VMVN (integer) - ARM section A8.8.354, encoding A1:
3528*03ce13f7SAndroid Build Coastguard Worker // vmvn <Qd>, <Qm>
3529*03ce13f7SAndroid Build Coastguard Worker //
3530*03ce13f7SAndroid Build Coastguard Worker // 111100111D110000dddd01011QM0mmmm where Dddd=Qd, Mmmm=Qm, and 1=Q.
3531*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp) xxx: unify
3532*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmvn = "vmvn";
3533*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VmvnOpcode = B24 | B23 | B21 | B20 | B10 | B8 | B7;
3534*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vmvn);
3535*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Qn = 0;
3536*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", Vmvn);
3537*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
3538*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloat = false;
3539*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmvnOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn),
3540*03ce13f7SAndroid Build Coastguard Worker mapQRegToDReg(Qm), UseQRegs, IsFloat);
3541*03ce13f7SAndroid Build Coastguard Worker }
3542*03ce13f7SAndroid Build Coastguard Worker
vmovlq(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3543*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovlq(const Operand *OpQd, const Operand *OpQn,
3544*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3545*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction to copy the first source operand and insert the lower
3546*03ce13f7SAndroid Build Coastguard Worker // half of the second operand into the lower half of the destination.
3547*03ce13f7SAndroid Build Coastguard Worker
3548*03ce13f7SAndroid Build Coastguard Worker // VMOV (register) - ARMv7-A/R section A8.6.327, encoding A1:
3549*03ce13f7SAndroid Build Coastguard Worker // VMOV<c> <Dd>, <Dm>
3550*03ce13f7SAndroid Build Coastguard Worker //
3551*03ce13f7SAndroid Build Coastguard Worker // 111100111D110000ddd001011QM0mmm0 where Dddd=Qd, Mmmm=Qm, and Q=0.
3552*03ce13f7SAndroid Build Coastguard Worker
3553*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmov = "vmov";
3554*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmov));
3555*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
3556*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
3557*03ce13f7SAndroid Build Coastguard Worker
3558*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3559*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloat = false;
3560*03ce13f7SAndroid Build Coastguard Worker
3561*03ce13f7SAndroid Build Coastguard Worker const IValueT VmovOpcode = B25 | B21 | B8 | B4;
3562*03ce13f7SAndroid Build Coastguard Worker
3563*03ce13f7SAndroid Build Coastguard Worker if (Dd != Dm)
3564*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd, Dm, Dm, UseQRegs, IsFloat);
3565*03ce13f7SAndroid Build Coastguard Worker if (Dd + 1 != Dn + 1)
3566*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd + 1, Dn + 1, Dn + 1, UseQRegs, IsFloat);
3567*03ce13f7SAndroid Build Coastguard Worker }
3568*03ce13f7SAndroid Build Coastguard Worker
vmovhq(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3569*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovhq(const Operand *OpQd, const Operand *OpQn,
3570*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3571*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction to copy the first source operand and insert the high
3572*03ce13f7SAndroid Build Coastguard Worker // half of the second operand into the high half of the destination.
3573*03ce13f7SAndroid Build Coastguard Worker
3574*03ce13f7SAndroid Build Coastguard Worker // VMOV (register) - ARMv7-A/R section A8.6.327, encoding A1:
3575*03ce13f7SAndroid Build Coastguard Worker // VMOV<c> <Dd>, <Dm>
3576*03ce13f7SAndroid Build Coastguard Worker //
3577*03ce13f7SAndroid Build Coastguard Worker // 111100111D110000ddd001011QM0mmm0 where Dddd=Qd, Mmmm=Qm, and Q=0.
3578*03ce13f7SAndroid Build Coastguard Worker
3579*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmov = "vmov";
3580*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmov));
3581*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
3582*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
3583*03ce13f7SAndroid Build Coastguard Worker
3584*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3585*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloat = false;
3586*03ce13f7SAndroid Build Coastguard Worker
3587*03ce13f7SAndroid Build Coastguard Worker const IValueT VmovOpcode = B25 | B21 | B8 | B4;
3588*03ce13f7SAndroid Build Coastguard Worker
3589*03ce13f7SAndroid Build Coastguard Worker if (Dd != Dn)
3590*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd, Dn, Dn, UseQRegs, IsFloat);
3591*03ce13f7SAndroid Build Coastguard Worker if (Dd + 1 != Dm + 1)
3592*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd + 1, Dm + 1, Dm + 1, UseQRegs, IsFloat);
3593*03ce13f7SAndroid Build Coastguard Worker }
3594*03ce13f7SAndroid Build Coastguard Worker
vmovhlq(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3595*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovhlq(const Operand *OpQd, const Operand *OpQn,
3596*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3597*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction to copy the first source operand and insert the high
3598*03ce13f7SAndroid Build Coastguard Worker // half of the second operand into the lower half of the destination.
3599*03ce13f7SAndroid Build Coastguard Worker
3600*03ce13f7SAndroid Build Coastguard Worker // VMOV (register) - ARMv7-A/R section A8.6.327, encoding A1:
3601*03ce13f7SAndroid Build Coastguard Worker // VMOV<c> <Dd>, <Dm>
3602*03ce13f7SAndroid Build Coastguard Worker //
3603*03ce13f7SAndroid Build Coastguard Worker // 111100111D110000ddd001011QM0mmm0 where Dddd=Qd, Mmmm=Qm, and Q=0.
3604*03ce13f7SAndroid Build Coastguard Worker
3605*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmov = "vmov";
3606*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmov));
3607*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
3608*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
3609*03ce13f7SAndroid Build Coastguard Worker
3610*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3611*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloat = false;
3612*03ce13f7SAndroid Build Coastguard Worker
3613*03ce13f7SAndroid Build Coastguard Worker const IValueT VmovOpcode = B25 | B21 | B8 | B4;
3614*03ce13f7SAndroid Build Coastguard Worker
3615*03ce13f7SAndroid Build Coastguard Worker if (Dd != Dm + 1)
3616*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd, Dm + 1, Dm + 1, UseQRegs, IsFloat);
3617*03ce13f7SAndroid Build Coastguard Worker if (Dd + 1 != Dn + 1)
3618*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd + 1, Dn + 1, Dn + 1, UseQRegs, IsFloat);
3619*03ce13f7SAndroid Build Coastguard Worker }
3620*03ce13f7SAndroid Build Coastguard Worker
vmovlhq(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3621*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vmovlhq(const Operand *OpQd, const Operand *OpQn,
3622*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3623*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction to copy the first source operand and insert the lower
3624*03ce13f7SAndroid Build Coastguard Worker // half of the second operand into the high half of the destination.
3625*03ce13f7SAndroid Build Coastguard Worker
3626*03ce13f7SAndroid Build Coastguard Worker // VMOV (register) - ARMv7-A/R section A8.6.327, encoding A1:
3627*03ce13f7SAndroid Build Coastguard Worker // VMOV<c> <Dd>, <Dm>
3628*03ce13f7SAndroid Build Coastguard Worker //
3629*03ce13f7SAndroid Build Coastguard Worker // 111100111D110000ddd001011QM0mmm0 where Dddd=Qd, Mmmm=Qm, and Q=0.
3630*03ce13f7SAndroid Build Coastguard Worker
3631*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vmov = "vmov";
3632*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmov));
3633*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
3634*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
3635*03ce13f7SAndroid Build Coastguard Worker
3636*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3637*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloat = false;
3638*03ce13f7SAndroid Build Coastguard Worker
3639*03ce13f7SAndroid Build Coastguard Worker const IValueT VmovOpcode = B25 | B21 | B8 | B4;
3640*03ce13f7SAndroid Build Coastguard Worker
3641*03ce13f7SAndroid Build Coastguard Worker if (Dd + 1 != Dm)
3642*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd + 1, Dm, Dm, UseQRegs, IsFloat);
3643*03ce13f7SAndroid Build Coastguard Worker if (Dd != Dn)
3644*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd, Dn, Dn, UseQRegs, IsFloat);
3645*03ce13f7SAndroid Build Coastguard Worker }
3646*03ce13f7SAndroid Build Coastguard Worker
vnegqs(Type ElmtTy,const Operand * OpQd,const Operand * OpQm)3647*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vnegqs(Type ElmtTy, const Operand *OpQd,
3648*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3649*03ce13f7SAndroid Build Coastguard Worker // VNEG - ARM section A8.8.355, encoding A1:
3650*03ce13f7SAndroid Build Coastguard Worker // vneg.<dt> <Qd>, <Qm>
3651*03ce13f7SAndroid Build Coastguard Worker //
3652*03ce13f7SAndroid Build Coastguard Worker // 111111111D11ss01dddd0F111QM0mmmm where Dddd=Qd, and Mmmm=Qm, and:
3653*03ce13f7SAndroid Build Coastguard Worker // * dt=s8 -> 00=ss, 0=F
3654*03ce13f7SAndroid Build Coastguard Worker // * dt=s16 -> 01=ss, 0=F
3655*03ce13f7SAndroid Build Coastguard Worker // * dt=s32 -> 10=ss, 0=F
3656*03ce13f7SAndroid Build Coastguard Worker // * dt=s32 -> 10=ss, 1=F
3657*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vneg = "vneg";
3658*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VnegOpcode = B24 | B23 | B21 | B20 | B16 | B9 | B8 | B7;
3659*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vneg);
3660*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Qn = 0;
3661*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", Vneg);
3662*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = true;
3663*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 18;
3664*03ce13f7SAndroid Build Coastguard Worker const IValueT ElmtSize = encodeElmtType(ElmtTy);
3665*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsUint(2, ElmtSize));
3666*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VnegOpcode | (ElmtSize << ElmtShift), mapQRegToDReg(Qd),
3667*03ce13f7SAndroid Build Coastguard Worker mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs,
3668*03ce13f7SAndroid Build Coastguard Worker isFloatingType(ElmtTy));
3669*03ce13f7SAndroid Build Coastguard Worker }
3670*03ce13f7SAndroid Build Coastguard Worker
vorrq(const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3671*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vorrq(const Operand *OpQd, const Operand *OpQm,
3672*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQn) {
3673*03ce13f7SAndroid Build Coastguard Worker // VORR (register) - ARM section A8.8.360, encoding A1:
3674*03ce13f7SAndroid Build Coastguard Worker // vorr <Qd>, <Qn>, <Qm>
3675*03ce13f7SAndroid Build Coastguard Worker //
3676*03ce13f7SAndroid Build Coastguard Worker // 111100100D10nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm.
3677*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vorrq = "vorrq";
3678*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VorrqOpcode = B21 | B8 | B4;
3679*03ce13f7SAndroid Build Coastguard Worker constexpr Type ElmtTy = IceType_i8;
3680*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VorrqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vorrq);
3681*03ce13f7SAndroid Build Coastguard Worker }
3682*03ce13f7SAndroid Build Coastguard Worker
vstrd(const Operand * OpDd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)3683*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress,
3684*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
3685*03ce13f7SAndroid Build Coastguard Worker // VSTR - ARM section A8.8.413, encoding A1:
3686*03ce13f7SAndroid Build Coastguard Worker // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}]
3687*03ce13f7SAndroid Build Coastguard Worker //
3688*03ce13f7SAndroid Build Coastguard Worker // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
3689*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0.
3690*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vstrd = "vstrd";
3691*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd);
3692*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3693*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
3694*03ce13f7SAndroid Build Coastguard Worker IValueT AddressEncoding =
3695*03ce13f7SAndroid Build Coastguard Worker encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
3696*03ce13f7SAndroid Build Coastguard Worker (void)AddressEncoding;
3697*03ce13f7SAndroid Build Coastguard Worker assert(AddressEncoding == EncodedAsImmRegOffset);
3698*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 |
3699*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) |
3700*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) |
3701*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | Address;
3702*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3703*03ce13f7SAndroid Build Coastguard Worker }
3704*03ce13f7SAndroid Build Coastguard Worker
vstrq(const Operand * OpQd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)3705*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vstrq(const Operand *OpQd, const Operand *OpAddress,
3706*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
3707*03ce13f7SAndroid Build Coastguard Worker // This is a pseudo-instruction which stores 64-bit data into a quadword
3708*03ce13f7SAndroid Build Coastguard Worker // vector register. It is implemented by storing into the lower doubleword.
3709*03ce13f7SAndroid Build Coastguard Worker
3710*03ce13f7SAndroid Build Coastguard Worker // VSTR - ARM section A8.8.413, encoding A1:
3711*03ce13f7SAndroid Build Coastguard Worker // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}]
3712*03ce13f7SAndroid Build Coastguard Worker //
3713*03ce13f7SAndroid Build Coastguard Worker // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
3714*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0.
3715*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vstrd = "vstrd";
3716*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Dd", Vstrd));
3717*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3718*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
3719*03ce13f7SAndroid Build Coastguard Worker IValueT AddressEncoding =
3720*03ce13f7SAndroid Build Coastguard Worker encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
3721*03ce13f7SAndroid Build Coastguard Worker (void)AddressEncoding;
3722*03ce13f7SAndroid Build Coastguard Worker assert(AddressEncoding == EncodedAsImmRegOffset);
3723*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 |
3724*03ce13f7SAndroid Build Coastguard Worker (encodeCondition(Cond) << kConditionShift) |
3725*03ce13f7SAndroid Build Coastguard Worker (getYInRegYXXXX(Dd) << 22) |
3726*03ce13f7SAndroid Build Coastguard Worker (getXXXXInRegYXXXX(Dd) << 12) | Address;
3727*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3728*03ce13f7SAndroid Build Coastguard Worker }
3729*03ce13f7SAndroid Build Coastguard Worker
vstrs(const Operand * OpSd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetInfo & TInfo)3730*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress,
3731*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond, const TargetInfo &TInfo) {
3732*03ce13f7SAndroid Build Coastguard Worker // VSTR - ARM section A8.8.413, encoding A2:
3733*03ce13f7SAndroid Build Coastguard Worker // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]]
3734*03ce13f7SAndroid Build Coastguard Worker //
3735*03ce13f7SAndroid Build Coastguard Worker // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd,
3736*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0;
3737*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vstrs = "vstrs";
3738*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs);
3739*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3740*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
3741*03ce13f7SAndroid Build Coastguard Worker IValueT AddressEncoding =
3742*03ce13f7SAndroid Build Coastguard Worker encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address);
3743*03ce13f7SAndroid Build Coastguard Worker (void)AddressEncoding;
3744*03ce13f7SAndroid Build Coastguard Worker assert(AddressEncoding == EncodedAsImmRegOffset);
3745*03ce13f7SAndroid Build Coastguard Worker IValueT Encoding =
3746*03ce13f7SAndroid Build Coastguard Worker B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) |
3747*03ce13f7SAndroid Build Coastguard Worker (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address;
3748*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3749*03ce13f7SAndroid Build Coastguard Worker }
3750*03ce13f7SAndroid Build Coastguard Worker
vst1qr(size_t ElmtSize,const Operand * OpQd,const Operand * OpAddress,const TargetInfo & TInfo)3751*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vst1qr(size_t ElmtSize, const Operand *OpQd,
3752*03ce13f7SAndroid Build Coastguard Worker const Operand *OpAddress, const TargetInfo &TInfo) {
3753*03ce13f7SAndroid Build Coastguard Worker // VST1 (multiple single elements) - ARM section A8.8.404, encoding A1:
3754*03ce13f7SAndroid Build Coastguard Worker // vst1.<size> <Qd>, [<Rn>]
3755*03ce13f7SAndroid Build Coastguard Worker //
3756*03ce13f7SAndroid Build Coastguard Worker // 111101000D00nnnnddd0ttttssaammmm where tttt=DRegListSize2, Dddd=Qd,
3757*03ce13f7SAndroid Build Coastguard Worker // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the
3758*03ce13f7SAndroid Build Coastguard Worker // encoding of ElmtSize.
3759*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vst1qr = "vst1qr";
3760*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vst1qr);
3761*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(Qd);
3762*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
3763*03ce13f7SAndroid Build Coastguard Worker if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) !=
3764*03ce13f7SAndroid Build Coastguard Worker EncodedAsImmRegOffset)
3765*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(Vst1qr) + ": malform memory address");
3766*03ce13f7SAndroid Build Coastguard Worker const IValueT Rn = mask(Address, kRnShift, 4);
3767*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rm = RegARM32::Reg_pc;
3768*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Opcode = B26;
3769*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Align = 0; // use default alignment.
3770*03ce13f7SAndroid Build Coastguard Worker emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vst1qr);
3771*03ce13f7SAndroid Build Coastguard Worker }
3772*03ce13f7SAndroid Build Coastguard Worker
vst1(size_t ElmtSize,const Operand * OpQd,const Operand * OpAddress,const TargetInfo & TInfo)3773*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vst1(size_t ElmtSize, const Operand *OpQd,
3774*03ce13f7SAndroid Build Coastguard Worker const Operand *OpAddress, const TargetInfo &TInfo) {
3775*03ce13f7SAndroid Build Coastguard Worker
3776*03ce13f7SAndroid Build Coastguard Worker // This is a pseudo-instruction for storing a single element of a quadword
3777*03ce13f7SAndroid Build Coastguard Worker // vector. For 64-bit the lower doubleword vector is stored.
3778*03ce13f7SAndroid Build Coastguard Worker
3779*03ce13f7SAndroid Build Coastguard Worker if (ElmtSize == 64) {
3780*03ce13f7SAndroid Build Coastguard Worker return vstrq(OpQd, OpAddress, Ice::CondARM32::AL, TInfo);
3781*03ce13f7SAndroid Build Coastguard Worker }
3782*03ce13f7SAndroid Build Coastguard Worker
3783*03ce13f7SAndroid Build Coastguard Worker // VST1 (single element from one lane) - ARMv7-A/R section A8.6.392, encoding
3784*03ce13f7SAndroid Build Coastguard Worker // A1:
3785*03ce13f7SAndroid Build Coastguard Worker // VST1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>
3786*03ce13f7SAndroid Build Coastguard Worker //
3787*03ce13f7SAndroid Build Coastguard Worker // 111101001D00nnnnddd0ss00aaaammmm where Dddd=Qd, nnnn=Rn,
3788*03ce13f7SAndroid Build Coastguard Worker // aaaa=0 (use default alignment), size=ElmtSize, and ss is the
3789*03ce13f7SAndroid Build Coastguard Worker // encoding of ElmtSize.
3790*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vst1qr = "vst1qr";
3791*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vst1qr);
3792*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(Qd);
3793*03ce13f7SAndroid Build Coastguard Worker IValueT Address;
3794*03ce13f7SAndroid Build Coastguard Worker if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) !=
3795*03ce13f7SAndroid Build Coastguard Worker EncodedAsImmRegOffset)
3796*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(Vst1qr) + ": malform memory address");
3797*03ce13f7SAndroid Build Coastguard Worker const IValueT Rn = mask(Address, kRnShift, 4);
3798*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Rm = RegARM32::Reg_pc;
3799*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Opcode = B26 | B23;
3800*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT Align = 0; // use default alignment.
3801*03ce13f7SAndroid Build Coastguard Worker emitVMem1Op(Opcode, Dd, Rn, Rm, ElmtSize, Align, Vst1qr);
3802*03ce13f7SAndroid Build Coastguard Worker }
3803*03ce13f7SAndroid Build Coastguard Worker
vsubs(const Operand * OpSd,const Operand * OpSn,const Operand * OpSm,CondARM32::Cond Cond)3804*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn,
3805*03ce13f7SAndroid Build Coastguard Worker const Operand *OpSm, CondARM32::Cond Cond) {
3806*03ce13f7SAndroid Build Coastguard Worker // VSUB (floating-point) - ARM section A8.8.415, encoding A2:
3807*03ce13f7SAndroid Build Coastguard Worker // vsub<c>.f32 <Sd>, <Sn>, <Sm>
3808*03ce13f7SAndroid Build Coastguard Worker //
3809*03ce13f7SAndroid Build Coastguard Worker // cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
3810*03ce13f7SAndroid Build Coastguard Worker // and mmmmM=Rm.
3811*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vsubs = "vsubs";
3812*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VsubsOpcode = B21 | B20 | B6;
3813*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VsubsOpcode, OpSd, OpSn, OpSm, Vsubs);
3814*03ce13f7SAndroid Build Coastguard Worker }
3815*03ce13f7SAndroid Build Coastguard Worker
vsubd(const Operand * OpDd,const Operand * OpDn,const Operand * OpDm,CondARM32::Cond Cond)3816*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vsubd(const Operand *OpDd, const Operand *OpDn,
3817*03ce13f7SAndroid Build Coastguard Worker const Operand *OpDm, CondARM32::Cond Cond) {
3818*03ce13f7SAndroid Build Coastguard Worker // VSUB (floating-point) - ARM section A8.8.415, encoding A2:
3819*03ce13f7SAndroid Build Coastguard Worker // vsub<c>.f64 <Dd>, <Dn>, <Dm>
3820*03ce13f7SAndroid Build Coastguard Worker //
3821*03ce13f7SAndroid Build Coastguard Worker // cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
3822*03ce13f7SAndroid Build Coastguard Worker // and Mmmmm=Rm.
3823*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vsubd = "vsubd";
3824*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VsubdOpcode = B21 | B20 | B6;
3825*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VsubdOpcode, OpDd, OpDn, OpDm, Vsubd);
3826*03ce13f7SAndroid Build Coastguard Worker }
3827*03ce13f7SAndroid Build Coastguard Worker
vqaddqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3828*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vqaddqi(Type ElmtTy, const Operand *OpQd,
3829*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
3830*03ce13f7SAndroid Build Coastguard Worker // VQADD (integer) - ARM section A8.6.369, encoding A1:
3831*03ce13f7SAndroid Build Coastguard Worker // vqadd<c><q>.s<size> {<Qd>,} <Qn>, <Qm>
3832*03ce13f7SAndroid Build Coastguard Worker //
3833*03ce13f7SAndroid Build Coastguard Worker // 111100100Dssnnn0ddd00000N1M1mmm0 where Dddd=OpQd, Nnnn=OpQn, Mmmm=OpQm,
3834*03ce13f7SAndroid Build Coastguard Worker // size is 8, 16, 32, or 64.
3835*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3836*03ce13f7SAndroid Build Coastguard Worker "vqaddqi expects vector with integer element type");
3837*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vqaddqi = "vqaddqi";
3838*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VqaddqiOpcode = B4;
3839*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VqaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vqaddqi);
3840*03ce13f7SAndroid Build Coastguard Worker }
3841*03ce13f7SAndroid Build Coastguard Worker
vqaddqu(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3842*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vqaddqu(Type ElmtTy, const Operand *OpQd,
3843*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
3844*03ce13f7SAndroid Build Coastguard Worker // VQADD (integer) - ARM section A8.6.369, encoding A1:
3845*03ce13f7SAndroid Build Coastguard Worker // vqadd<c><q>.s<size> {<Qd>,} <Qn>, <Qm>
3846*03ce13f7SAndroid Build Coastguard Worker //
3847*03ce13f7SAndroid Build Coastguard Worker // 111100110Dssnnn0ddd00000N1M1mmm0 where Dddd=OpQd, Nnnn=OpQn, Mmmm=OpQm,
3848*03ce13f7SAndroid Build Coastguard Worker // size is 8, 16, 32, or 64.
3849*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3850*03ce13f7SAndroid Build Coastguard Worker "vqaddqu expects vector with integer element type");
3851*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vqaddqu = "vqaddqu";
3852*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VqaddquOpcode = B24 | B4;
3853*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VqaddquOpcode, ElmtTy, OpQd, OpQm, OpQn, Vqaddqu);
3854*03ce13f7SAndroid Build Coastguard Worker }
3855*03ce13f7SAndroid Build Coastguard Worker
vqsubqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3856*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vqsubqi(Type ElmtTy, const Operand *OpQd,
3857*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
3858*03ce13f7SAndroid Build Coastguard Worker // VQSUB (integer) - ARM section A8.6.369, encoding A1:
3859*03ce13f7SAndroid Build Coastguard Worker // vqsub<c><q>.s<size> {<Qd>,} <Qn>, <Qm>
3860*03ce13f7SAndroid Build Coastguard Worker //
3861*03ce13f7SAndroid Build Coastguard Worker // 111100100Dssnnn0ddd00010N1M1mmm0 where Dddd=OpQd, Nnnn=OpQn, Mmmm=OpQm,
3862*03ce13f7SAndroid Build Coastguard Worker // size is 8, 16, 32, or 64.
3863*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3864*03ce13f7SAndroid Build Coastguard Worker "vqsubqi expects vector with integer element type");
3865*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vqsubqi = "vqsubqi";
3866*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VqsubqiOpcode = B9 | B4;
3867*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VqsubqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vqsubqi);
3868*03ce13f7SAndroid Build Coastguard Worker }
3869*03ce13f7SAndroid Build Coastguard Worker
vqsubqu(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3870*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vqsubqu(Type ElmtTy, const Operand *OpQd,
3871*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
3872*03ce13f7SAndroid Build Coastguard Worker // VQSUB (integer) - ARM section A8.6.369, encoding A1:
3873*03ce13f7SAndroid Build Coastguard Worker // vqsub<c><q>.s<size> {<Qd>,} <Qn>, <Qm>
3874*03ce13f7SAndroid Build Coastguard Worker //
3875*03ce13f7SAndroid Build Coastguard Worker // 111100110Dssnnn0ddd00010N1M1mmm0 where Dddd=OpQd, Nnnn=OpQn, Mmmm=OpQm,
3876*03ce13f7SAndroid Build Coastguard Worker // size is 8, 16, 32, or 64.
3877*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3878*03ce13f7SAndroid Build Coastguard Worker "vqsubqu expects vector with integer element type");
3879*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vqsubqu = "vqsubqu";
3880*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VqsubquOpcode = B24 | B9 | B4;
3881*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VqsubquOpcode, ElmtTy, OpQd, OpQm, OpQn, Vqsubqu);
3882*03ce13f7SAndroid Build Coastguard Worker }
3883*03ce13f7SAndroid Build Coastguard Worker
vsubqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)3884*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vsubqi(Type ElmtTy, const Operand *OpQd,
3885*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
3886*03ce13f7SAndroid Build Coastguard Worker // VSUB (integer) - ARM section A8.8.414, encoding A1:
3887*03ce13f7SAndroid Build Coastguard Worker // vsub.<dt> <Qd>, <Qn>, <Qm>
3888*03ce13f7SAndroid Build Coastguard Worker //
3889*03ce13f7SAndroid Build Coastguard Worker // 111100110Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm,
3890*03ce13f7SAndroid Build Coastguard Worker // and dt in [i8, i16, i32, i64] where ss is the index.
3891*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
3892*03ce13f7SAndroid Build Coastguard Worker "vsubqi expects vector with integer element type");
3893*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vsubqi = "vsubqi";
3894*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VsubqiOpcode = B24 | B11;
3895*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VsubqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vsubqi);
3896*03ce13f7SAndroid Build Coastguard Worker }
3897*03ce13f7SAndroid Build Coastguard Worker
vqmovn2(Type DestElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn,bool Unsigned,bool Saturating)3898*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vqmovn2(Type DestElmtTy, const Operand *OpQd,
3899*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn,
3900*03ce13f7SAndroid Build Coastguard Worker bool Unsigned, bool Saturating) {
3901*03ce13f7SAndroid Build Coastguard Worker // Pseudo-instruction for packing two quadword vectors into one quadword
3902*03ce13f7SAndroid Build Coastguard Worker // vector, narrowing each element using saturation or truncation.
3903*03ce13f7SAndroid Build Coastguard Worker
3904*03ce13f7SAndroid Build Coastguard Worker // VQMOVN - ARMv7-A/R section A8.6.361, encoding A1:
3905*03ce13f7SAndroid Build Coastguard Worker // V{Q}MOVN{U}N<c>.<type><size> <Dd>, <Qm>
3906*03ce13f7SAndroid Build Coastguard Worker //
3907*03ce13f7SAndroid Build Coastguard Worker // 111100111D11ss10dddd0010opM0mmm0 where Ddddd=OpQd, op = 10, Mmmm=OpQm,
3908*03ce13f7SAndroid Build Coastguard Worker // ss is 00 (16-bit), 01 (32-bit), or 10 (64-bit).
3909*03ce13f7SAndroid Build Coastguard Worker
3910*03ce13f7SAndroid Build Coastguard Worker assert(DestElmtTy != IceType_i64 &&
3911*03ce13f7SAndroid Build Coastguard Worker "vmovn doesn't allow i64 destination vector elements!");
3912*03ce13f7SAndroid Build Coastguard Worker
3913*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vqmovn = "vqmovn";
3914*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseQRegs = false;
3915*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsFloatTy = false;
3916*03ce13f7SAndroid Build Coastguard Worker const IValueT Qd = encodeQRegister(OpQd, "Qd", Vqmovn);
3917*03ce13f7SAndroid Build Coastguard Worker const IValueT Qm = encodeQRegister(OpQm, "Qm", Vqmovn);
3918*03ce13f7SAndroid Build Coastguard Worker const IValueT Qn = encodeQRegister(OpQn, "Qn", Vqmovn);
3919*03ce13f7SAndroid Build Coastguard Worker const IValueT Dd = mapQRegToDReg(Qd);
3920*03ce13f7SAndroid Build Coastguard Worker const IValueT Dm = mapQRegToDReg(Qm);
3921*03ce13f7SAndroid Build Coastguard Worker const IValueT Dn = mapQRegToDReg(Qn);
3922*03ce13f7SAndroid Build Coastguard Worker
3923*03ce13f7SAndroid Build Coastguard Worker IValueT VqmovnOpcode = B25 | B24 | B23 | B21 | B20 | B17 | B9 |
3924*03ce13f7SAndroid Build Coastguard Worker (Saturating ? (Unsigned ? B6 : B7) : 0);
3925*03ce13f7SAndroid Build Coastguard Worker
3926*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT ElmtShift = 18;
3927*03ce13f7SAndroid Build Coastguard Worker VqmovnOpcode |= (encodeElmtType(DestElmtTy) << ElmtShift);
3928*03ce13f7SAndroid Build Coastguard Worker
3929*03ce13f7SAndroid Build Coastguard Worker if (Qm != Qd) {
3930*03ce13f7SAndroid Build Coastguard Worker // Narrow second source operand to upper half of destination.
3931*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VqmovnOpcode, Dd + 1, 0, Dn, UseQRegs, IsFloatTy);
3932*03ce13f7SAndroid Build Coastguard Worker // Narrow first source operand to lower half of destination.
3933*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VqmovnOpcode, Dd + 0, 0, Dm, UseQRegs, IsFloatTy);
3934*03ce13f7SAndroid Build Coastguard Worker } else if (Qn != Qd) {
3935*03ce13f7SAndroid Build Coastguard Worker // Narrow first source operand to lower half of destination.
3936*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VqmovnOpcode, Dd + 0, 0, Dm, UseQRegs, IsFloatTy);
3937*03ce13f7SAndroid Build Coastguard Worker // Narrow second source operand to upper half of destination.
3938*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VqmovnOpcode, Dd + 1, 0, Dn, UseQRegs, IsFloatTy);
3939*03ce13f7SAndroid Build Coastguard Worker } else {
3940*03ce13f7SAndroid Build Coastguard Worker // Narrow first source operand to lower half of destination.
3941*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VqmovnOpcode, Dd, 0, Dm, UseQRegs, IsFloatTy);
3942*03ce13f7SAndroid Build Coastguard Worker
3943*03ce13f7SAndroid Build Coastguard Worker // VMOV Dd, Dm
3944*03ce13f7SAndroid Build Coastguard Worker // 111100100D10mmmmdddd0001MQM1mmmm
3945*03ce13f7SAndroid Build Coastguard Worker const IValueT VmovOpcode = B25 | B21 | B8 | B4;
3946*03ce13f7SAndroid Build Coastguard Worker
3947*03ce13f7SAndroid Build Coastguard Worker emitSIMDBase(VmovOpcode, Dd + 1, Dd, Dd, UseQRegs, IsFloatTy);
3948*03ce13f7SAndroid Build Coastguard Worker }
3949*03ce13f7SAndroid Build Coastguard Worker }
3950*03ce13f7SAndroid Build Coastguard Worker
vsubqf(const Operand * OpQd,const Operand * OpQn,const Operand * OpQm)3951*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vsubqf(const Operand *OpQd, const Operand *OpQn,
3952*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm) {
3953*03ce13f7SAndroid Build Coastguard Worker // VSUB (floating-point) - ARM section A8.8.415, Encoding A1:
3954*03ce13f7SAndroid Build Coastguard Worker // vsub.f32 <Qd>, <Qn>, <Qm>
3955*03ce13f7SAndroid Build Coastguard Worker //
3956*03ce13f7SAndroid Build Coastguard Worker // 111100100D10nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm.
3957*03ce13f7SAndroid Build Coastguard Worker assert(OpQd->getType() == IceType_v4f32 && "vsubqf expects type <4 x float>");
3958*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vsubqf = "vsubqf";
3959*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VsubqfOpcode = B21 | B11 | B8;
3960*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VsubqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vsubqf);
3961*03ce13f7SAndroid Build Coastguard Worker }
3962*03ce13f7SAndroid Build Coastguard Worker
emitVStackOp(CondARM32::Cond Cond,IValueT Opcode,const Variable * OpBaseReg,SizeT NumConsecRegs)3963*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
3964*03ce13f7SAndroid Build Coastguard Worker const Variable *OpBaseReg,
3965*03ce13f7SAndroid Build Coastguard Worker SizeT NumConsecRegs) {
3966*03ce13f7SAndroid Build Coastguard Worker const IValueT BaseReg = getEncodedSRegNum(OpBaseReg);
3967*03ce13f7SAndroid Build Coastguard Worker const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register.
3968*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register.
3969*03ce13f7SAndroid Build Coastguard Worker assert(0 < NumConsecRegs);
3970*03ce13f7SAndroid Build Coastguard Worker (void)VpushVpopMaxConsecRegs;
3971*03ce13f7SAndroid Build Coastguard Worker assert(NumConsecRegs <= VpushVpopMaxConsecRegs);
3972*03ce13f7SAndroid Build Coastguard Worker assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs());
3973*03ce13f7SAndroid Build Coastguard Worker assert(CondARM32::isDefined(Cond));
3974*03ce13f7SAndroid Build Coastguard Worker const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit |
3975*03ce13f7SAndroid Build Coastguard Worker (Rd << kRdShift) | NumConsecRegs;
3976*03ce13f7SAndroid Build Coastguard Worker emitInst(Encoding);
3977*03ce13f7SAndroid Build Coastguard Worker }
3978*03ce13f7SAndroid Build Coastguard Worker
vpop(const Variable * OpBaseReg,SizeT NumConsecRegs,CondARM32::Cond Cond)3979*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
3980*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3981*03ce13f7SAndroid Build Coastguard Worker // Note: Current implementation assumes that OpBaseReg is defined using S
3982*03ce13f7SAndroid Build Coastguard Worker // registers. It doesn't implement the D register form.
3983*03ce13f7SAndroid Build Coastguard Worker //
3984*03ce13f7SAndroid Build Coastguard Worker // VPOP - ARM section A8.8.367, encoding A2:
3985*03ce13f7SAndroid Build Coastguard Worker // vpop<c> <RegList>
3986*03ce13f7SAndroid Build Coastguard Worker //
3987*03ce13f7SAndroid Build Coastguard Worker // cccc11001D111101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and
3988*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=NumConsecRegs.
3989*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VpopOpcode =
3990*03ce13f7SAndroid Build Coastguard Worker B27 | B26 | B23 | B21 | B20 | B19 | B18 | B16 | B11 | B9;
3991*03ce13f7SAndroid Build Coastguard Worker emitVStackOp(Cond, VpopOpcode, OpBaseReg, NumConsecRegs);
3992*03ce13f7SAndroid Build Coastguard Worker }
3993*03ce13f7SAndroid Build Coastguard Worker
vpush(const Variable * OpBaseReg,SizeT NumConsecRegs,CondARM32::Cond Cond)3994*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vpush(const Variable *OpBaseReg, SizeT NumConsecRegs,
3995*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
3996*03ce13f7SAndroid Build Coastguard Worker // Note: Current implementation assumes that OpBaseReg is defined using S
3997*03ce13f7SAndroid Build Coastguard Worker // registers. It doesn't implement the D register form.
3998*03ce13f7SAndroid Build Coastguard Worker //
3999*03ce13f7SAndroid Build Coastguard Worker // VPUSH - ARM section A8.8.368, encoding A2:
4000*03ce13f7SAndroid Build Coastguard Worker // vpush<c> <RegList>
4001*03ce13f7SAndroid Build Coastguard Worker //
4002*03ce13f7SAndroid Build Coastguard Worker // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and
4003*03ce13f7SAndroid Build Coastguard Worker // iiiiiiii=NumConsecRegs.
4004*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VpushOpcode =
4005*03ce13f7SAndroid Build Coastguard Worker B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9;
4006*03ce13f7SAndroid Build Coastguard Worker emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs);
4007*03ce13f7SAndroid Build Coastguard Worker }
4008*03ce13f7SAndroid Build Coastguard Worker
vshlqi(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)4009*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vshlqi(Type ElmtTy, const Operand *OpQd,
4010*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
4011*03ce13f7SAndroid Build Coastguard Worker // VSHL - ARM section A8.8.396, encoding A1:
4012*03ce13f7SAndroid Build Coastguard Worker // vshl Qd, Qm, Qn
4013*03ce13f7SAndroid Build Coastguard Worker //
4014*03ce13f7SAndroid Build Coastguard Worker // 1111001U0Dssnnnndddd0100NQM0mmmm where Ddddd=Qd, Mmmmm=Qm, Nnnnn=Qn, 0=U,
4015*03ce13f7SAndroid Build Coastguard Worker // 1=Q
4016*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
4017*03ce13f7SAndroid Build Coastguard Worker "vshl expects vector with integer element type");
4018*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vshl = "vshl";
4019*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VshlOpcode = B10 | B6;
4020*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl);
4021*03ce13f7SAndroid Build Coastguard Worker }
4022*03ce13f7SAndroid Build Coastguard Worker
vshlqc(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const ConstantInteger32 * Imm6)4023*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vshlqc(Type ElmtTy, const Operand *OpQd,
4024*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm,
4025*03ce13f7SAndroid Build Coastguard Worker const ConstantInteger32 *Imm6) {
4026*03ce13f7SAndroid Build Coastguard Worker // VSHL - ARM section A8.8.395, encoding A1:
4027*03ce13f7SAndroid Build Coastguard Worker // vshl Qd, Qm, #Imm
4028*03ce13f7SAndroid Build Coastguard Worker //
4029*03ce13f7SAndroid Build Coastguard Worker // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6,
4030*03ce13f7SAndroid Build Coastguard Worker // 0=U, 1=Q, 0=L.
4031*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
4032*03ce13f7SAndroid Build Coastguard Worker "vshl expects vector with integer element type");
4033*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vshl = "vshl";
4034*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VshlOpcode = B23 | B10 | B8 | B4;
4035*03ce13f7SAndroid Build Coastguard Worker emitSIMDShiftqqc(VshlOpcode, OpQd, OpQm,
4036*03ce13f7SAndroid Build Coastguard Worker encodeSIMDShiftImm6(ST_Vshl, ElmtTy, Imm6), Vshl);
4037*03ce13f7SAndroid Build Coastguard Worker }
4038*03ce13f7SAndroid Build Coastguard Worker
vshrqc(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const ConstantInteger32 * Imm6,InstARM32::FPSign Sign)4039*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vshrqc(Type ElmtTy, const Operand *OpQd,
4040*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const ConstantInteger32 *Imm6,
4041*03ce13f7SAndroid Build Coastguard Worker InstARM32::FPSign Sign) {
4042*03ce13f7SAndroid Build Coastguard Worker // VSHR - ARM section A8.8.398, encoding A1:
4043*03ce13f7SAndroid Build Coastguard Worker // vshr Qd, Qm, #Imm
4044*03ce13f7SAndroid Build Coastguard Worker //
4045*03ce13f7SAndroid Build Coastguard Worker // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6,
4046*03ce13f7SAndroid Build Coastguard Worker // U=Unsigned, Q=1, L=0.
4047*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
4048*03ce13f7SAndroid Build Coastguard Worker "vshr expects vector with integer element type");
4049*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vshr = "vshr";
4050*03ce13f7SAndroid Build Coastguard Worker const IValueT VshrOpcode =
4051*03ce13f7SAndroid Build Coastguard Worker (Sign == InstARM32::FS_Unsigned ? B24 : 0) | B23 | B4;
4052*03ce13f7SAndroid Build Coastguard Worker emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm,
4053*03ce13f7SAndroid Build Coastguard Worker encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr);
4054*03ce13f7SAndroid Build Coastguard Worker }
4055*03ce13f7SAndroid Build Coastguard Worker
vshlqu(Type ElmtTy,const Operand * OpQd,const Operand * OpQm,const Operand * OpQn)4056*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vshlqu(Type ElmtTy, const Operand *OpQd,
4057*03ce13f7SAndroid Build Coastguard Worker const Operand *OpQm, const Operand *OpQn) {
4058*03ce13f7SAndroid Build Coastguard Worker // VSHL - ARM section A8.8.396, encoding A1:
4059*03ce13f7SAndroid Build Coastguard Worker // vshl Qd, Qm, Qn
4060*03ce13f7SAndroid Build Coastguard Worker //
4061*03ce13f7SAndroid Build Coastguard Worker // 1111001U0Dssnnnndddd0100NQM0mmmm where Ddddd=Qd, Mmmmm=Qm, Nnnnn=Qn, 1=U,
4062*03ce13f7SAndroid Build Coastguard Worker // 1=Q
4063*03ce13f7SAndroid Build Coastguard Worker assert(isScalarIntegerType(ElmtTy) &&
4064*03ce13f7SAndroid Build Coastguard Worker "vshl expects vector with integer element type");
4065*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vshl = "vshl";
4066*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VshlOpcode = B24 | B10 | B6;
4067*03ce13f7SAndroid Build Coastguard Worker emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl);
4068*03ce13f7SAndroid Build Coastguard Worker }
4069*03ce13f7SAndroid Build Coastguard Worker
vsqrtd(const Operand * OpDd,const Operand * OpDm,CondARM32::Cond Cond)4070*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vsqrtd(const Operand *OpDd, const Operand *OpDm,
4071*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
4072*03ce13f7SAndroid Build Coastguard Worker // VSQRT - ARM section A8.8.401, encoding A1:
4073*03ce13f7SAndroid Build Coastguard Worker // vsqrt<c>.f64 <Dd>, <Dm>
4074*03ce13f7SAndroid Build Coastguard Worker //
4075*03ce13f7SAndroid Build Coastguard Worker // cccc11101D110001dddd101111M0mmmm where cccc=Cond, Ddddd=Sd, and Mmmmm=Sm.
4076*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vsqrtd = "vsqrtd";
4077*03ce13f7SAndroid Build Coastguard Worker IValueT Dd = encodeDRegister(OpDd, "Dd", Vsqrtd);
4078*03ce13f7SAndroid Build Coastguard Worker IValueT Dm = encodeDRegister(OpDm, "Dm", Vsqrtd);
4079*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VsqrtdOpcode = B23 | B21 | B20 | B16 | B7 | B6;
4080*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT D0 = 0;
4081*03ce13f7SAndroid Build Coastguard Worker emitVFPddd(Cond, VsqrtdOpcode, Dd, D0, Dm);
4082*03ce13f7SAndroid Build Coastguard Worker }
4083*03ce13f7SAndroid Build Coastguard Worker
vsqrts(const Operand * OpSd,const Operand * OpSm,CondARM32::Cond Cond)4084*03ce13f7SAndroid Build Coastguard Worker void AssemblerARM32::vsqrts(const Operand *OpSd, const Operand *OpSm,
4085*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond Cond) {
4086*03ce13f7SAndroid Build Coastguard Worker // VSQRT - ARM section A8.8.401, encoding A1:
4087*03ce13f7SAndroid Build Coastguard Worker // vsqrt<c>.f32 <Sd>, <Sm>
4088*03ce13f7SAndroid Build Coastguard Worker //
4089*03ce13f7SAndroid Build Coastguard Worker // cccc11101D110001dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
4090*03ce13f7SAndroid Build Coastguard Worker constexpr const char *Vsqrts = "vsqrts";
4091*03ce13f7SAndroid Build Coastguard Worker IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts);
4092*03ce13f7SAndroid Build Coastguard Worker IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts);
4093*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6;
4094*03ce13f7SAndroid Build Coastguard Worker constexpr IValueT S0 = 0;
4095*03ce13f7SAndroid Build Coastguard Worker emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm);
4096*03ce13f7SAndroid Build Coastguard Worker }
4097*03ce13f7SAndroid Build Coastguard Worker
4098*03ce13f7SAndroid Build Coastguard Worker } // end of namespace ARM32
4099*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
4100