blob: 6c5007f47db97111f62d9ce43b3c60d9a5827fc0 [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 Schimpf137e62b2015-10-27 07:28:09 -070041/// Encoding of an ARM 32-bit instruction.
42using IValueT = uint32_t;
43
44/// An Offset value (+/-) used in an ARM 32-bit instruction.
45using IOffsetT = int32_t;
46
Karl Schimpf7cb2db32015-10-29 14:04:12 -070047/// Handles encoding of bottom/top 16 bits of an address using movw/movt.
Karl Schimpf174531e2015-11-18 08:19:26 -080048class MoveRelocatableFixup final : public AssemblerFixup {
Karl Schimpf7cb2db32015-10-29 14:04:12 -070049 MoveRelocatableFixup &operator=(const MoveRelocatableFixup &) = delete;
50 MoveRelocatableFixup(const MoveRelocatableFixup &) = default;
51
52public:
53 MoveRelocatableFixup() = default;
Karl Schimpf174531e2015-11-18 08:19:26 -080054 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
55};
56
57/// Handles encoding of branch and link to global location.
58class BlRelocatableFixup final : public AssemblerFixup {
59 BlRelocatableFixup(const BlRelocatableFixup &) = delete;
60 BlRelocatableFixup &operator=(const BlRelocatableFixup &) = delete;
61
62public:
63 BlRelocatableFixup() = default;
64 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
Karl Schimpf7cb2db32015-10-29 14:04:12 -070065};
66
Jan Voungb36ad9b2015-04-21 17:01:49 -070067class AssemblerARM32 : public Assembler {
68 AssemblerARM32(const AssemblerARM32 &) = delete;
69 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete;
70
71public:
Karl Schimpfbb0bacf2015-11-11 15:42:55 -080072 // Rotation values.
73 enum RotationValue {
74 kRotateNone, // Omitted
75 kRotate8, // ror #8
76 kRotate16, // ror #16
77 kRotate24 // ror #24
78 };
79
Karl Schimpf2c68d902015-11-11 15:37:50 -080080 class TargetInfo {
81 TargetInfo(const TargetInfo &) = delete;
82 TargetInfo &operator=(const TargetInfo &) = delete;
83
84 public:
David Sehr26217e32015-11-26 13:03:50 -080085 TargetInfo(bool HasFramePointer, SizeT FrameOrStackReg)
86 : HasFramePointer(HasFramePointer), FrameOrStackReg(FrameOrStackReg) {}
Karl Schimpf2c68d902015-11-11 15:37:50 -080087 explicit TargetInfo(const TargetLowering *Target)
88 : HasFramePointer(Target->hasFramePointer()),
David Sehr26217e32015-11-26 13:03:50 -080089 FrameOrStackReg(Target->getFrameOrStackReg()) {}
Karl Schimpf2c68d902015-11-11 15:37:50 -080090 const bool HasFramePointer;
91 const SizeT FrameOrStackReg;
Karl Schimpf2c68d902015-11-11 15:37:50 -080092 };
93
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070094 explicit AssemblerARM32(bool use_far_branches = false)
95 : Assembler(Asm_ARM32) {
Karl Schimpfc5abdc12015-10-09 13:29:13 -070096 // TODO(kschimpf): Add mode if needed when branches are handled.
Jan Voungb36ad9b2015-04-21 17:01:49 -070097 (void)use_far_branches;
98 }
Karl Schimpf50a33312015-10-23 09:19:48 -070099 ~AssemblerARM32() override {
100 if (BuildDefs::asserts()) {
101 for (const Label *Label : CfgNodeLabels) {
102 Label->finalCheck();
103 }
104 for (const Label *Label : LocalLabels) {
105 Label->finalCheck();
106 }
107 }
108 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700109
Karl Schimpf7cb2db32015-10-29 14:04:12 -0700110 MoveRelocatableFixup *createMoveFixup(bool IsMovW, const Constant *Value);
111
Karl Schimpf515e8c22015-11-30 11:19:16 -0800112 BlRelocatableFixup *createBlFixup(const ConstantRelocatable *BlTarget);
Karl Schimpf174531e2015-11-18 08:19:26 -0800113
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700114 void alignFunction() override {
115 const SizeT Align = 1 << getBundleAlignLog2Bytes();
116 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
Karl Schimpf137e62b2015-10-27 07:28:09 -0700117 constexpr IValueT UndefinedInst = 0xe7fedef0; // udf #60896
118 constexpr SizeT InstSize = sizeof(IValueT);
Karl Schimpf856734c2015-11-05 08:18:26 -0800119 assert(BytesNeeded % InstARM32::InstSize == 0);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700120 while (BytesNeeded > 0) {
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700121 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
122 emitInst(UndefinedInst);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700123 BytesNeeded -= InstSize;
124 }
125 }
Jan Voungb36ad9b2015-04-21 17:01:49 -0700126
127 SizeT getBundleAlignLog2Bytes() const override { return 4; }
128
Andrew Scull86df4e92015-07-30 13:54:44 -0700129 const char *getAlignDirective() const override { return ".p2alignl"; }
Jan Voungb2d50842015-05-12 09:53:50 -0700130
Jan Voungb36ad9b2015-04-21 17:01:49 -0700131 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
Jan Voungb2d50842015-05-12 09:53:50 -0700132 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0
133 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943
134 static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0};
135 return llvm::ArrayRef<uint8_t>(Padding, 4);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700136 }
137
Karl Schimpf67574d82015-12-08 15:37:00 -0800138 void padWithNop(intptr_t Padding) override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700139
Jan Voungc2ec5812015-08-05 09:35:18 -0700140 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
Karl Schimpf85342a72015-10-13 09:49:31 -0700141 assert(NodeNumber < CfgNodeLabels.size());
142 return CfgNodeLabels[NodeNumber];
Andrew Scull86df4e92015-07-30 13:54:44 -0700143 }
144
Karl Schimpf137e62b2015-10-27 07:28:09 -0700145 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
146 return getOrCreateLabel(NodeNumber, CfgNodeLabels);
147 }
148
149 Label *getOrCreateLocalLabel(SizeT Number) {
150 return getOrCreateLabel(Number, LocalLabels);
151 }
Karl Schimpf50a33312015-10-23 09:19:48 -0700152
Karl Schimpfcb504ca2015-11-04 08:02:07 -0800153 void bindLocalLabel(const Cfg *Func, const InstARM32Label *InstL,
154 SizeT Number) {
155 if (BuildDefs::dump() &&
156 !Func->getContext()->getFlags().getDisableHybridAssembly()) {
157 constexpr SizeT InstSize = 0;
158 emitTextInst(InstL->getName(Func) + ":", InstSize);
159 }
Karl Schimpf50a33312015-10-23 09:19:48 -0700160 Label *L = getOrCreateLocalLabel(Number);
161 if (!getPreliminary())
162 this->bind(L);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700163 }
164
165 bool fixupIsPCRel(FixupKind Kind) const override {
166 (void)Kind;
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700167 // TODO(kschimpf) Decide if we need this.
168 return false;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700169 }
Karl Schimpf372bdd62015-10-13 14:39:14 -0700170
Karl Schimpf856734c2015-11-05 08:18:26 -0800171 /// Accessors to keep track of the number of bytes generated inside
172 /// InstARM32::emit() methods, when run inside of
173 /// InstARM32::emitUsingTextFixup().
174 void resetEmitTextSize() { EmitTextSize = 0; }
175 void incEmitTextSize(size_t Amount) { EmitTextSize += Amount; }
176 void decEmitTextSize(size_t Amount) { EmitTextSize -= Amount; }
177 size_t getEmitTextSize() const { return EmitTextSize; }
178
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700179 void bind(Label *label);
180
Karl Schimpf372bdd62015-10-13 14:39:14 -0700181 // List of instructions implemented by integrated assembler.
182
Karl Schimpfdb098882015-10-27 07:36:59 -0700183 void adc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
184 bool SetFlags, CondARM32::Cond Cond);
185
Karl Schimpf372bdd62015-10-13 14:39:14 -0700186 void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
187 bool SetFlags, CondARM32::Cond Cond);
188
Karl Schimpfc33f7bb2015-10-29 15:50:32 -0700189 void and_(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
190 bool SetFlags, CondARM32::Cond Cond);
191
Karl Schimpf3ac9a492015-12-08 13:41:38 -0800192 void asr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
193 bool SetFlags, CondARM32::Cond Cond);
194
Karl Schimpf137e62b2015-10-27 07:28:09 -0700195 void b(Label *L, CondARM32::Cond Cond);
196
Karl Schimpf85342a72015-10-13 09:49:31 -0700197 void bkpt(uint16_t Imm16);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700198
Karl Schimpf4f8805b2015-11-02 15:01:56 -0800199 void bic(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
200 bool SetFlags, CondARM32::Cond Cond);
201
Karl Schimpf174531e2015-11-18 08:19:26 -0800202 void bl(const ConstantRelocatable *Target);
203
204 void blx(const Operand *Target);
205
206 void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
207
Karl Schimpf65f80d72015-12-17 08:02:17 -0800208 void clz(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
209
Karl Schimpf4c435d32015-12-08 14:45:28 -0800210 void cmn(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
211
Karl Schimpf174531e2015-11-18 08:19:26 -0800212 void cmp(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
213
Karl Schimpfd3f94f72015-12-09 07:35:00 -0800214 void dmb(IValueT Option); // Option is a 4-bit value.
215
Karl Schimpf62d367b2015-10-30 08:06:44 -0700216 void eor(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
217 bool SetFlags, CondARM32::Cond Cond);
218
Karl Schimpf2c68d902015-11-11 15:37:50 -0800219 void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
220 const TargetInfo &TInfo);
221
222 void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
223 const TargetLowering *Lowering) {
224 const TargetInfo TInfo(Lowering);
225 ldr(OpRt, OpAddress, Cond, TInfo);
226 }
Karl Schimpf745ad1d2015-10-16 10:31:31 -0700227
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800228 void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
229 bool SetFlags, CondARM32::Cond Cond);
230
Karl Schimpf4ddce702015-12-07 10:43:34 -0800231 void lsr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
232 bool SetFlags, CondARM32::Cond Cond);
233
Karl Schimpf372bdd62015-10-13 14:39:14 -0700234 void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
Karl Schimpf85342a72015-10-13 09:49:31 -0700235
Karl Schimpf7cb2db32015-10-29 14:04:12 -0700236 void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
237
238 void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
239
Karl Schimpf080b65b2015-11-05 08:27:51 -0800240 void mla(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
241 const Operand *OpRa, CondARM32::Cond Cond);
242
Karl Schimpfb81b9012015-11-04 14:54:52 -0800243 void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
244 bool SetFlags, CondARM32::Cond Cond);
245
Karl Schimpfe559be72015-11-20 14:26:12 -0800246 void mvn(const Operand *OpRd, const Operand *OpScc, CondARM32::Cond Cond);
247
Karl Schimpf67574d82015-12-08 15:37:00 -0800248 void nop();
249
Karl Schimpf9c08bee2015-10-30 07:42:00 -0700250 void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
251 bool SetFlags, CondARM32::Cond Cond);
252
Karl Schimpff66a85b2015-11-10 14:12:35 -0800253 void pop(const Operand *OpRt, CondARM32::Cond Cond);
254
255 // Note: Registers is a bitset, where bit n corresponds to register Rn.
256 void popList(const IValueT Registers, CondARM32::Cond Cond);
257
Karl Schimpf6cab5612015-11-06 09:14:10 -0800258 void push(const Operand *OpRt, CondARM32::Cond Cond);
259
260 // Note: Registers is a bitset, where bit n corresponds to register Rn.
261 void pushList(const IValueT Registers, CondARM32::Cond Cond);
262
Karl Schimpf7e87b612015-12-11 09:32:28 -0800263 void rev(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
264
Karl Schimpfdca86742015-12-04 15:11:43 -0800265 void rsb(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
266 bool SetFlags, CondARM32::Cond Cond);
267
Karl Schimpf337ac9e2015-12-11 09:12:07 -0800268 void rsc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
269 bool SetFlags, CondARM32::Cond Cond);
270
Karl Schimpf3b8a15e2015-10-29 09:11:40 -0700271 void sbc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
272 bool SetFlags, CondARM32::Cond Cond);
273
Karl Schimpf697dc792015-10-30 13:21:59 -0700274 void sdiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
275 CondARM32::Cond Cond);
276
Karl Schimpf2c68d902015-11-11 15:37:50 -0800277 void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
278 const TargetInfo &TInfo);
279
280 void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
281 const TargetLowering *Lowering) {
282 const TargetInfo TInfo(Lowering);
283 str(OpRt, OpAddress, Cond, TInfo);
284 }
Karl Schimpf745ad1d2015-10-16 10:31:31 -0700285
Karl Schimpfe3455052015-10-14 14:30:21 -0700286 void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
287 bool SetFlags, CondARM32::Cond Cond);
288
Karl Schimpf1e67f912015-12-08 11:17:23 -0800289 // Implements sxtb/sxth depending on type of OpSrc0.
290 void sxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
291
Karl Schimpfb81b9012015-11-04 14:54:52 -0800292 void tst(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
293
Karl Schimpf1c285502015-10-30 15:00:24 -0700294 void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
295 CondARM32::Cond Cond);
296
Karl Schimpf430e8442015-11-09 12:16:20 -0800297 void umull(const Operand *OpRdLo, const Operand *OpRdHi, const Operand *OpRn,
298 const Operand *OpRm, CondARM32::Cond Cond);
299
Karl Schimpfbb0bacf2015-11-11 15:42:55 -0800300 // Implements uxtb/uxth depending on type of OpSrc0.
301 void uxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
302
John Porto2da710c2015-06-29 07:57:02 -0700303 static bool classof(const Assembler *Asm) {
304 return Asm->getKind() == Asm_ARM32;
305 }
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700306
Karl Schimpf856734c2015-11-05 08:18:26 -0800307 void emitTextInst(const std::string &Text, SizeT InstSize);
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700308
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700309private:
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700310 // A vector of pool-allocated x86 labels for CFG nodes.
311 using LabelVector = std::vector<Label *>;
312 LabelVector CfgNodeLabels;
Karl Schimpf50a33312015-10-23 09:19:48 -0700313 // A vector of pool-allocated x86 labels for Local labels.
314 LabelVector LocalLabels;
Karl Schimpf856734c2015-11-05 08:18:26 -0800315 // Number of bytes emitted by InstARM32::emit() methods, when run inside
316 // InstARM32::emitUsingTextFixup().
317 size_t EmitTextSize = 0;
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700318
Karl Schimpf6cab5612015-11-06 09:14:10 -0800319 // Load/store multiple addressing mode.
320 enum BlockAddressMode {
321 // bit encoding P U W
322 DA = (0 | 0 | 0) << 21, // decrement after
323 IA = (0 | 4 | 0) << 21, // increment after
324 DB = (8 | 0 | 0) << 21, // decrement before
325 IB = (8 | 4 | 0) << 21, // increment before
326 DA_W = (0 | 0 | 1) << 21, // decrement after with writeback to base
327 IA_W = (0 | 4 | 1) << 21, // increment after with writeback to base
328 DB_W = (8 | 0 | 1) << 21, // decrement before with writeback to base
329 IB_W = (8 | 4 | 1) << 21 // increment before with writeback to base
330 };
331
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700332 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700333
Karl Schimpf137e62b2015-10-27 07:28:09 -0700334 void bindCfgNodeLabel(const CfgNode *Node) override;
335
336 void emitInst(IValueT Value) { Buffer.emit<IValueT>(Value); }
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700337
Karl Schimpfb81b9012015-11-04 14:54:52 -0800338 // List of possible checks to apply when calling emitType01() (below).
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800339 enum EmitChecks { NoChecks, RdIsPcAndSetFlags };
340
Karl Schimpf0437ae82015-12-04 07:29:10 -0800341 // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=InstType,
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800342 // s=SetFlags, oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM
343 // section A5.2.3).
Karl Schimpf0437ae82015-12-04 07:29:10 -0800344 void emitType01(CondARM32::Cond Cond, IValueT InstType, IValueT Opcode,
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800345 bool SetFlags, IValueT Rn, IValueT Rd, IValueT imm12,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800346 EmitChecks RuleChecks, const char *InstName);
Karl Schimpfb81b9012015-11-04 14:54:52 -0800347
348 // Converts appropriate representation on a data operation, and then calls
349 // emitType01 above.
Karl Schimpf0437ae82015-12-04 07:29:10 -0800350 void emitType01(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
351 const Operand *OpRn, const Operand *OpSrc1, bool SetFlags,
352 EmitChecks RuleChecks, const char *InstName);
Karl Schimpfb81b9012015-11-04 14:54:52 -0800353
354 // Same as above, but the value for Rd and Rn have already been converted
355 // into instruction values.
Karl Schimpf0437ae82015-12-04 07:29:10 -0800356 void emitType01(CondARM32::Cond Cond, IValueT Opcode, IValueT OpRd,
357 IValueT OpRn, const Operand *OpSrc1, bool SetFlags,
358 EmitChecks RuleChecks, const char *InstName);
Karl Schimpf62d367b2015-10-30 08:06:44 -0700359
Karl Schimpf0437ae82015-12-04 07:29:10 -0800360 void emitType05(CondARM32::Cond Cond, int32_t Offset, bool Link,
361 const char *InstName);
Karl Schimpf745ad1d2015-10-16 10:31:31 -0700362
Karl Schimpf19567882015-12-02 10:24:15 -0800363 // Emit ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond,
364 // ooo=InstType, l=isLoad, b=isByte, and
365 // aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that Address is assumed to be
366 // defined by decodeAddress() in IceAssemblerARM32.cpp.
Karl Schimpf137e62b2015-10-27 07:28:09 -0700367 void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800368 bool IsByte, IValueT Rt, IValueT Address,
369 const char *InstName);
Karl Schimpf19567882015-12-02 10:24:15 -0800370
371 // Emit ldr/ldrb/str/strb instruction with given address.
372 void emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, IValueT Rt,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800373 const Operand *OpAddress, const TargetInfo &TInfo,
374 const char *InstName);
Karl Schimpf19567882015-12-02 10:24:15 -0800375
376 // Emit ldrh/ldrd/strh/strd instruction with given address using encoding 3.
377 void emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, IValueT Rt,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800378 const Operand *OpAddress, const TargetInfo &TInfo,
379 const char *InstName);
Karl Schimpf137e62b2015-10-27 07:28:09 -0700380
Karl Schimpf6cab5612015-11-06 09:14:10 -0800381 // Pattern cccc100aaaalnnnnrrrrrrrrrrrrrrrr where cccc=Cond,
382 // aaaa<<21=AddressMode, l=IsLoad, nnnn=BaseReg, and
383 // rrrrrrrrrrrrrrrr is bitset of Registers.
384 void emitMultiMemOp(CondARM32::Cond Cond, BlockAddressMode AddressMode,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800385 bool IsLoad, IValueT BaseReg, IValueT Registers,
386 const char *InstName);
Karl Schimpf6cab5612015-11-06 09:14:10 -0800387
Karl Schimpf697dc792015-10-30 13:21:59 -0700388 // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond,
389 // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm.
390 void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800391 IValueT Rm, const char *InstName);
Karl Schimpf697dc792015-10-30 13:21:59 -0700392
Karl Schimpf396de532015-10-30 07:25:43 -0700393 // Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
Karl Schimpff4d0a7a2015-11-19 08:10:44 -0800394 // mmmm=Rm, ssss=Rs, f=SetFlags and xxxxxxx=Opcode.
Karl Schimpf396de532015-10-30 07:25:43 -0700395 void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
Karl Schimpf0437ae82015-12-04 07:29:10 -0800396 IValueT Rm, IValueT Rs, bool SetFlags, const char *InstName);
Karl Schimpf396de532015-10-30 07:25:43 -0700397
Karl Schimpf4ddce702015-12-07 10:43:34 -0800398 // Pattern cccc0001101s0000ddddxxxxxtt0mmmm where cccc=Cond, s=SetFlags,
399 // dddd=Rd, mmmm=Rm, tt=Shift, and xxxxx is defined by OpSrc1. OpSrc1 defines
400 // either xxxxx=Imm5, or xxxxx=ssss0 where ssss=Rs.
401 void emitShift(const CondARM32::Cond Cond,
402 const OperandARM32::ShiftKind Shift, const Operand *OpRd,
403 const Operand *OpRm, const Operand *OpSrc1,
404 const bool SetFlags, const char *InstName);
405
Karl Schimpf1e67f912015-12-08 11:17:23 -0800406 // Implements various forms of signed/unsigned extend value, using pattern
Karl Schimpfbb0bacf2015-11-11 15:42:55 -0800407 // ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
408 // nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm.
Karl Schimpf1e67f912015-12-08 11:17:23 -0800409 void emitSignExtend(CondARM32::Cond, IValueT Opcode, const Operand *OpRd,
410 const Operand *OpSrc0, const char *InstName);
Karl Schimpfbb0bacf2015-11-11 15:42:55 -0800411
Karl Schimpfb81b9012015-11-04 14:54:52 -0800412 // Pattern cccctttxxxxnnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn,
413 // ttt=Instruction type (derived from OpSrc1), iiiiiiiiiiii is derived from
414 // OpSrc1, and xxxx=Opcode.
Karl Schimpf0437ae82015-12-04 07:29:10 -0800415 void emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRn,
416 const Operand *OpSrc1, const char *CmpName);
Karl Schimpfb81b9012015-11-04 14:54:52 -0800417
Karl Schimpf137e62b2015-10-27 07:28:09 -0700418 void emitBranch(Label *L, CondARM32::Cond, bool Link);
419
420 // Encodes the given Offset into the branch instruction Inst.
421 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst);
422
423 // Returns the offset encoded in the branch instruction Inst.
424 static IOffsetT decodeBranchOffset(IValueT Inst);
Karl Schimpf5ff0cfb2015-11-11 14:47:49 -0800425
Karl Schimpf7cfe9a02015-12-04 15:07:01 -0800426 // Implements movw/movt, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii
427 // where cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and
Karl Schimpf5ff0cfb2015-11-11 14:47:49 -0800428 // iiiiiiiiiiiiiiii=Imm16.
Karl Schimpf7cfe9a02015-12-04 15:07:01 -0800429 void emitMovwt(CondARM32::Cond Cond, bool IsMovw, const Operand *OpRd,
430 const Operand *OpSrc, const char *MovName);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700431};
432
Jan Voung90ccc3f2015-04-30 14:15:10 -0700433} // end of namespace ARM32
Jan Voungb36ad9b2015-04-21 17:01:49 -0700434} // end of namespace Ice
435
John Portoaff4ccf2015-06-10 16:35:06 -0700436#endif // SUBZERO_SRC_ICEASSEMBLERARM32_H