blob: 43c3f56152bde78056e78f843729d1fc300d0854 [file] [log] [blame]
John Portoaff4ccf2015-06-10 16:35:06 -07001//===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===//
Jan Voungb36ad9b2015-04-21 17:01:49 -07002//
3// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
4// for details. All rights reserved. Use of this source code is governed by a
5// BSD-style license that can be found in the LICENSE file.
6//
7// Modified by the Subzero authors.
8//
9//===----------------------------------------------------------------------===//
10//
11// The Subzero Code Generator
12//
13// This file is distributed under the University of Illinois Open Source
14// License. See LICENSE.TXT for details.
15//
16//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -070017///
18/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080019/// \brief Declares the Assembler class for ARM32.
Andrew Scull9612d322015-07-06 14:53:25 -070020///
Karl Schimpf85342a72015-10-13 09:49:31 -070021/// Note: All references to ARM "section" documentation refers to the "ARM
22/// Architecture Reference Manual, ARMv7-A and ARMv7-R edition". See:
23/// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c
24///
Jan Voungb36ad9b2015-04-21 17:01:49 -070025//===----------------------------------------------------------------------===//
26
John Portoaff4ccf2015-06-10 16:35:06 -070027#ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H
28#define SUBZERO_SRC_ICEASSEMBLERARM32_H
Jan Voungb36ad9b2015-04-21 17:01:49 -070029
John Portoaff4ccf2015-06-10 16:35:06 -070030#include "IceAssembler.h"
Karl Schimpfc5abdc12015-10-09 13:29:13 -070031#include "IceConditionCodesARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070032#include "IceDefs.h"
33#include "IceFixups.h"
Karl Schimpf85342a72015-10-13 09:49:31 -070034#include "IceInstARM32.h"
Karl Schimpfc5abdc12015-10-09 13:29:13 -070035#include "IceRegistersARM32.h"
36#include "IceTargetLowering.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070037
Jan Voungb36ad9b2015-04-21 17:01:49 -070038namespace Ice {
Jan Voung90ccc3f2015-04-30 14:15:10 -070039namespace ARM32 {
Jan Voungb36ad9b2015-04-21 17:01:49 -070040
Karl Schimpf7cb2db32015-10-29 14:04:12 -070041/// Handles encoding of bottom/top 16 bits of an address using movw/movt.
Karl Schimpf174531e2015-11-18 08:19:26 -080042class MoveRelocatableFixup final : public AssemblerFixup {
Karl Schimpf7cb2db32015-10-29 14:04:12 -070043 MoveRelocatableFixup &operator=(const MoveRelocatableFixup &) = delete;
44 MoveRelocatableFixup(const MoveRelocatableFixup &) = default;
45
46public:
47 MoveRelocatableFixup() = default;
Karl Schimpf174531e2015-11-18 08:19:26 -080048 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
John Porto6e8d3fa2016-02-04 10:35:20 -080049 void emitOffset(Assembler *Asm) const;
Karl Schimpf174531e2015-11-18 08:19:26 -080050};
51
52/// Handles encoding of branch and link to global location.
53class BlRelocatableFixup final : public AssemblerFixup {
54 BlRelocatableFixup(const BlRelocatableFixup &) = delete;
55 BlRelocatableFixup &operator=(const BlRelocatableFixup &) = delete;
56
57public:
58 BlRelocatableFixup() = default;
59 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
John Porto6e8d3fa2016-02-04 10:35:20 -080060 void emitOffset(Assembler *Asm) const;
Karl Schimpf7cb2db32015-10-29 14:04:12 -070061};
62
Jan Voungb36ad9b2015-04-21 17:01:49 -070063class AssemblerARM32 : public Assembler {
64 AssemblerARM32(const AssemblerARM32 &) = delete;
65 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete;
66
67public:
Karl Schimpfbb0bacf2015-11-11 15:42:55 -080068 // Rotation values.
69 enum RotationValue {
70 kRotateNone, // Omitted
71 kRotate8, // ror #8
72 kRotate16, // ror #16
73 kRotate24 // ror #24
74 };
75
Karl Schimpf18cce422016-02-04 13:54:53 -080076 // Encoding of the number of D registers in a list of D registers.
77 enum DRegListSize {
78 DRegListSize1 = 7, // 0b0111
79 DRegListSize2 = 10, // 0b1010
80 DRegListSIze3 = 6, // 0b0110
81 DRegListSize4 = 2 // 0b0010
82 };
83
Karl Schimpf2c68d902015-11-11 15:37:50 -080084 class TargetInfo {
85 TargetInfo(const TargetInfo &) = delete;
86 TargetInfo &operator=(const TargetInfo &) = delete;
87
88 public:
Jim Stichnoth8aa39662016-02-10 11:20:30 -080089 TargetInfo(bool HasFramePointer, RegNumT FrameOrStackReg)
David Sehr26217e32015-11-26 13:03:50 -080090 : HasFramePointer(HasFramePointer), FrameOrStackReg(FrameOrStackReg) {}
Karl Schimpf2c68d902015-11-11 15:37:50 -080091 explicit TargetInfo(const TargetLowering *Target)
92 : HasFramePointer(Target->hasFramePointer()),
David Sehr26217e32015-11-26 13:03:50 -080093 FrameOrStackReg(Target->getFrameOrStackReg()) {}
Karl Schimpf2c68d902015-11-11 15:37:50 -080094 const bool HasFramePointer;
Jim Stichnoth8aa39662016-02-10 11:20:30 -080095 const RegNumT FrameOrStackReg;
Karl Schimpf2c68d902015-11-11 15:37:50 -080096 };
97
John Portodc619252016-02-10 15:57:16 -080098 explicit AssemblerARM32(bool IsNonsfi, bool use_far_branches = false)
99 : Assembler(Asm_ARM32), IsNonsfi(IsNonsfi) {
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700100 // TODO(kschimpf): Add mode if needed when branches are handled.
Jan Voungb36ad9b2015-04-21 17:01:49 -0700101 (void)use_far_branches;
102 }
Karl Schimpf50a33312015-10-23 09:19:48 -0700103 ~AssemblerARM32() override {
104 if (BuildDefs::asserts()) {
105 for (const Label *Label : CfgNodeLabels) {
106 Label->finalCheck();
107 }
108 for (const Label *Label : LocalLabels) {
109 Label->finalCheck();
110 }
111 }
112 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700113
Karl Schimpf7cb2db32015-10-29 14:04:12 -0700114 MoveRelocatableFixup *createMoveFixup(bool IsMovW, const Constant *Value);
115
Karl Schimpf515e8c22015-11-30 11:19:16 -0800116 BlRelocatableFixup *createBlFixup(const ConstantRelocatable *BlTarget);
Karl Schimpf174531e2015-11-18 08:19:26 -0800117
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700118 void alignFunction() override {
119 const SizeT Align = 1 << getBundleAlignLog2Bytes();
120 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
Karl Schimpf137e62b2015-10-27 07:28:09 -0700121 constexpr SizeT InstSize = sizeof(IValueT);
Karl Schimpf856734c2015-11-05 08:18:26 -0800122 assert(BytesNeeded % InstARM32::InstSize == 0);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700123 while (BytesNeeded > 0) {
Karl Schimpf7de24352015-12-17 08:55:10 -0800124 trap();
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700125 BytesNeeded -= InstSize;
126 }
127 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700128
129 SizeT getBundleAlignLog2Bytes() const override { return 4; }
130
Andrew Scull86df4e92015-07-30 13:54:44 -0700131 const char *getAlignDirective() const override { return ".p2alignl"; }
Jan Voungb2d50842015-05-12 09:53:50 -0700132
Karl Schimpf7de24352015-12-17 08:55:10 -0800133 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700134
Karl Schimpf67574d82015-12-08 15:37:00 -0800135 void padWithNop(intptr_t Padding) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700136
Jan Voungc2ec5812015-08-05 09:35:18 -0700137 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
Karl Schimpf85342a72015-10-13 09:49:31 -0700138 assert(NodeNumber < CfgNodeLabels.size());
139 return CfgNodeLabels[NodeNumber];
Andrew Scull86df4e92015-07-30 13:54:44 -0700140 }
141
Karl Schimpf137e62b2015-10-27 07:28:09 -0700142 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
143 return getOrCreateLabel(NodeNumber, CfgNodeLabels);
144 }
145
146 Label *getOrCreateLocalLabel(SizeT Number) {
147 return getOrCreateLabel(Number, LocalLabels);
148 }
Karl Schimpf50a33312015-10-23 09:19:48 -0700149
Karl Schimpfd4699942016-04-02 09:55:31 -0700150 void bindLocalLabel(const InstARM32Label *InstL, SizeT Number) {
151 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
Karl Schimpfcb504ca2015-11-04 08:02:07 -0800152 constexpr SizeT InstSize = 0;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700153 emitTextInst(InstL->getLabelName() + ":", InstSize);
Karl Schimpfcb504ca2015-11-04 08:02:07 -0800154 }
Karl Schimpf50a33312015-10-23 09:19:48 -0700155 Label *L = getOrCreateLocalLabel(Number);
156 if (!getPreliminary())
157 this->bind(L);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700158 }
159
160 bool fixupIsPCRel(FixupKind Kind) const override {
Jim Stichnoth3e324002016-03-08 16:18:40 -0800161 if (Kind == llvm::ELF::R_ARM_MOVW_PREL_NC)
162 return true;
163 if (Kind == llvm::ELF::R_ARM_MOVT_PREL)
164 return true;
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700165 return false;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700166 }
Karl Schimpf372bdd62015-10-13 14:39:14 -0700167
Karl Schimpf856734c2015-11-05 08:18:26 -0800168 /// Accessors to keep track of the number of bytes generated inside
169 /// InstARM32::emit() methods, when run inside of
170 /// InstARM32::emitUsingTextFixup().
171 void resetEmitTextSize() { EmitTextSize = 0; }
172 void incEmitTextSize(size_t Amount) { EmitTextSize += Amount; }
173 void decEmitTextSize(size_t Amount) { EmitTextSize -= Amount; }
174 size_t getEmitTextSize() const { return EmitTextSize; }
175
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700176 void bind(Label *label);
177
Karl Schimpf372bdd62015-10-13 14:39:14 -0700178 // List of instructions implemented by integrated assembler.
179
Karl Schimpfdb098882015-10-27 07:36:59 -0700180 void adc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
181 bool SetFlags, CondARM32::Cond Cond);
182
Karl Schimpf372bdd62015-10-13 14:39:14 -0700183 void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
184 bool SetFlags, CondARM32::Cond Cond);
185
Karl Schimpfc33f7bb2015-10-29 15:50:32 -0700186 void and_(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
187 bool SetFlags, CondARM32::Cond Cond);
188
Karl Schimpf3ac9a492015-12-08 13:41:38 -0800189 void asr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
190 bool SetFlags, CondARM32::Cond Cond);
191
Karl Schimpf137e62b2015-10-27 07:28:09 -0700192 void b(Label *L, CondARM32::Cond Cond);
193
Karl Schimpf85342a72015-10-13 09:49:31 -0700194 void bkpt(uint16_t Imm16);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700195
Karl Schimpf4f8805b2015-11-02 15:01:56 -0800196 void bic(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
197 bool SetFlags, CondARM32::Cond Cond);
198
Karl Schimpf174531e2015-11-18 08:19:26 -0800199 void bl(const ConstantRelocatable *Target);
200
201 void blx(const Operand *Target);
202
203 void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
204
Karl Schimpf65f80d72015-12-17 08:02:17 -0800205 void clz(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
206
Karl Schimpf4c435d32015-12-08 14:45:28 -0800207 void cmn(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
208
Karl Schimpf174531e2015-11-18 08:19:26 -0800209 void cmp(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
210
Karl Schimpfd3f94f72015-12-09 07:35:00 -0800211 void dmb(IValueT Option); // Option is a 4-bit value.
212
Karl Schimpf62d367b2015-10-30 08:06:44 -0700213 void eor(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
214 bool SetFlags, CondARM32::Cond Cond);
215
Karl Schimpf2c68d902015-11-11 15:37:50 -0800216 void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
217 const TargetInfo &TInfo);
218
219 void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
220 const TargetLowering *Lowering) {
221 const TargetInfo TInfo(Lowering);
222 ldr(OpRt, OpAddress, Cond, TInfo);
223 }
Karl Schimpf745ad1d2015-10-16 10:31:31 -0700224
Karl Schimpf4175d452015-12-17 08:06:01 -0800225 void ldrex(const Operand *OpRt, const Operand *OpAddress,
226 CondARM32::Cond Cond, const TargetInfo &TInfo);
227
228 void ldrex(const Operand *OpRt, const Operand *OpAddress,
229 CondARM32::Cond Cond, const TargetLowering *Lowering) {
230 const TargetInfo TInfo(Lowering);
231 ldrex(OpRt, OpAddress, Cond, TInfo);
232 }
233
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800234 void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
235 bool SetFlags, CondARM32::Cond Cond);
236
Karl Schimpf4ddce702015-12-07 10:43:34 -0800237 void lsr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
238 bool SetFlags, CondARM32::Cond Cond);
239
Karl Schimpf372bdd62015-10-13 14:39:14 -0700240 void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
Karl Schimpf85342a72015-10-13 09:49:31 -0700241
Karl Schimpf7cb2db32015-10-29 14:04:12 -0700242 void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
243
244 void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
245
Karl Schimpf080b65b2015-11-05 08:27:51 -0800246 void mla(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
247 const Operand *OpRa, CondARM32::Cond Cond);
248
Karl Schimpfa990f0c2015-12-18 07:36:02 -0800249 void mls(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
250 const Operand *OpRa, CondARM32::Cond Cond);
251
Karl Schimpfb81b9012015-11-04 14:54:52 -0800252 void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
253 bool SetFlags, CondARM32::Cond Cond);
254
Karl Schimpfe559be72015-11-20 14:26:12 -0800255 void mvn(const Operand *OpRd, const Operand *OpScc, CondARM32::Cond Cond);
256
Karl Schimpf67574d82015-12-08 15:37:00 -0800257 void nop();
258
Karl Schimpf9c08bee2015-10-30 07:42:00 -0700259 void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
260 bool SetFlags, CondARM32::Cond Cond);
261
Karl Schimpfc411dbf2016-01-11 09:59:19 -0800262 void pop(const Variable *OpRt, CondARM32::Cond Cond);
Karl Schimpff66a85b2015-11-10 14:12:35 -0800263
264 // Note: Registers is a bitset, where bit n corresponds to register Rn.
265 void popList(const IValueT Registers, CondARM32::Cond Cond);
266
Karl Schimpf6cab5612015-11-06 09:14:10 -0800267 void push(const Operand *OpRt, CondARM32::Cond Cond);
268
269 // Note: Registers is a bitset, where bit n corresponds to register Rn.
270 void pushList(const IValueT Registers, CondARM32::Cond Cond);
271
Karl Schimpf17fe1942015-12-18 07:41:06 -0800272 void rbit(const Operand *OpRd, const Operand *OpRm, CondARM32::Cond Cond);
273
274 void rev(const Operand *OpRd, const Operand *OpRm, CondARM32::Cond Cond);
Karl Schimpf7e87b612015-12-11 09:32:28 -0800275
Karl Schimpfdca86742015-12-04 15:11:43 -0800276 void rsb(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
277 bool SetFlags, CondARM32::Cond Cond);
278
Karl Schimpf337ac9e2015-12-11 09:12:07 -0800279 void rsc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
280 bool SetFlags, CondARM32::Cond Cond);
281
Karl Schimpf3b8a15e2015-10-29 09:11:40 -0700282 void sbc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
283 bool SetFlags, CondARM32::Cond Cond);
284
Karl Schimpf697dc792015-10-30 13:21:59 -0700285 void sdiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
286 CondARM32::Cond Cond);
287
Karl Schimpf2c68d902015-11-11 15:37:50 -0800288 void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
289 const TargetInfo &TInfo);
290
291 void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
292 const TargetLowering *Lowering) {
293 const TargetInfo TInfo(Lowering);
294 str(OpRt, OpAddress, Cond, TInfo);
295 }
Karl Schimpf745ad1d2015-10-16 10:31:31 -0700296
Karl Schimpf4175d452015-12-17 08:06:01 -0800297 void strex(const Operand *OpRd, const Operand *OpRt, const Operand *OpAddress,
298 CondARM32::Cond Cond, const TargetInfo &TInfo);
299
300 void strex(const Operand *OpRd, const Operand *OpRt, const Operand *OpAddress,
301 CondARM32::Cond Cond, const TargetLowering *Lowering) {
302 const TargetInfo TInfo(Lowering);
303 strex(OpRd, OpRt, OpAddress, Cond, TInfo);
304 }
305
Karl Schimpfe3455052015-10-14 14:30:21 -0700306 void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
307 bool SetFlags, CondARM32::Cond Cond);
308
Karl Schimpf1e67f912015-12-08 11:17:23 -0800309 // Implements sxtb/sxth depending on type of OpSrc0.
310 void sxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
311
Karl Schimpf7de24352015-12-17 08:55:10 -0800312 void trap();
313
Karl Schimpfb81b9012015-11-04 14:54:52 -0800314 void tst(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
315
Karl Schimpf1c285502015-10-30 15:00:24 -0700316 void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
317 CondARM32::Cond Cond);
318
Karl Schimpf430e8442015-11-09 12:16:20 -0800319 void umull(const Operand *OpRdLo, const Operand *OpRdHi, const Operand *OpRn,
320 const Operand *OpRm, CondARM32::Cond Cond);
321
Karl Schimpfbb0bacf2015-11-11 15:42:55 -0800322 // Implements uxtb/uxth depending on type of OpSrc0.
323 void uxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
324
Karl Schimpfbd4356d2016-02-02 13:35:45 -0800325 void vabss(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
326
Karl Schimpf425e06b2016-02-17 09:51:23 -0800327 void vabsd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond);
328
329 void vabsq(const Operand *OpQd, const Operand *OpQm);
Karl Schimpfbd4356d2016-02-02 13:35:45 -0800330
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800331 void vaddd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
332 CondARM32::Cond Cond);
333
334 void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
335 CondARM32::Cond Cond);
336
Karl Schimpf2c0764e2016-02-01 13:44:37 -0800337 // Integer vector add.
338 void vaddqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
339 const Operand *OpQn);
340
341 // Float vector add.
342 void vaddqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
343
Karl Schimpffd7975f2016-02-02 11:25:10 -0800344 void vandq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
345
John Porto397f6022016-04-15 06:26:58 -0700346 void vbslq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
347
John Portoa4d100a2016-04-18 15:32:27 -0700348 void vceqqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
349 const Operand *OpQn);
350
351 void vceqqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
352
353 void vcgeqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
354 const Operand *OpQn);
355
356 void vcugeqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
357 const Operand *OpQn);
358
359 void vcgeqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
360
361 void vcgtqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
362 const Operand *OpQn);
363
364 void vcugtqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
365 const Operand *OpQn);
366
367 void vcgtqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
368
Karl Schimpfcd5e07e2016-01-11 10:12:20 -0800369 void vcmpd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond cond);
370
371 // Second argument of compare is zero (+0.0).
372 void vcmpdz(const Operand *OpDd, CondARM32::Cond cond);
373
374 void vcmps(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond cond);
375
376 // Second argument of compare is zero (+0.0).
377 void vcmpsz(const Operand *OpSd, CondARM32::Cond cond);
378
Karl Schimpf6c7181c2016-01-08 07:31:08 -0800379 void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
380
Karl Schimpf94cc3e62016-01-22 08:33:50 -0800381 // vcvt<c>.S32.F32
382 void vcvtis(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
383
Karl Schimpfab389f22016-01-22 15:08:44 -0800384 // vcvt<c>.S32.F64
385 void vcvtid(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
386
387 // vcvt<c>.F64.S32
388 void vcvtdi(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
389
390 // vcvt<c>.F64.U32
391 void vcvtdu(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
392
Karl Schimpf94cc3e62016-01-22 08:33:50 -0800393 void vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
394
Karl Schimpfab389f22016-01-22 15:08:44 -0800395 // vcvt<c>.F32.S32
396 void vcvtsi(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
397
398 // vcvt<c>.F32.U32
399 void vcvtsu(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
400
401 // vcvt<c>.U32.F64
402 void vcvtud(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
403
404 // vcvt<c>.u32.f32
405 void vcvtus(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
406
John Portoe88c7de2016-04-14 11:51:38 -0700407 void vcvtqsi(const Operand *OpQd, const Operand *OpQm);
408
409 void vcvtqsu(const Operand *OpQd, const Operand *OpQm);
410
411 void vcvtqis(const Operand *OpQd, const Operand *OpQm);
412
413 void vcvtqus(const Operand *OpQd, const Operand *OpQm);
414
Karl Schimpf3dbe7802016-01-07 13:37:39 -0800415 void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
416 CondARM32::Cond Cond);
417
418 void vdivs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
419 CondARM32::Cond Cond);
420
Karl Schimpf53378c12016-01-21 10:16:43 -0800421 void veord(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm);
422
Karl Schimpf625dfb32016-02-03 13:21:50 -0800423 void veorq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
424
Karl Schimpfe1d71382016-01-21 09:47:14 -0800425 void vldrd(const Operand *OpDd, const Operand *OpAddress,
426 CondARM32::Cond Cond, const TargetInfo &TInfo);
427
428 void vldrd(const Operand *OpDd, const Operand *OpAddress,
429 CondARM32::Cond Cond, const TargetLowering *Lowering) {
430 const TargetInfo TInfo(Lowering);
431 vldrd(OpDd, OpAddress, Cond, TInfo);
432 }
433
434 void vldrs(const Operand *OpSd, const Operand *OpAddress,
435 CondARM32::Cond Cond, const TargetInfo &TInfo);
436
437 void vldrs(const Operand *OpSd, const Operand *OpAddress,
438 CondARM32::Cond Cond, const TargetLowering *Lowering) {
439 const TargetInfo TInfo(Lowering);
440 vldrs(OpSd, OpAddress, Cond, TInfo);
441 }
442
Nicolas Capens675e15b2017-09-27 15:06:35 -0400443 void vldrq(const Operand *OpQd, const Operand *OpAddress,
444 CondARM32::Cond Cond, const TargetInfo &TInfo);
445
446 void vldrq(const Operand *OpQd, const Operand *OpAddress,
447 CondARM32::Cond Cond, const TargetLowering *Lowering) {
448 const TargetInfo TInfo(Lowering);
449 vldrq(OpQd, OpAddress, Cond, TInfo);
450 }
451
Karl Schimpf18cce422016-02-04 13:54:53 -0800452 // ElmtSize = #bits in vector element.
453 void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
454 const TargetInfo &TInfo);
455
Nicolas Capens675e15b2017-09-27 15:06:35 -0400456 void vld1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
457 const TargetInfo &TInfo);
458
Karl Schimpf18cce422016-02-04 13:54:53 -0800459 void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
460 const TargetLowering *Lowering) {
461 const TargetInfo TInfo(Lowering);
462 vld1qr(ElmtSize, OpQd, OpRn, TInfo);
463 }
464
Nicolas Capens675e15b2017-09-27 15:06:35 -0400465 void vld1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
466 const TargetLowering *Lowering) {
467 const TargetInfo TInfo(Lowering);
468 vld1(ElmtSize, OpQd, OpRn, TInfo);
469 }
470
Karl Schimpfb627f092016-04-11 14:32:15 -0700471 // Qn[i] = Imm for all i in vector. Returns true iff Imm can be defined as an
472 // Imm8 using AdvSIMDExpandImm().
473 bool vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm);
474
Karl Schimpf6de32b22016-02-10 13:30:48 -0800475 // Dn = FpImm
Karl Schimpfc64448f2016-01-26 11:12:29 -0800476 void vmovd(const Operand *OpDn, const OperandARM32FlexFpImm *OpFpImm,
477 CondARM32::Cond Cond);
478
Karl Schimpf6de32b22016-02-10 13:30:48 -0800479 // Dd = Dm
Karl Schimpfac186fd2016-01-27 15:39:32 -0800480 void vmovdd(const Operand *OpDd, const Variable *OpDm, CondARM32::Cond Cond);
Karl Schimpf9aedc2e2016-01-27 13:36:09 -0800481
Karl Schimpf6de32b22016-02-10 13:30:48 -0800482 // Dm = Rt:Rt2
Karl Schimpfa880ac82016-01-29 07:28:05 -0800483 void vmovdrr(const Operand *OpDm, const Operand *OpRt, const Operand *OpRt2,
484 CondARM32::Cond Cond);
485
Karl Schimpf6de32b22016-02-10 13:30:48 -0800486 // Qd[Index] = Rt
487 void vmovqir(const Operand *OpQd, uint32_t Index, const Operand *OpRt,
488 CondARM32::Cond Cond);
489
490 // Qd[Index] = Sm
491 void vmovqis(const Operand *OpQd, uint32_t Indx, const Operand *OpSm,
492 CondARM32::Cond Cond);
493
494 // Rt = Qm[Index]
495 void vmovrqi(const Operand *OpRt, const Operand *OpQd, uint32_t Index,
496 CondARM32::Cond Cond);
497
498 // Rt:Rt2 = Dm
Karl Schimpfa880ac82016-01-29 07:28:05 -0800499 void vmovrrd(const Operand *OpRt, const Operand *OpRt2, const Operand *OpDm,
500 CondARM32::Cond Cond);
501
Karl Schimpf6de32b22016-02-10 13:30:48 -0800502 // Rt = Sn
Karl Schimpfe1b65742016-01-27 15:36:18 -0800503 void vmovrs(const Operand *OpRt, const Operand *OpSn, CondARM32::Cond Cond);
504
Karl Schimpf6de32b22016-02-10 13:30:48 -0800505 // Sn = FpImm
Karl Schimpfc64448f2016-01-26 11:12:29 -0800506 void vmovs(const Operand *OpSn, const OperandARM32FlexFpImm *OpFpImm,
507 CondARM32::Cond Cond);
508
Karl Schimpf6de32b22016-02-10 13:30:48 -0800509 // Sd = Sm
510 void vmovss(const Operand *OpSd, const Variable *OpSm, CondARM32::Cond Cond);
Karl Schimpf9aedc2e2016-01-27 13:36:09 -0800511
Karl Schimpf6de32b22016-02-10 13:30:48 -0800512 // Sd = Qm[Index]
513 void vmovsqi(const Operand *OpSd, const Operand *OpQm, uint32_t Index,
514 CondARM32::Cond Cond);
515
516 // Sn = Rt
Karl Schimpf4ff90be2016-01-22 15:15:50 -0800517 void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
518
Karl Schimpfbd8e28e2016-01-26 12:25:43 -0800519 void vmlad(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
520 CondARM32::Cond Cond);
521
522 void vmlas(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
523 CondARM32::Cond Cond);
524
Karl Schimpf694cdbd2016-01-29 07:23:20 -0800525 void vmlsd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
526 CondARM32::Cond Cond);
527
528 void vmlss(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
529 CondARM32::Cond Cond);
530
Karl Schimpfee718272016-01-25 09:17:26 -0800531 // Uses APSR_nzcv as register
532 void vmrsAPSR_nzcv(CondARM32::Cond Cond);
533
Karl Schimpf8a105fd2016-01-07 13:46:20 -0800534 void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
535 CondARM32::Cond Cond);
536
Karl Schimpf341158a2016-02-03 13:27:01 -0800537 // Integer vector multiply.
538 void vmulqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
539 const Operand *OpQm);
540
Nicolas Capens675e15b2017-09-27 15:06:35 -0400541 // Integer vector multiply high.
542 void vmulh(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
543 const Operand *OpQm, bool Unsigned);
544
545 // Integer vector multiply add pairwise.
546 void vmlap(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
547 const Operand *OpQm);
548
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400549 // Vector element replication.
550 void vdup(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, IValueT Idx);
551
552 // Vector interleave lower halves.
553 void vzip(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
554 const Operand *OpQm);
555
Karl Schimpf341158a2016-02-03 13:27:01 -0800556 // Float vector multiply.
557 void vmulqf(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
558
Karl Schimpf8a105fd2016-01-07 13:46:20 -0800559 void vmuls(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
560 CondARM32::Cond Cond);
561
John Portoa4d100a2016-04-18 15:32:27 -0700562 void vmvnq(const Operand *OpQd, const Operand *OpQm);
563
Nicolas Capensf6951fa2017-10-02 10:44:03 -0400564 void vmovlq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
565 void vmovhq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
566 void vmovhlq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
567 void vmovlhq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
568
John Portoa4d100a2016-04-18 15:32:27 -0700569 void vnegqs(const Operand *OpQd, const Operand *OpQm);
570
John Porto15e77d42016-04-13 12:57:14 -0700571 void vnegqs(Type ElmtTy, const Operand *OpQd, const Operand *OpQm);
572
Karl Schimpfe2955752016-02-02 12:57:30 -0800573 void vorrq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
574
Karl Schimpfa3c32142015-12-18 08:26:16 -0800575 void vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
576 CondARM32::Cond Cond);
577
578 void vpush(const Variable *OpBaseReg, SizeT NumConsecRegs,
579 CondARM32::Cond Cond);
580
John Porto15e77d42016-04-13 12:57:14 -0700581 void vshlqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
582 const Operand *OpQn);
583
584 void vshlqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
585 const Operand *OpQn);
586
John Portoe88c7de2016-04-14 11:51:38 -0700587 void vshlqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
588 const ConstantInteger32 *OpQn);
589
Nicolas Capens8d90a342017-09-27 14:33:11 -0400590 void vshrqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
591 const ConstantInteger32 *OpQn, InstARM32::FPSign Sign);
John Portoe88c7de2016-04-14 11:51:38 -0700592
Karl Schimpf266c5a22016-01-29 09:54:58 -0800593 void vsqrtd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond);
594
595 void vsqrts(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
596
Karl Schimpf4a55a602016-01-21 10:02:15 -0800597 void vstrd(const Operand *OpDd, const Operand *OpAddress,
598 CondARM32::Cond Cond, const TargetInfo &TInfo);
599
600 void vstrd(const Operand *OpDd, const Operand *OpAddress,
601 CondARM32::Cond Cond, const TargetLowering *Lowering) {
602 const TargetInfo TInfo(Lowering);
603 vstrd(OpDd, OpAddress, Cond, TInfo);
604 }
605
606 void vstrs(const Operand *OpSd, const Operand *OpAddress,
607 CondARM32::Cond Cond, const TargetInfo &TInfo);
608
609 void vstrs(const Operand *OpSd, const Operand *OpAddress,
610 CondARM32::Cond Cond, const TargetLowering *Lowering) {
611 const TargetInfo TInfo(Lowering);
612 vstrs(OpSd, OpAddress, Cond, TInfo);
613 }
614
Nicolas Capens675e15b2017-09-27 15:06:35 -0400615 void vstrq(const Operand *OpQd, const Operand *OpAddress,
616 CondARM32::Cond Cond, const TargetInfo &TInfo);
617
618 void vstrq(const Operand *OpQd, const Operand *OpAddress,
619 CondARM32::Cond Cond, const TargetLowering *Lowering) {
620 const TargetInfo TInfo(Lowering);
621 vstrq(OpQd, OpAddress, Cond, TInfo);
622 }
623
Karl Schimpf18cce422016-02-04 13:54:53 -0800624 // ElmtSize = #bits in vector element.
625 void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress,
626 const TargetInfo &TInfo);
627
628 void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
629 const TargetLowering *Lowering) {
630 const TargetInfo TInfo(Lowering);
631 vst1qr(ElmtSize, OpQd, OpRn, TInfo);
632 }
633
Nicolas Capens675e15b2017-09-27 15:06:35 -0400634 void vst1(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress,
635 const TargetInfo &TInfo);
636
637 void vst1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
638 const TargetLowering *Lowering) {
639 const TargetInfo TInfo(Lowering);
640 vst1(ElmtSize, OpQd, OpRn, TInfo);
641 }
642
Karl Schimpfb3e25742016-01-07 10:20:27 -0800643 void vsubd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
644 CondARM32::Cond Cond);
645
Karl Schimpf50cfcb02016-02-02 10:19:20 -0800646 // Integer vector subtract.
647 void vsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
648 const Operand *OpQn);
649
Casey Dahlinb40560b2017-06-28 13:58:58 -0700650 // Integer vector saturating subtract.
651 void vqsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
652 const Operand *OpQn);
653 void vqsubqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
654 const Operand *OpQn);
655
656 // Integer vector saturating add.
657 void vqaddqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
658 const Operand *OpQn);
659 void vqaddqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
660 const Operand *OpQn);
661
Nicolas Capens675e15b2017-09-27 15:06:35 -0400662 // Integer vector packing with optional saturation.
663 void vqmovn2(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
664 const Operand *OpQn, bool Unsigned, bool Saturating);
665
Karl Schimpf50cfcb02016-02-02 10:19:20 -0800666 // Float vector subtract
667 void vsubqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
668
Karl Schimpfb3e25742016-01-07 10:20:27 -0800669 void vsubs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
670 CondARM32::Cond Cond);
671
John Porto2da710c2015-06-29 07:57:02 -0700672 static bool classof(const Assembler *Asm) {
673 return Asm->getKind() == Asm_ARM32;
674 }
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700675
Karl Schimpf856734c2015-11-05 08:18:26 -0800676 void emitTextInst(const std::string &Text, SizeT InstSize);
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700677
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700678private:
John Porto53611e22015-12-30 07:30:10 -0800679 ENABLE_MAKE_UNIQUE;
680
John Portodc619252016-02-10 15:57:16 -0800681 const bool IsNonsfi;
682
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700683 // A vector of pool-allocated x86 labels for CFG nodes.
684 using LabelVector = std::vector<Label *>;
685 LabelVector CfgNodeLabels;
Karl Schimpf50a33312015-10-23 09:19:48 -0700686 // A vector of pool-allocated x86 labels for Local labels.
687 LabelVector LocalLabels;
Karl Schimpf856734c2015-11-05 08:18:26 -0800688 // Number of bytes emitted by InstARM32::emit() methods, when run inside
689 // InstARM32::emitUsingTextFixup().
690 size_t EmitTextSize = 0;
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700691
Karl Schimpf6cab5612015-11-06 09:14:10 -0800692 // Load/store multiple addressing mode.
693 enum BlockAddressMode {
694 // bit encoding P U W
695 DA = (0 | 0 | 0) << 21, // decrement after
696 IA = (0 | 4 | 0) << 21, // increment after
697 DB = (8 | 0 | 0) << 21, // decrement before
698 IB = (8 | 4 | 0) << 21, // increment before
699 DA_W = (0 | 0 | 1) << 21, // decrement after with writeback to base
700 IA_W = (0 | 4 | 1) << 21, // increment after with writeback to base
701 DB_W = (8 | 0 | 1) << 21, // decrement before with writeback to base
702 IB_W = (8 | 4 | 1) << 21 // increment before with writeback to base
703 };
704
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700705 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700706
Karl Schimpf137e62b2015-10-27 07:28:09 -0700707 void bindCfgNodeLabel(const CfgNode *Node) override;
708
Karl Schimpf425e06b2016-02-17 09:51:23 -0800709 // SIMD encoding for the vector ElmtTy.
710 static IValueT encodeElmtType(Type ElmtTy);
711
Karl Schimpf237afed2016-01-25 09:54:20 -0800712 void emitInst(IValueT Value) {
713 AssemblerBuffer::EnsureCapacity _(&Buffer);
714 Buffer.emit<IValueT>(Value);
715 }
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700716
Karl Schimpfb81b9012015-11-04 14:54:52 -0800717 // List of possible checks to apply when calling emitType01() (below).
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800718 enum EmitChecks { NoChecks, RdIsPcAndSetFlags };
719
Karl Schimpf0437ae82015-12-04 07:29:10 -0800720 // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=InstType,
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800721 // s=SetFlags, oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM
722 // section A5.2.3).
Karl Schimpf0437ae82015-12-04 07:29:10 -0800723 void emitType01(CondARM32::Cond Cond, IValueT InstType, IValueT Opcode,
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800724 bool SetFlags, IValueT Rn, IValueT Rd, IValueT imm12,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800725 EmitChecks RuleChecks, const char *InstName);
Karl Schimpfb81b9012015-11-04 14:54:52 -0800726
727 // Converts appropriate representation on a data operation, and then calls
728 // emitType01 above.
Karl Schimpf0437ae82015-12-04 07:29:10 -0800729 void emitType01(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
730 const Operand *OpRn, const Operand *OpSrc1, bool SetFlags,
731 EmitChecks RuleChecks, const char *InstName);
Karl Schimpfb81b9012015-11-04 14:54:52 -0800732
733 // Same as above, but the value for Rd and Rn have already been converted
734 // into instruction values.
Karl Schimpf0437ae82015-12-04 07:29:10 -0800735 void emitType01(CondARM32::Cond Cond, IValueT Opcode, IValueT OpRd,
736 IValueT OpRn, const Operand *OpSrc1, bool SetFlags,
737 EmitChecks RuleChecks, const char *InstName);
Karl Schimpf62d367b2015-10-30 08:06:44 -0700738
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800739 void emitType05(CondARM32::Cond Cond, int32_t Offset, bool Link);
Karl Schimpf745ad1d2015-10-16 10:31:31 -0700740
Karl Schimpf19567882015-12-02 10:24:15 -0800741 // Emit ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond,
742 // ooo=InstType, l=isLoad, b=isByte, and
743 // aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that Address is assumed to be
744 // defined by decodeAddress() in IceAssemblerARM32.cpp.
Karl Schimpf137e62b2015-10-27 07:28:09 -0700745 void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad,
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800746 bool IsByte, IValueT Rt, IValueT Address);
Karl Schimpf19567882015-12-02 10:24:15 -0800747
Karl Schimpf17fe1942015-12-18 07:41:06 -0800748 // Emit ccccxxxxxxxxxxxxddddxxxxxxxxmmmm where cccc=Cond,
749 // xxxxxxxxxxxx0000xxxxxxxx0000=Opcode, dddd=Rd, and mmmm=Rm.
750 void emitRdRm(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
751 const Operand *OpRm, const char *InstName);
752
Karl Schimpf19567882015-12-02 10:24:15 -0800753 // Emit ldr/ldrb/str/strb instruction with given address.
754 void emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, IValueT Rt,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800755 const Operand *OpAddress, const TargetInfo &TInfo,
756 const char *InstName);
Karl Schimpf19567882015-12-02 10:24:15 -0800757
758 // Emit ldrh/ldrd/strh/strd instruction with given address using encoding 3.
759 void emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, IValueT Rt,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800760 const Operand *OpAddress, const TargetInfo &TInfo,
761 const char *InstName);
Karl Schimpf137e62b2015-10-27 07:28:09 -0700762
Karl Schimpf4175d452015-12-17 08:06:01 -0800763 // Emit cccc00011xxlnnnndddd11111001tttt where cccc=Cond, xx encodes type
764 // size, l=IsLoad, nnnn=Rn (as defined by OpAddress), and tttt=Rt.
765 void emitMemExOp(CondARM32::Cond, Type Ty, bool IsLoad, const Operand *OpRd,
766 IValueT Rt, const Operand *OpAddress,
767 const TargetInfo &TInfo, const char *InstName);
768
Karl Schimpf6cab5612015-11-06 09:14:10 -0800769 // Pattern cccc100aaaalnnnnrrrrrrrrrrrrrrrr where cccc=Cond,
770 // aaaa<<21=AddressMode, l=IsLoad, nnnn=BaseReg, and
771 // rrrrrrrrrrrrrrrr is bitset of Registers.
772 void emitMultiMemOp(CondARM32::Cond Cond, BlockAddressMode AddressMode,
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800773 bool IsLoad, IValueT BaseReg, IValueT Registers);
Karl Schimpf6cab5612015-11-06 09:14:10 -0800774
Karl Schimpfa3c32142015-12-18 08:26:16 -0800775 // Pattern ccccxxxxxDxxxxxxddddxxxxiiiiiiii where cccc=Cond, ddddD=BaseReg,
776 // iiiiiiii=NumConsecRegs, and xxxxx0xxxxxx0000xxxx00000000=Opcode.
777 void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800778 const Variable *OpBaseReg, SizeT NumConsecRegs);
Karl Schimpfa3c32142015-12-18 08:26:16 -0800779
Karl Schimpf6c7181c2016-01-08 07:31:08 -0800780 // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, ddddD=Sd,
781 // Mmmmm=Dm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
782 void emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Dm);
783
784 // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, Ddddd=Dd,
785 // mmmmM=Sm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
786 void emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Sm);
787
Karl Schimpf18cce422016-02-04 13:54:53 -0800788 // Pattern 111100000D00nnnnddddttttssaammmm | Opcode where Ddddd=Dd, nnnn=Rn,
789 // mmmmm=Rm, tttt=NumDRegs, ElmtSize in {8, 16, 32, 64) and defines ss, and
790 // aa=Align.
791 void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm,
792 DRegListSize NumDRegs, size_t ElmtSize, IValueT Align,
793 const char *InstName);
794
Nicolas Capens675e15b2017-09-27 15:06:35 -0400795 // Pattern 111100000D00nnnnddddss00aaaammmm | Opcode where Ddddd=Dd, nnnn=Rn,
796 // mmmmm=Rm, ElmtSize in {8, 16, 32) and defines ss, and aa=Align.
797 void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm,
798 size_t ElmtSize, IValueT Align, const char *InstName);
799
Karl Schimpf697dc792015-10-30 13:21:59 -0700800 // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond,
801 // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm.
802 void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800803 IValueT Rm);
Karl Schimpf697dc792015-10-30 13:21:59 -0700804
Karl Schimpf6de32b22016-02-10 13:30:48 -0800805 // cccc1110iiiennnntttt1011Njj10000 where cccc=Cond, tttt=Rt, Ndddd=2*Qn=Dn,
806 // iii=Opcode1, jj=Opcode2, Opcode1Opcode2 encodes Index and the
807 // corresponding element size of the vector element, and e=IsExtract.
808 void emitInsertExtractInt(CondARM32::Cond Cond, const Operand *OpQn,
809 uint32_t Index, const Operand *OpRt, bool IsExtract,
810 const char *InstName);
811
812 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
813 // Assigns Sd the value of Sm.
814 void emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm);
815
Karl Schimpf396de532015-10-30 07:25:43 -0700816 // Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800817 // mmmm=Rm, ssss=Rs, f=SetFlags and xxxxxxx=Opcode.
Karl Schimpf396de532015-10-30 07:25:43 -0700818 void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800819 IValueT Rm, IValueT Rs, bool SetFlags);
Karl Schimpf396de532015-10-30 07:25:43 -0700820
Karl Schimpf4ddce702015-12-07 10:43:34 -0800821 // Pattern cccc0001101s0000ddddxxxxxtt0mmmm where cccc=Cond, s=SetFlags,
822 // dddd=Rd, mmmm=Rm, tt=Shift, and xxxxx is defined by OpSrc1. OpSrc1 defines
823 // either xxxxx=Imm5, or xxxxx=ssss0 where ssss=Rs.
824 void emitShift(const CondARM32::Cond Cond,
825 const OperandARM32::ShiftKind Shift, const Operand *OpRd,
826 const Operand *OpRm, const Operand *OpSrc1,
827 const bool SetFlags, const char *InstName);
828
Karl Schimpf1e67f912015-12-08 11:17:23 -0800829 // Implements various forms of signed/unsigned extend value, using pattern
Karl Schimpfbb0bacf2015-11-11 15:42:55 -0800830 // ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
831 // nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm.
Karl Schimpf1e67f912015-12-08 11:17:23 -0800832 void emitSignExtend(CondARM32::Cond, IValueT Opcode, const Operand *OpRd,
833 const Operand *OpSrc0, const char *InstName);
Karl Schimpfbb0bacf2015-11-11 15:42:55 -0800834
Karl Schimpf2c0764e2016-02-01 13:44:37 -0800835 // Implements various forms of vector (SIMD) operations. Implements pattern
Karl Schimpf425e06b2016-02-17 09:51:23 -0800836 // 111100100D00nnnndddn00F0NQM0mmmm where Dddd=Dd, Nnnn=Dn, Mmmm=Dm,
837 // Q=UseQRegs, F=IsFloatTy, and Opcode is unioned into the pattern.
838 void emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn, IValueT Dm,
839 bool UseQRegs, bool IsFloatTy);
840
841 // Same as emitSIMDBase above, except ElmtShift=20 and ElmtSize is computed
842 // from ElmtTy.
Karl Schimpf2c0764e2016-02-01 13:44:37 -0800843 void emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, IValueT Dn, IValueT Dm,
844 bool UseQRegs);
845
846 // Implements various integer forms of vector (SIMD) operations using Q
Karl Schimpf425e06b2016-02-17 09:51:23 -0800847 // registers. Implements pattern 111100100D00nnn0ddd000F0N1M0mmm0 where
848 // Dddd=Qd, Nnnn=Qn, Mmmm=Qm, F=IsFloatTy, and Opcode is unioned into the
849 // pattern.
850 void emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd, const Operand *OpQn,
851 const Operand *OpQm, bool IsFloatTy,
852 const char *OpcodeName);
853
854 // Same as emitSIMD above, except ElmtShift=20 and ElmtSize is computed from
855 // ElmtTy.
Karl Schimpf2c0764e2016-02-01 13:44:37 -0800856 void emitSIMDqqq(IValueT Opcode, Type ElmtTy, const Operand *OpQd,
857 const Operand *OpQn, const Operand *OpQm,
858 const char *OpcodeName);
859
John Portoe88c7de2016-04-14 11:51:38 -0700860 // Implements various forms of vector (SIMD) shifts using Q registers.
861 // Implements pattern 111100101Diiiiiidddd010101M1mmmm where Dddd=Qd, Mmmm=Qm,
862 // iiiiii=Imm6, and Opcode is unioned into the pattern.
863 void emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd,
864 const Operand *OpQm, const IValueT Imm6,
865 const char *OpcodeName);
866
867 // Implements various forms of vector (SIMD) casts between (signed and
868 // unsigned) integer and floating point types (f32). Implements pattern
869 // 111100111D11ss11dddd011ooQM0mmmm where Dddd=Qd, Mmmm=Qm, 10=ss, op=00, 1=Q,
870 // and Opcode is unioned into the pattern.
871 void emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd, const Operand *OpQm,
872 const char *CvtName);
873
Karl Schimpfb81b9012015-11-04 14:54:52 -0800874 // Pattern cccctttxxxxnnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn,
875 // ttt=Instruction type (derived from OpSrc1), iiiiiiiiiiii is derived from
876 // OpSrc1, and xxxx=Opcode.
Karl Schimpf0437ae82015-12-04 07:29:10 -0800877 void emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRn,
878 const Operand *OpSrc1, const char *CmpName);
Karl Schimpfb81b9012015-11-04 14:54:52 -0800879
Karl Schimpf137e62b2015-10-27 07:28:09 -0700880 void emitBranch(Label *L, CondARM32::Cond, bool Link);
881
Karl Schimpf137e62b2015-10-27 07:28:09 -0700882 // Returns the offset encoded in the branch instruction Inst.
883 static IOffsetT decodeBranchOffset(IValueT Inst);
Karl Schimpf5ff0cfb2015-11-11 14:47:49 -0800884
Karl Schimpf7cfe9a02015-12-04 15:07:01 -0800885 // Implements movw/movt, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii
886 // where cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and
Karl Schimpf5ff0cfb2015-11-11 14:47:49 -0800887 // iiiiiiiiiiiiiiii=Imm16.
Karl Schimpf7cfe9a02015-12-04 15:07:01 -0800888 void emitMovwt(CondARM32::Cond Cond, bool IsMovw, const Operand *OpRd,
889 const Operand *OpSrc, const char *MovName);
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800890
891 // Emit VFP instruction with 3 D registers.
Karl Schimpfbd8e28e2016-01-26 12:25:43 -0800892 void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpDd,
893 const Operand *OpDn, const Operand *OpDm,
894 const char *InstName);
895
Karl Schimpf4acf11a2016-01-07 07:31:19 -0800896 void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Dn,
897 IValueT Dm);
898
899 // Emit VFP instruction with 3 S registers.
900 void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Sn,
901 IValueT Sm);
Karl Schimpfbd8e28e2016-01-26 12:25:43 -0800902
903 void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpSd,
904 const Operand *OpSn, const Operand *OpSm,
905 const char *InstName);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700906};
907
Jan Voung90ccc3f2015-04-30 14:15:10 -0700908} // end of namespace ARM32
Jan Voungb36ad9b2015-04-21 17:01:49 -0700909} // end of namespace Ice
910
John Portoaff4ccf2015-06-10 16:35:06 -0700911#endif // SUBZERO_SRC_ICEASSEMBLERARM32_H