OLD | NEW |
1 //===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 5 // BSD-style license that can be found in the LICENSE file. |
6 // | 6 // |
7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
11 // The Subzero Code Generator | 11 // The Subzero Code Generator |
12 // | 12 // |
13 // This file is distributed under the University of Illinois Open Source | 13 // This file is distributed under the University of Illinois Open Source |
14 // License. See LICENSE.TXT for details. | 14 // License. See LICENSE.TXT for details. |
15 // | 15 // |
16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
17 /// | 17 /// |
18 /// \file | 18 /// \file |
19 /// This file implements the Assembler class for ARM32. | 19 /// This file implements the Assembler class for ARM32. |
20 /// | 20 /// |
21 //===----------------------------------------------------------------------===// | 21 //===----------------------------------------------------------------------===// |
22 | 22 |
23 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H | 23 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H |
24 #define SUBZERO_SRC_ICEASSEMBLERARM32_H | 24 #define SUBZERO_SRC_ICEASSEMBLERARM32_H |
25 | 25 |
26 #include "IceAssembler.h" | 26 #include "IceAssembler.h" |
| 27 #include "IceConditionCodesARM32.h" |
27 #include "IceDefs.h" | 28 #include "IceDefs.h" |
28 #include "IceFixups.h" | 29 #include "IceFixups.h" |
| 30 #include "IceRegistersARM32.h" |
| 31 #include "IceTargetLowering.h" |
29 | 32 |
30 namespace Ice { | 33 namespace Ice { |
31 namespace ARM32 { | 34 namespace ARM32 { |
32 | 35 |
33 class AssemblerARM32 : public Assembler { | 36 class AssemblerARM32 : public Assembler { |
34 AssemblerARM32(const AssemblerARM32 &) = delete; | 37 AssemblerARM32(const AssemblerARM32 &) = delete; |
35 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete; | 38 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete; |
36 | 39 |
37 public: | 40 public: |
38 explicit AssemblerARM32(bool use_far_branches = false) | 41 explicit AssemblerARM32(GlobalContext *Ctx, bool use_far_branches = false) |
39 : Assembler(Asm_ARM32) { | 42 : Assembler(Asm_ARM32, Ctx) { |
40 // This mode is only needed and implemented for MIPS and ARM. | 43 // TODO(kschimpf): Add mode if needed when branches are handled. |
41 assert(!use_far_branches); | |
42 (void)use_far_branches; | 44 (void)use_far_branches; |
43 } | 45 } |
44 ~AssemblerARM32() override = default; | 46 ~AssemblerARM32() override = default; |
45 | 47 |
46 void alignFunction() override { llvm_unreachable("Not yet implemented."); } | 48 void alignFunction() override { |
| 49 const SizeT Align = 1 << getBundleAlignLog2Bytes(); |
| 50 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); |
| 51 constexpr SizeT InstSize = sizeof(int32_t); |
| 52 assert(BytesNeeded % InstSize == 0); |
| 53 while (BytesNeeded > 0) { |
| 54 // TODO(kschimpf) Should this be NOP or some other instruction? |
| 55 bkpt(0); |
| 56 BytesNeeded -= InstSize; |
| 57 } |
| 58 } |
47 | 59 |
48 SizeT getBundleAlignLog2Bytes() const override { return 4; } | 60 SizeT getBundleAlignLog2Bytes() const override { return 4; } |
49 | 61 |
50 const char *getAlignDirective() const override { return ".p2alignl"; } | 62 const char *getAlignDirective() const override { return ".p2alignl"; } |
51 | 63 |
52 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { | 64 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { |
53 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0 | 65 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0 |
54 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943 | 66 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943 |
55 static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0}; | 67 static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0}; |
56 return llvm::ArrayRef<uint8_t>(Padding, 4); | 68 return llvm::ArrayRef<uint8_t>(Padding, 4); |
57 } | 69 } |
58 | 70 |
59 void padWithNop(intptr_t Padding) override { | 71 void padWithNop(intptr_t Padding) override { |
60 (void)Padding; | 72 (void)Padding; |
61 llvm_unreachable("Not yet implemented."); | 73 llvm_unreachable("Not yet implemented."); |
62 } | 74 } |
63 | 75 |
64 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { | 76 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { |
65 (void)NodeNumber; | 77 (void)NodeNumber; |
66 llvm_unreachable("Not yet implemented."); | 78 llvm_unreachable("Not yet implemented."); |
67 } | 79 } |
68 | 80 |
69 void bindCfgNodeLabel(SizeT NodeNumber) override { | 81 void bindCfgNodeLabel(SizeT NodeNumber) override { |
70 (void)NodeNumber; | 82 assert(!getPreliminary()); |
71 llvm_unreachable("Not yet implemented."); | 83 Label *L = getOrCreateCfgNodeLabel(NodeNumber); |
| 84 this->bind(L); |
72 } | 85 } |
73 | 86 |
74 bool fixupIsPCRel(FixupKind Kind) const override { | 87 bool fixupIsPCRel(FixupKind Kind) const override { |
75 (void)Kind; | 88 (void)Kind; |
76 llvm_unreachable("Not yet implemented."); | 89 llvm_unreachable("Not yet implemented."); |
77 } | 90 } |
| 91 void bind(Label *label); |
| 92 |
| 93 void bkpt(uint16_t imm16); |
| 94 |
| 95 void bx(RegARM32::GPRRegister rm, CondARM32::Cond cond = CondARM32::AL); |
78 | 96 |
79 static bool classof(const Assembler *Asm) { | 97 static bool classof(const Assembler *Asm) { |
80 return Asm->getKind() == Asm_ARM32; | 98 return Asm->getKind() == Asm_ARM32; |
81 } | 99 } |
| 100 |
| 101 private: |
| 102 // Instruction encoding bits. |
| 103 |
| 104 // halfword (or byte) |
| 105 static constexpr uint32_t H = 1 << 5; |
| 106 // load (or store) |
| 107 static constexpr uint32_t L = 1 << 20; |
| 108 // set condition code (or leave unchanged) |
| 109 static constexpr uint32_t S = 1 << 20; |
| 110 // writeback base register (or leave unchanged) |
| 111 static constexpr uint32_t W = 1 << 21; |
| 112 // accumulate in multiply instruction (or not) |
| 113 static constexpr uint32_t A = 1 << 21; |
| 114 // unsigned byte (or word) |
| 115 static constexpr uint32_t B = 1 << 22; |
| 116 // high/lo bit of start of s/d register range |
| 117 static constexpr uint32_t D = 1 << 22; |
| 118 // long (or short) |
| 119 static constexpr uint32_t N = 1 << 22; |
| 120 // positive (or negative) offset/index |
| 121 static constexpr uint32_t U = 1 << 23; |
| 122 // offset/pre-indexed addressing (or post-indexed addressing) |
| 123 static constexpr uint32_t P = 1 << 24; |
| 124 // immediate shifter operand (or not) |
| 125 static constexpr uint32_t I = 1 << 25; |
| 126 |
| 127 // The following define individual bits. |
| 128 static constexpr uint32_t B0 = 1; |
| 129 static constexpr uint32_t B1 = 1 << 1; |
| 130 static constexpr uint32_t B2 = 1 << 2; |
| 131 static constexpr uint32_t B3 = 1 << 3; |
| 132 static constexpr uint32_t B4 = 1 << 4; |
| 133 static constexpr uint32_t B5 = 1 << 5; |
| 134 static constexpr uint32_t B6 = 1 << 6; |
| 135 static constexpr uint32_t B7 = 1 << 7; |
| 136 static constexpr uint32_t B8 = 1 << 8; |
| 137 static constexpr uint32_t B9 = 1 << 9; |
| 138 static constexpr uint32_t B10 = 1 << 10; |
| 139 static constexpr uint32_t B11 = 1 << 11; |
| 140 static constexpr uint32_t B12 = 1 << 12; |
| 141 static constexpr uint32_t B16 = 1 << 16; |
| 142 static constexpr uint32_t B17 = 1 << 17; |
| 143 static constexpr uint32_t B18 = 1 << 18; |
| 144 static constexpr uint32_t B19 = 1 << 19; |
| 145 static constexpr uint32_t B20 = 1 << 20; |
| 146 static constexpr uint32_t B21 = 1 << 21; |
| 147 static constexpr uint32_t B22 = 1 << 22; |
| 148 static constexpr uint32_t B23 = 1 << 23; |
| 149 static constexpr uint32_t B24 = 1 << 24; |
| 150 static constexpr uint32_t B25 = 1 << 25; |
| 151 static constexpr uint32_t B26 = 1 << 26; |
| 152 static constexpr uint32_t B27 = 1 << 27; |
| 153 |
| 154 // Constants used for the decoding or encoding of the individual fields of |
| 155 // instructions. Based on section A5.1 from the "ARM Architecture Reference |
| 156 // Manual, ARMv7-A and ARMv7-R edition". See: |
| 157 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c |
| 158 static constexpr uint32_t kConditionShift = 28; |
| 159 static constexpr uint32_t kConditionBits = 4; |
| 160 static constexpr uint32_t kTypeShift = 25; |
| 161 static constexpr uint32_t kTypeBits = 3; |
| 162 static constexpr uint32_t kLinkShift = 24; |
| 163 static constexpr uint32_t kLinkBits = 1; |
| 164 static constexpr uint32_t kUShift = 23; |
| 165 static constexpr uint32_t kUBits = 1; |
| 166 static constexpr uint32_t kOpcodeShift = 21; |
| 167 static constexpr uint32_t kOpcodeBits = 4; |
| 168 static constexpr uint32_t kSShift = 20; |
| 169 static constexpr uint32_t kSBits = 1; |
| 170 static constexpr uint32_t kRnShift = 16; |
| 171 static constexpr uint32_t kRnBits = 4; |
| 172 static constexpr uint32_t kRdShift = 12; |
| 173 static constexpr uint32_t kRdBits = 4; |
| 174 static constexpr uint32_t kRsShift = 8; |
| 175 static constexpr uint32_t kRsBits = 4; |
| 176 static constexpr uint32_t kRmShift = 0; |
| 177 static constexpr uint32_t kRmBits = 4; |
| 178 |
| 179 // Immediate instruction fields encoding. |
| 180 static constexpr uint32_t kRotateShift = 8; |
| 181 static constexpr uint32_t kRotateBits = 4; |
| 182 static constexpr uint32_t kImmed8Shift = 0; |
| 183 static constexpr uint32_t kImmed8Bits = 8; |
| 184 |
| 185 // Shift instruction register fields encodings. |
| 186 static constexpr uint32_t kShiftImmShift = 7; |
| 187 static constexpr uint32_t kShiftRegisterShift = 8; |
| 188 static constexpr uint32_t kShiftImmBits = 5; |
| 189 static constexpr uint32_t kShiftShift = 5; |
| 190 static constexpr uint32_t kShiftBits = 2; |
| 191 |
| 192 // Load/store instruction offset field encoding. |
| 193 static constexpr uint32_t kOffset12Shift = 0; |
| 194 static constexpr uint32_t kOffset12Bits = 12; |
| 195 static constexpr uint32_t kOffset12Mask = 0x00000fff; |
| 196 |
| 197 // Mul instruction register field encodings. |
| 198 static constexpr uint32_t kMulRdShift = 16; |
| 199 static constexpr uint32_t kMulRdBits = 4; |
| 200 static constexpr uint32_t kMulRnShift = 12; |
| 201 static constexpr uint32_t kMulRnBits = 4; |
| 202 |
| 203 // Div instruction register field encodings. |
| 204 static constexpr uint32_t kDivRdShift = 16; |
| 205 static constexpr uint32_t kDivRdBits = 4; |
| 206 static constexpr uint32_t kDivRmShift = 8; |
| 207 static constexpr uint32_t kDivRmBints = 4; |
| 208 static constexpr uint32_t kDivRnShift = 0; |
| 209 static constexpr uint32_t kDivRnBits = 4; |
| 210 |
| 211 // ldrex/strex register field encodings. |
| 212 static constexpr uint32_t kLdExRnShift = 16; |
| 213 static constexpr uint32_t kLdExRtShift = 12; |
| 214 static constexpr uint32_t kStrExRnShift = 16; |
| 215 static constexpr uint32_t kStrExRdShift = 12; |
| 216 static constexpr uint32_t kStrExRtShift = 0; |
| 217 |
| 218 // MRC instruction offset field encoding. |
| 219 static constexpr uint32_t kCRmShift = 0; |
| 220 static constexpr uint32_t kCRmBits = 4; |
| 221 static constexpr uint32_t kOpc2Shift = 5; |
| 222 static constexpr uint32_t kOpc2Bits = 3; |
| 223 static constexpr uint32_t kCoprocShift = 8; |
| 224 static constexpr uint32_t kCoprocBits = 4; |
| 225 static constexpr uint32_t kCRnShift = 16; |
| 226 static constexpr uint32_t kCRnBits = 4; |
| 227 static constexpr uint32_t kOpc1Shift = 21; |
| 228 static constexpr uint32_t kOpc1Bits = 3; |
| 229 |
| 230 static constexpr uint32_t kBranchOffsetMask = 0x00ffffff; |
| 231 |
| 232 // A vector of pool-allocated x86 labels for CFG nodes. |
| 233 using LabelVector = std::vector<Label *>; |
| 234 LabelVector CfgNodeLabels; |
| 235 |
| 236 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); |
| 237 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { |
| 238 return getOrCreateLabel(NodeNumber, CfgNodeLabels); |
| 239 } |
| 240 |
| 241 void emitInt32(int32_t Value) { Buffer.emit<int32_t>(Value); } |
| 242 |
| 243 static int32_t BkptEncoding(uint16_t imm16) { |
| 244 // bkpt requires that the cond field is AL. |
| 245 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and i in imm16 |
| 246 return (CondARM32::AL << kConditionShift) | B24 | B21 | |
| 247 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); |
| 248 } |
82 }; | 249 }; |
83 | 250 |
84 } // end of namespace ARM32 | 251 } // end of namespace ARM32 |
85 } // end of namespace Ice | 252 } // end of namespace Ice |
86 | 253 |
87 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H | 254 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H |
OLD | NEW |