Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: src/IceAssemblerARM32.cpp

Issue 1418313003: Handle branch relative to pc in ARM integrated assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix issues in patch set 2. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// 1 //===- subzero/src/IceAssemblerARM32.cpp - 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 #include "IceAssemblerARM32.h" 23 #include "IceAssemblerARM32.h"
24 #include "IceCfgNode.h" 24 #include "IceCfgNode.h"
25 #include "IceUtils.h" 25 #include "IceUtils.h"
26 26
27 namespace { 27 namespace {
28 28
29 using namespace Ice; 29 using namespace Ice;
30 using namespace Ice::ARM32;
30 31
31 // The following define individual bits. 32 // The following define individual bits.
32 static constexpr uint32_t B0 = 1; 33 static constexpr IValueT B0 = 1;
33 static constexpr uint32_t B1 = 1 << 1; 34 static constexpr IValueT B1 = 1 << 1;
34 static constexpr uint32_t B2 = 1 << 2; 35 static constexpr IValueT B2 = 1 << 2;
35 static constexpr uint32_t B3 = 1 << 3; 36 static constexpr IValueT B3 = 1 << 3;
36 static constexpr uint32_t B4 = 1 << 4; 37 static constexpr IValueT B4 = 1 << 4;
37 static constexpr uint32_t B5 = 1 << 5; 38 static constexpr IValueT B5 = 1 << 5;
38 static constexpr uint32_t B6 = 1 << 6; 39 static constexpr IValueT B6 = 1 << 6;
39 static constexpr uint32_t B21 = 1 << 21; 40 static constexpr IValueT B21 = 1 << 21;
40 static constexpr uint32_t B24 = 1 << 24; 41 static constexpr IValueT B24 = 1 << 24;
41 42
42 // Constants used for the decoding or encoding of the individual fields of 43 // Constants used for the decoding or encoding of the individual fields of
43 // instructions. Based on ARM section A5.1. 44 // instructions. Based on ARM section A5.1.
44 static constexpr uint32_t L = 1 << 20; // load (or store) 45 static constexpr IValueT L = 1 << 20; // load (or store)
45 static constexpr uint32_t W = 1 << 21; // writeback base register (or leave 46 static constexpr IValueT W = 1 << 21; // writeback base register
46 // unchanged) 47 // (or leave unchanged)
47 static constexpr uint32_t B = 1 << 22; // unsigned byte (or word) 48 static constexpr IValueT B = 1 << 22; // unsigned byte (or word)
48 static constexpr uint32_t U = 1 << 23; // positive (or negative) offset/index 49 static constexpr IValueT U = 1 << 23; // positive (or negative)
49 static constexpr uint32_t P = 1 << 24; // offset/pre-indexed addressing (or 50 // offset/index
50 // post-indexed addressing) 51 static constexpr IValueT P = 1 << 24; // offset/pre-indexed
52 // addressing (or
53 // post-indexed addressing)
51 54
52 static constexpr uint32_t kConditionShift = 28; 55 static constexpr IValueT kConditionShift = 28;
53 static constexpr uint32_t kOpcodeShift = 21; 56 static constexpr IValueT kLinkShift = 24;
54 static constexpr uint32_t kRdShift = 12; 57 static constexpr IValueT kOpcodeShift = 21;
55 static constexpr uint32_t kRmShift = 0; 58 static constexpr IValueT kRdShift = 12;
56 static constexpr uint32_t kRnShift = 16; 59 static constexpr IValueT kRmShift = 0;
57 static constexpr uint32_t kSShift = 20; 60 static constexpr IValueT kRnShift = 16;
58 static constexpr uint32_t kTypeShift = 25; 61 static constexpr IValueT kSShift = 20;
62 static constexpr IValueT kTypeShift = 25;
59 63
60 // Immediate instruction fields encoding. 64 // Immediate instruction fields encoding.
61 static constexpr uint32_t kImmed8Bits = 8; 65 static constexpr IValueT kImmed8Bits = 8;
62 static constexpr uint32_t kImmed8Shift = 0; 66 static constexpr IValueT kImmed8Shift = 0;
63 static constexpr uint32_t kRotateBits = 4; 67 static constexpr IValueT kRotateBits = 4;
64 static constexpr uint32_t kRotateShift = 8; 68 static constexpr IValueT kRotateShift = 8;
65 69
66 // Shift instruction register fields encodings. 70 // Shift instruction register fields encodings.
67 static constexpr uint32_t kShiftImmShift = 7; 71 static constexpr IValueT kShiftImmShift = 7;
68 static constexpr uint32_t kShiftImmBits = 5; 72 static constexpr IValueT kShiftImmBits = 5;
69 static constexpr uint32_t kShiftShift = 5; 73 static constexpr IValueT kShiftShift = 5;
70 74
71 static constexpr uint32_t kImmed12Bits = 12; 75 static constexpr IValueT kImmed12Bits = 12;
72 static constexpr uint32_t kImm12Shift = 0; 76 static constexpr IValueT kImm12Shift = 0;
73 77
74 // Type of instruction encoding (bits 25-27). See ARM section A5.1 78 // Type of instruction encoding (bits 25-27). See ARM section A5.1
75 static constexpr uint32_t kInstTypeDataRegister = 0; // i.e. 000 79 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000
76 static constexpr uint32_t kInstTypeDataImmediate = 1; // i.e. 001 80 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001
77 static constexpr uint32_t kInstTypeMemImmediate = 2; // i.e. 010 81 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010
78 82
79 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } 83 // Offset modifier to current PC for next instruction. The offset is off by 8
84 // due to the way the ARM CPUs read PC.
85 static constexpr IOffsetT kPCReadOffset = 8;
80 86
81 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { 87 // Mask to pull out PC offset from branch (b) instruction.
82 return static_cast<uint32_t>(Rn); 88 static constexpr int kBranchOffsetBits = 24;
89 static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff;
90
91 inline IValueT encodeBool(bool b) { return b ? 1 : 0; }
Jim Stichnoth 2015/10/26 22:59:08 Probably want B instead of b
Karl 2015/10/27 14:28:27 Done.
92
93 inline IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) {
94 return static_cast<IValueT>(Rn);
83 } 95 }
84 96
85 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { 97 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) {
86 return R != RegARM32::Encoded_Not_GPR; 98 return R != RegARM32::Encoded_Not_GPR;
87 } 99 }
88 100
89 inline bool isGPRRegisterDefined(uint32_t R) { 101 inline bool isGPRRegisterDefined(IValueT R) {
90 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); 102 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR);
91 } 103 }
92 104
93 inline bool isConditionDefined(CondARM32::Cond Cond) { 105 inline bool isConditionDefined(CondARM32::Cond Cond) {
94 return Cond != CondARM32::kNone; 106 return Cond != CondARM32::kNone;
95 } 107 }
96 108
97 inline uint32_t encodeCondition(CondARM32::Cond Cond) { 109 inline IValueT encodeCondition(CondARM32::Cond Cond) {
98 return static_cast<uint32_t>(Cond); 110 return static_cast<IValueT>(Cond);
99 } 111 }
100 112
101 uint32_t encodeShift(OperandARM32::ShiftKind Shift) { 113 IValueT encodeShift(OperandARM32::ShiftKind Shift) {
102 // Follows encoding in ARM section A8.4.1 "Constant shifts". 114 // Follows encoding in ARM section A8.4.1 "Constant shifts".
103 switch (Shift) { 115 switch (Shift) {
104 case OperandARM32::kNoShift: 116 case OperandARM32::kNoShift:
105 case OperandARM32::LSL: 117 case OperandARM32::LSL:
106 return 0; // 0b00 118 return 0; // 0b00
107 case OperandARM32::LSR: 119 case OperandARM32::LSR:
108 return 1; // 0b01 120 return 1; // 0b01
109 case OperandARM32::ASR: 121 case OperandARM32::ASR:
110 return 2; // 0b10 122 return 2; // 0b10
111 case OperandARM32::ROR: 123 case OperandARM32::ROR:
112 case OperandARM32::RRX: 124 case OperandARM32::RRX:
113 return 3; // 0b11 125 return 3; // 0b11
114 } 126 }
115 } 127 }
116 128
117 // Returns the bits in the corresponding masked value. 129 // Returns the bits in the corresponding masked value.
118 inline uint32_t mask(uint32_t Value, uint32_t Shift, uint32_t Bits) { 130 inline IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) {
119 return (Value >> Shift) & ((1 << Bits) - 1); 131 return (Value >> Shift) & ((1 << Bits) - 1);
120 } 132 }
121 133
122 // Extract out a Bit in Value. 134 // Extract out a Bit in Value.
123 inline bool isBitSet(uint32_t Bit, uint32_t Value) { 135 inline bool isBitSet(IValueT Bit, IValueT Value) {
124 return (Value & Bit) == Bit; 136 return (Value & Bit) == Bit;
125 } 137 }
126 138
127 // Returns the GPR register at given Shift in Value. 139 // Returns the GPR register at given Shift in Value.
128 inline RegARM32::GPRRegister getGPRReg(uint32_t Shift, uint32_t Value) { 140 inline RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
129 return static_cast<RegARM32::GPRRegister>((Value >> Shift) & 0xF); 141 return static_cast<RegARM32::GPRRegister>((Value >> Shift) & 0xF);
130 } 142 }
131 143
132 // The way an operand was decoded in functions decodeOperand and decodeAddress 144 // The way an operand was decoded in functions decodeOperand and decodeAddress
133 // below. 145 // below.
134 enum DecodedResult { 146 enum DecodedResult {
135 // Unable to decode, value left undefined. 147 // Unable to decode, value left undefined.
136 CantDecode = 0, 148 CantDecode = 0,
137 // Value is register found. 149 // Value is register found.
138 DecodedAsRegister, 150 DecodedAsRegister,
139 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 151 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8
140 // value. 152 // value.
141 DecodedAsRotatedImm8, 153 DecodedAsRotatedImm8,
142 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, 154 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
143 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to 155 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
144 // Rn should be used, and iiiiiiiiiiii is the offset. 156 // Rn should be used, and iiiiiiiiiiii is the offset.
145 DecodedAsImmRegOffset 157 DecodedAsImmRegOffset
146 }; 158 };
147 159
148 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, 160 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5,
149 // tt=Shift, and mmmm=Rm. 161 // tt=Shift, and mmmm=Rm.
150 uint32_t encodeShiftRotateImm5(uint32_t Rm, OperandARM32::ShiftKind Shift, 162 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift,
151 uint32_t imm5) { 163 IValueT imm5) {
152 (void)kShiftImmBits; 164 (void)kShiftImmBits;
153 assert(imm5 < (1 << kShiftImmBits)); 165 assert(imm5 < (1 << kShiftImmBits));
154 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; 166 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm;
155 } 167 }
156 168
157 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { 169 DecodedResult decodeOperand(const Operand *Opnd, IValueT &Value) {
158 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 170 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
159 if (Var->hasReg()) { 171 if (Var->hasReg()) {
160 Value = Var->getRegNum(); 172 Value = Var->getRegNum();
161 return DecodedAsRegister; 173 return DecodedAsRegister;
162 } 174 }
163 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { 175 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
164 const uint32_t Immed8 = FlexImm->getImm(); 176 const IValueT Immed8 = FlexImm->getImm();
165 const uint32_t Rotate = FlexImm->getRotateAmt(); 177 const IValueT Rotate = FlexImm->getRotateAmt();
166 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); 178 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))))
167 // TODO(kschimpf): Remove void casts when MINIMAL build allows. 179 return CantDecode;
168 (void)kRotateBits;
169 (void)kImmed8Bits;
170 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); 180 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
171 return DecodedAsRotatedImm8; 181 return DecodedAsRotatedImm8;
172 } 182 }
173 return CantDecode; 183 return CantDecode;
174 } 184 }
175 185
176 uint32_t decodeImmRegOffset(RegARM32::GPRRegister Reg, int32_t Offset, 186 IValueT decodeImmRegOffset(RegARM32::GPRRegister Reg, IOffsetT Offset,
177 OperandARM32Mem::AddrMode Mode) { 187 OperandARM32Mem::AddrMode Mode) {
178 uint32_t Value = Mode | (encodeGPRRegister(Reg) << kRnShift); 188 IValueT Value = Mode | (encodeGPRRegister(Reg) << kRnShift);
179 if (Offset < 0) { 189 if (Offset < 0) {
180 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. 190 Value = (Value ^ U) | -Offset; // Flip U to adjust sign.
181 } else { 191 } else {
182 Value |= Offset; 192 Value |= Offset;
183 } 193 }
184 return Value; 194 return Value;
185 } 195 }
186 196
187 // Decodes memory address Opnd, and encodes that information into Value, 197 // Decodes memory address Opnd, and encodes that information into Value,
188 // based on how ARM represents the address. Returns how the value was encoded. 198 // based on how ARM represents the address. Returns how the value was encoded.
189 DecodedResult decodeAddress(const Operand *Opnd, uint32_t &Value) { 199 DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value) {
190 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 200 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
191 // Should be a stack variable, with an offset. 201 // Should be a stack variable, with an offset.
192 if (Var->hasReg()) 202 if (Var->hasReg())
193 return CantDecode; 203 return CantDecode;
194 const int32_t Offset = Var->getStackOffset(); 204 const IOffsetT Offset = Var->getStackOffset();
195 if (!Utils::IsAbsoluteUint(12, Offset)) 205 if (!Utils::IsAbsoluteUint(12, Offset))
196 return CantDecode; 206 return CantDecode;
197 Value = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, Offset, 207 Value = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, Offset,
198 OperandARM32Mem::Offset); 208 OperandARM32Mem::Offset);
199 return DecodedAsImmRegOffset; 209 return DecodedAsImmRegOffset;
200 } 210 }
201 return CantDecode; 211 return CantDecode;
202 } 212 }
203 213
214 // Checks that Offset can fit in imm24 constant of branch (b) instruction.
215 bool canEncodeBranchOffset(IOffsetT Offset) {
216 return Utils::IsAligned(Offset, 4) &&
217 Utils::IsInt(kBranchOffsetBits, Offset >> 2);
218 }
219
204 } // end of anonymous namespace 220 } // end of anonymous namespace
205 221
206 namespace Ice { 222 namespace Ice {
223 namespace ARM32 {
207 224
208 void ARM32::AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { 225 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) {
209 if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) { 226 if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) {
210 // Generate label name so that branches can find it. 227 // Generate label name so that branches can find it.
211 constexpr SizeT InstSize = 0; 228 constexpr SizeT InstSize = 0;
212 emitTextInst(Node->getAsmName() + ":", InstSize); 229 emitTextInst(Node->getAsmName() + ":", InstSize);
213 } 230 }
214 SizeT NodeNumber = Node->getIndex(); 231 SizeT NodeNumber = Node->getIndex();
215 assert(!getPreliminary()); 232 assert(!getPreliminary());
216 Label *L = getOrCreateCfgNodeLabel(NodeNumber); 233 Label *L = getOrCreateCfgNodeLabel(NodeNumber);
217 this->bind(L); 234 this->bind(L);
218 } 235 }
219 236
220 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, 237 Label *AssemblerARM32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
221 LabelVector &Labels) {
222 Label *L = nullptr; 238 Label *L = nullptr;
223 if (Number == Labels.size()) { 239 if (Number == Labels.size()) {
224 L = new (this->allocate<Label>()) Label(); 240 L = new (this->allocate<Label>()) Label();
225 Labels.push_back(L); 241 Labels.push_back(L);
226 return L; 242 return L;
227 } 243 }
228 if (Number > Labels.size()) { 244 if (Number > Labels.size()) {
229 Labels.resize(Number + 1); 245 Labels.resize(Number + 1);
230 } 246 }
231 L = Labels[Number]; 247 L = Labels[Number];
232 if (!L) { 248 if (!L) {
233 L = new (this->allocate<Label>()) Label(); 249 L = new (this->allocate<Label>()) Label();
234 Labels[Number] = L; 250 Labels[Number] = L;
235 } 251 }
236 return L; 252 return L;
237 } 253 }
238 254
239 void ARM32::AssemblerARM32::bind(Label *label) { 255 IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
240 intptr_t bound = Buffer.size(); 256 // Adjust offset to the way ARM CPUs read PC.
241 assert(!label->isBound()); // Labels can only be bound once. 257 Offset -= kPCReadOffset;
242 while (label->isLinked()) { 258
243 intptr_t position = label->getLinkPosition(); 259 bool isGoodOffset = canEncodeBranchOffset(Offset);
Jim Stichnoth 2015/10/26 22:59:08 IsGoodOffset
Karl 2015/10/27 14:28:27 Done.
244 intptr_t next = Buffer.load<int32_t>(position); 260 assert(isGoodOffset);
245 Buffer.store<int32_t>(position, bound - (position + 4)); 261 // Note: Following cast is for MINIMAL build.
246 label->setPosition(next); 262 (void)isGoodOffset;
247 } 263
248 // TODO(kschimpf) Decide if we have near jumps. 264 // Properly preserve only the bits supported in the instruction.
249 label->bindTo(bound); 265 Offset >>= 2;
266 Offset &= kBranchOffsetMask;
267 return (Inst & ~kBranchOffsetMask) | Offset;
250 } 268 }
251 269
252 void ARM32::AssemblerARM32::emitTextInst(const std::string &Text, 270 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) {
253 SizeT InstSize) { 271 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC.
272 IOffsetT Offset = static_cast<IOffsetT>((Inst & kBranchOffsetMask) << 8);
273 return (Offset >> 6) + kPCReadOffset;
274 }
275
276 void AssemblerARM32::bind(Label *L) {
277 IOffsetT BoundPc = Buffer.size();
278 assert(!L->isBound()); // Labels can only be bound once.
279 while (L->isLinked()) {
280 IOffsetT Position = L->getLinkPosition();
281 IOffsetT Dest = BoundPc - Position;
282 IValueT Inst = Buffer.load<IValueT>(Position);
283 Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
284 L->setPosition(decodeBranchOffset(Inst));
285 }
286 L->bindTo(BoundPc);
287 }
288
289 void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) {
254 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 290 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
255 AssemblerFixup *F = createTextFixup(Text, InstSize); 291 AssemblerFixup *F = createTextFixup(Text, InstSize);
256 emitFixup(F); 292 emitFixup(F);
257 for (SizeT I = 0; I < InstSize; ++I) 293 for (SizeT I = 0; I < InstSize; ++I)
258 Buffer.emit<char>(0); 294 Buffer.emit<char>(0);
259 } 295 }
260 296
261 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, 297 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type,
262 uint32_t Opcode, bool SetCc, uint32_t Rn, 298 IValueT Opcode, bool SetCc, IValueT Rn,
263 uint32_t Rd, uint32_t Imm12) { 299 IValueT Rd, IValueT Imm12) {
264 assert(isGPRRegisterDefined(Rd)); 300 assert(isGPRRegisterDefined(Rd));
265 // TODO(kschimpf): Remove void cast when MINIMAL build allows. 301 // TODO(kschimpf): Remove void cast when MINIMAL build allows.
266 (void)isGPRRegisterDefined(Rd); 302 (void)isGPRRegisterDefined(Rd);
267 assert(Cond != CondARM32::kNone); 303 assert(Cond != CondARM32::kNone);
268 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 304 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
269 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | 305 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
270 (Type << kTypeShift) | (Opcode << kOpcodeShift) | 306 (Type << kTypeShift) | (Opcode << kOpcodeShift) |
271 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | 307 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) |
272 (Rd << kRdShift) | Imm12; 308 (Rd << kRdShift) | Imm12;
273 emitInst(Encoding); 309 emitInst(Encoding);
274 } 310 }
275 311
276 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, 312 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset,
277 bool IsLoad, bool IsByte, uint32_t Rt, 313 bool Link) {
278 uint32_t Address) { 314 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and
315 // iiiiiiiiiiiiiiiiiiiiiiii=
316 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset);
317 if (!isConditionDefined(Cond))
318 return setNeedsTextFixup();
319 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
320 IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift |
321 5 << kTypeShift | (Link ? 1 : 0) << kLinkShift;
322 Encoding = encodeBranchOffset(Offset, Encoding);
323 emitInst(Encoding);
324 }
325
326 void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) {
327 // TODO(kschimpf): Handle far jumps.
328 if (L->isBound()) {
329 const int32_t Dest = L->getPosition() - Buffer.size();
330 emitType05(Cond, Dest, Link);
331 return;
332 }
333 const IOffsetT Position = Buffer.size();
334 // Use the offset field of the branch instruction for linking the sites.
335 emitType05(Cond, L->getEncodedPosition(), Link);
336 if (!needsTextFixup())
337 L->linkTo(Position);
338 }
339
340 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
341 bool IsLoad, bool IsByte, IValueT Rt,
342 IValueT Address) {
279 assert(isGPRRegisterDefined(Rt)); 343 assert(isGPRRegisterDefined(Rt));
280 assert(Cond != CondARM32::kNone); 344 assert(Cond != CondARM32::kNone);
281 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 345 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
282 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | 346 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
283 (InstType << kTypeShift) | (IsLoad ? L : 0) | 347 (InstType << kTypeShift) | (IsLoad ? L : 0) |
284 (IsByte ? B : 0) | (Rt << kRdShift) | Address; 348 (IsByte ? B : 0) | (Rt << kRdShift) | Address;
285 emitInst(Encoding); 349 emitInst(Encoding);
286 } 350 }
287 351
288 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, 352 void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
289 const Operand *OpSrc1, bool SetFlags, 353 const Operand *OpSrc1, bool SetFlags,
290 CondARM32::Cond Cond) { 354 CondARM32::Cond Cond) {
291 uint32_t Rd; 355 IValueT Rd;
292 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) 356 if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
293 return setNeedsTextFixup(); 357 return setNeedsTextFixup();
294 uint32_t Rn; 358 IValueT Rn;
295 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) 359 if (decodeOperand(OpRn, Rn) != DecodedAsRegister)
296 return setNeedsTextFixup(); 360 return setNeedsTextFixup();
297 constexpr uint32_t Add = B2; // 0100 361 constexpr IValueT Add = B2; // 0100
298 uint32_t Src1Value; 362 IValueT Src1Value;
299 // TODO(kschimpf) Other possible decodings of add. 363 // TODO(kschimpf) Other possible decodings of add.
300 switch (decodeOperand(OpSrc1, Src1Value)) { 364 switch (decodeOperand(OpSrc1, Src1Value)) {
301 default: 365 default:
302 return setNeedsTextFixup(); 366 return setNeedsTextFixup();
303 case DecodedAsRegister: { 367 case DecodedAsRegister: {
304 // ADD (register) - ARM section A8.8.7, encoding A1: 368 // ADD (register) - ARM section A8.8.7, encoding A1:
305 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} 369 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>}
306 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: 370 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1:
307 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} 371 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>}
308 // 372 //
(...skipping 16 matching lines...) Expand all
325 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. 389 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8.
326 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) 390 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags))
327 // Conditions of rule violated. 391 // Conditions of rule violated.
328 return setNeedsTextFixup(); 392 return setNeedsTextFixup();
329 emitType01(Cond, kInstTypeDataImmediate, Add, SetFlags, Rn, Rd, Src1Value); 393 emitType01(Cond, kInstTypeDataImmediate, Add, SetFlags, Rn, Rd, Src1Value);
330 return; 394 return;
331 } 395 }
332 }; 396 };
333 } 397 }
334 398
335 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { 399 void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) {
400 emitBranch(L, Cond, false);
401 }
402
403 void AssemblerARM32::bkpt(uint16_t Imm16) {
336 // BKPT - ARM section A*.8.24 - encoding A1: 404 // BKPT - ARM section A*.8.24 - encoding A1:
337 // bkpt #<Imm16> 405 // bkpt #<Imm16>
338 // 406 //
339 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 407 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16
340 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 408 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
341 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | 409 const IValueT Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 |
342 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); 410 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf);
343 emitInst(Encoding); 411 emitInst(Encoding);
344 } 412 }
345 413
346 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { 414 void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
347 // BX - ARM section A8.8.27, encoding A1: 415 // BX - ARM section A8.8.27, encoding A1:
348 // bx<c> <Rm> 416 // bx<c> <Rm>
349 // 417 //
350 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. 418 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond.
351 if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond))) 419 if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond)))
352 return setNeedsTextFixup(); 420 return setNeedsTextFixup();
353 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 421 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
354 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | 422 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 |
355 B21 | (0xfff << 8) | B4 | 423 B21 | (0xfff << 8) | B4 |
356 (encodeGPRRegister(Rm) << kRmShift); 424 (encodeGPRRegister(Rm) << kRmShift);
357 emitInst(Encoding); 425 emitInst(Encoding);
358 } 426 }
359 427
360 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, 428 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
361 CondARM32::Cond Cond) { 429 CondARM32::Cond Cond) {
362 uint32_t Rt; 430 IValueT Rt;
363 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) 431 if (decodeOperand(OpRt, Rt) != DecodedAsRegister)
364 return setNeedsTextFixup(); 432 return setNeedsTextFixup();
365 uint32_t Address; 433 IValueT Address;
366 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) 434 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset)
367 return setNeedsTextFixup(); 435 return setNeedsTextFixup();
368 // LDR (immediate) - ARM section A8.8.63, encoding A1: 436 // LDR (immediate) - ARM section A8.8.63, encoding A1:
369 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 437 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
370 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 438 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
371 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 439 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
372 // LDRB (immediate) - ARM section A8.8.68, encoding A1: 440 // LDRB (immediate) - ARM section A8.8.68, encoding A1:
373 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 441 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
374 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 442 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
375 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 443 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
(...skipping 10 matching lines...) Expand all
386 return setNeedsTextFixup(); 454 return setNeedsTextFixup();
387 if (!isBitSet(P, Address) && isBitSet(W, Address)) 455 if (!isBitSet(P, Address) && isBitSet(W, Address))
388 return setNeedsTextFixup(); 456 return setNeedsTextFixup();
389 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && 457 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) &&
390 !isBitSet(P, Address) && isBitSet(U, Address) & !isBitSet(W, Address) && 458 !isBitSet(P, Address) && isBitSet(U, Address) & !isBitSet(W, Address) &&
391 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) 459 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
392 return setNeedsTextFixup(); 460 return setNeedsTextFixup();
393 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); 461 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
394 } 462 }
395 463
396 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, 464 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
397 CondARM32::Cond Cond) { 465 CondARM32::Cond Cond) {
398 uint32_t Rd; 466 IValueT Rd;
399 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) 467 if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
400 return setNeedsTextFixup(); 468 return setNeedsTextFixup();
401 uint32_t Src; 469 IValueT Src;
402 // TODO(kschimpf) Handle other forms of mov. 470 // TODO(kschimpf) Handle other forms of mov.
403 if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8) 471 if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8)
404 return setNeedsTextFixup(); 472 return setNeedsTextFixup();
405 // MOV (immediate) - ARM section A8.8.102, encoding A1: 473 // MOV (immediate) - ARM section A8.8.102, encoding A1:
406 // mov{S}<c> <Rd>, #<RotatedImm8> 474 // mov{S}<c> <Rd>, #<RotatedImm8>
407 // 475 //
408 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, 476 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd,
409 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this 477 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this
410 // assembler. 478 // assembler.
411 constexpr bool SetFlags = false; 479 constexpr bool SetFlags = false;
412 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) 480 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags))
413 // Conditions of rule violated. 481 // Conditions of rule violated.
414 return setNeedsTextFixup(); 482 return setNeedsTextFixup();
415 constexpr uint32_t Rn = 0; 483 constexpr IValueT Rn = 0;
416 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. 484 constexpr IValueT Mov = B3 | B2 | B0; // 1101.
417 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); 485 emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src);
418 } 486 }
419 487
420 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, 488 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
421 CondARM32::Cond Cond) { 489 CondARM32::Cond Cond) {
422 uint32_t Rt; 490 IValueT Rt;
423 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) 491 if (decodeOperand(OpRt, Rt) != DecodedAsRegister)
424 return setNeedsTextFixup(); 492 return setNeedsTextFixup();
425 uint32_t Address; 493 IValueT Address;
426 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) 494 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset)
427 return setNeedsTextFixup(); 495 return setNeedsTextFixup();
428 // STR (immediate) - ARM section A8.8.204, encoding A1: 496 // STR (immediate) - ARM section A8.8.204, encoding A1:
429 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 497 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
430 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 498 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
431 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 499 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
432 // STRB (immediate) - ARM section A8.8.207, encoding A1: 500 // STRB (immediate) - ARM section A8.8.207, encoding A1:
433 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 501 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
434 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 502 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
435 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 503 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
(...skipping 10 matching lines...) Expand all
446 return setNeedsTextFixup(); 514 return setNeedsTextFixup();
447 if (!isBitSet(P, Address) && isBitSet(W, Address)) 515 if (!isBitSet(P, Address) && isBitSet(W, Address))
448 return setNeedsTextFixup(); 516 return setNeedsTextFixup();
449 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && 517 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) &&
450 isBitSet(P, Address) && !isBitSet(U, Address) && isBitSet(W, Address) && 518 isBitSet(P, Address) && !isBitSet(U, Address) && isBitSet(W, Address) &&
451 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) 519 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
452 return setNeedsTextFixup(); 520 return setNeedsTextFixup();
453 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); 521 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
454 } 522 }
455 523
456 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, 524 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
457 const Operand *OpSrc1, bool SetFlags, 525 const Operand *OpSrc1, bool SetFlags,
458 CondARM32::Cond Cond) { 526 CondARM32::Cond Cond) {
459 uint32_t Rd; 527 IValueT Rd;
460 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) 528 if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
461 return setNeedsTextFixup(); 529 return setNeedsTextFixup();
462 uint32_t Rn; 530 IValueT Rn;
463 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) 531 if (decodeOperand(OpRn, Rn) != DecodedAsRegister)
464 return setNeedsTextFixup(); 532 return setNeedsTextFixup();
465 constexpr uint32_t Sub = B1; // 0010 533 constexpr IValueT Sub = B1; // 0010
466 uint32_t Src1Value; 534 IValueT Src1Value;
467 // TODO(kschimpf) Other possible decodings of sub. 535 // TODO(kschimpf) Other possible decodings of sub.
468 switch (decodeOperand(OpSrc1, Src1Value)) { 536 switch (decodeOperand(OpSrc1, Src1Value)) {
469 default: 537 default:
470 return setNeedsTextFixup(); 538 return setNeedsTextFixup();
471 case DecodedAsRegister: { 539 case DecodedAsRegister: {
472 // SUB (register) - ARM section A8.8.223, encoding A1: 540 // SUB (register) - ARM section A8.8.223, encoding A1:
473 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 541 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>}
474 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: 542 // SUB (SP minus register): See ARM section 8.8.226, encoding A1:
475 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} 543 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>}
476 // 544 //
(...skipping 16 matching lines...) Expand all
493 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 561 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8
494 if (Rd == RegARM32::Encoded_Reg_pc) 562 if (Rd == RegARM32::Encoded_Reg_pc)
495 // Conditions of rule violated. 563 // Conditions of rule violated.
496 return setNeedsTextFixup(); 564 return setNeedsTextFixup();
497 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); 565 emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value);
498 return; 566 return;
499 } 567 }
500 } 568 }
501 } 569 }
502 570
571 } // end of namespace ARM32
503 } // end of namespace Ice 572 } // end of namespace Ice
OLDNEW
« src/IceAssemblerARM32.h ('K') | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698