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

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

Powered by Google App Engine
This is Rietveld 408576698