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

Side by Side Diff: src/IceInstARM32.cpp

Issue 1127963004: Subzero ARM: lowerArguments (GPR), basic legalize(), and lowerRet(i32, i64). (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: clang-format Created 5 years, 7 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/IceInstARM32.cpp - ARM32 instruction implementation ----===// 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the InstARM32 and OperandARM32 classes, 10 // This file implements the InstARM32 and OperandARM32 classes,
(...skipping 19 matching lines...) Expand all
30 int8_t SExtAddrOffsetBits; 30 int8_t SExtAddrOffsetBits;
31 int8_t ZExtAddrOffsetBits; 31 int8_t ZExtAddrOffsetBits;
32 } TypeARM32Attributes[] = { 32 } TypeARM32Attributes[] = {
33 #define X(tag, elementty, width, sbits, ubits) \ 33 #define X(tag, elementty, width, sbits, ubits) \
34 { width, sbits, ubits } \ 34 { width, sbits, ubits } \
35 , 35 ,
36 ICETYPEARM32_TABLE 36 ICETYPEARM32_TABLE
37 #undef X 37 #undef X
38 }; 38 };
39 39
40 const struct InstARM32ShiftAttributes_ {
41 const char *EmitString;
42 } InstARM32ShiftAttributes[] = {
43 #define X(tag, emit) \
44 { emit } \
45 ,
46 ICEINSTARM32SHIFT_TABLE
47 #undef X
48 };
49
40 } // end of anonymous namespace 50 } // end of anonymous namespace
41 51
42 const char *InstARM32::getWidthString(Type Ty) { 52 const char *InstARM32::getWidthString(Type Ty) {
43 return TypeARM32Attributes[Ty].WidthString; 53 return TypeARM32Attributes[Ty].WidthString;
44 } 54 }
45 55
56 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func) {
57 if (!ALLOW_DUMP)
58 return;
59 Ostream &Str = Func->getContext()->getStrEmit();
60 assert(Inst->getSrcSize() == 2);
61 Variable *Dest = Inst->getDest();
62 Operand *Src1 = Inst->getSrc(1);
63 Str << "\t" << Opcode << "\t";
64 Dest->emit(Func);
65 Str << ", ";
66 Src1->emit(Func);
67 }
68
69 OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
70 ConstantInteger32 *ImmOffset, AddrMode Mode)
71 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr),
72 ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) {
73 // The Neg modes are only needed for Reg +/- Reg.
74 assert(!isNegAddrMode());
75 NumVars = 1;
76 Vars = Func->allocateArrayOf<Variable *>(1);
77 Vars[0] = Base;
78 }
79
80 OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
81 Variable *Index, ShiftKind ShiftOp,
82 uint16_t ShiftAmt, AddrMode Mode)
83 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(0), Index(Index),
84 ShiftOp(ShiftOp), ShiftAmt(ShiftAmt), Mode(Mode) {
85 NumVars = 2;
86 Vars = Func->allocateArrayOf<Variable *>(2);
87 Vars[0] = Base;
88 Vars[1] = Index;
89 }
90
46 bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) { 91 bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
47 int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits 92 int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits
48 : TypeARM32Attributes[Ty].ZExtAddrOffsetBits; 93 : TypeARM32Attributes[Ty].ZExtAddrOffsetBits;
49 if (Bits == 0) 94 if (Bits == 0)
50 return Offset == 0; 95 return Offset == 0;
51 // Note that encodings for offsets are sign-magnitude for ARM, so we check 96 // Note that encodings for offsets are sign-magnitude for ARM, so we check
52 // with IsAbsoluteUint(). 97 // with IsAbsoluteUint().
53 if (isScalarFloatingType(Ty)) 98 if (isScalarFloatingType(Ty))
54 return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset); 99 return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset);
55 return Utils::IsAbsoluteUint(Bits, Offset); 100 return Utils::IsAbsoluteUint(Bits, Offset);
56 } 101 }
57 102
103 OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty,
104 uint32_t Imm, uint32_t RotateAmt)
105 : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) {
106 NumVars = 0;
107 Vars = nullptr;
108 }
109
110 bool OperandARM32FlexImm::canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
111 uint32_t *Immed_8) {
112 // Avoid the more expensive test for frequent small immediate values.
jvoung (off chromium) 2015/05/14 22:42:07 Sort of borrowed from Dart and V8. They are both a
113 if (Immediate <= (0xFF)) {
114 *RotateAmt = 0;
115 *Immed_8 = Immediate;
116 return true;
117 }
118 // Note that immediate must be unsigned for the test to work correctly.
119 for (int Rot = 1; Rot < 16; Rot++) {
120 uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot);
121 if (Imm8 <= 0xFF) {
122 *RotateAmt = Rot;
123 *Immed_8 = Imm8;
124 return true;
125 }
126 }
127 return false;
128 }
129
130 OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg,
131 ShiftKind ShiftOp, Operand *ShiftAmt)
132 : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp),
133 ShiftAmt(ShiftAmt) {
134 NumVars = 1;
135 Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt);
136 if (ShiftVar)
137 ++NumVars;
138 Vars = Func->allocateArrayOf<Variable *>(NumVars);
139 Vars[0] = Reg;
140 if (ShiftVar)
141 Vars[1] = ShiftVar;
142 }
143
144 InstARM32Ldr::InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem)
145 : InstARM32(Func, InstARM32::Ldr, 1, Dest) {
146 addSource(Mem);
147 }
148
58 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) 149 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
59 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { 150 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) {
60 addSource(LR); 151 addSource(LR);
61 if (Source) 152 if (Source)
62 addSource(Source); 153 addSource(Source);
63 } 154 }
64 155
65 // ======================== Dump routines ======================== // 156 // ======================== Dump routines ======================== //
66 157
158 // Two-addr ops
159 template <> const char *InstARM32Movt::Opcode = "movt";
160 // Unary ops
161 template <> const char *InstARM32Movw::Opcode = "movw";
162 template <> const char *InstARM32Mvn::Opcode = "mvn";
163 // Mov-like ops
164 template <> const char *InstARM32Mov::Opcode = "mov";
165
67 void InstARM32::dump(const Cfg *Func) const { 166 void InstARM32::dump(const Cfg *Func) const {
68 if (!ALLOW_DUMP) 167 if (!ALLOW_DUMP)
69 return; 168 return;
70 Ostream &Str = Func->getContext()->getStrDump(); 169 Ostream &Str = Func->getContext()->getStrDump();
71 Str << "[ARM32] "; 170 Str << "[ARM32] ";
72 Inst::dump(Func); 171 Inst::dump(Func);
73 } 172 }
74 173
174 template <> void InstARM32Mov::emit(const Cfg *Func) const {
175 if (!ALLOW_DUMP)
176 return;
177 Ostream &Str = Func->getContext()->getStrEmit();
178 assert(getSrcSize() == 1);
179 Variable *Dest = getDest();
180 if (Dest->hasReg()) {
181 Str << "\t"
182 << "mov"
183 << "\t";
184 getDest()->emit(Func);
185 Str << ", ";
186 getSrc(0)->emit(Func);
187 } else {
188 Variable *Src0 = llvm::cast<Variable>(getSrc(0));
189 assert(Src0->hasReg());
190 Str << "\t"
191 << "str"
192 << "\t";
193 Src0->emit(Func);
194 Str << ", ";
195 Dest->emit(Func);
196 }
197 }
198
199 template <> void InstARM32Mov::emitIAS(const Cfg *Func) const {
200 assert(getSrcSize() == 1);
201 (void)Func;
202 llvm_unreachable("Not yet implemented");
203 }
204
205 void InstARM32Ldr::emit(const Cfg *Func) const {
206 if (!ALLOW_DUMP)
207 return;
208 Ostream &Str = Func->getContext()->getStrEmit();
209 assert(getSrcSize() == 1);
210 assert(getDest()->hasReg());
211 Type Ty = getSrc(0)->getType();
212 Str << "\tldr" << getWidthString(Ty) << "\t";
213 getDest()->emit(Func);
214 Str << ", ";
215 getSrc(0)->emit(Func);
216 }
217
218 void InstARM32Ldr::emitIAS(const Cfg *Func) const {
219 assert(getSrcSize() == 2);
220 (void)Func;
221 llvm_unreachable("Not yet implemented");
222 }
223
224 void InstARM32Ldr::dump(const Cfg *Func) const {
225 if (!ALLOW_DUMP)
226 return;
227 Ostream &Str = Func->getContext()->getStrDump();
228 dumpDest(Func);
229 Str << "ldr." << getSrc(0)->getType() << " ";
230 dumpSources(Func);
231 }
232
233 template <> void InstARM32Movw::emit(const Cfg *Func) const {
234 if (!ALLOW_DUMP)
235 return;
236 Ostream &Str = Func->getContext()->getStrEmit();
237 assert(getSrcSize() == 1);
238 Str << "\t" << Opcode << "\t";
239 getDest()->emit(Func);
240 Str << ", ";
241 Constant *Src0 = llvm::cast<Constant>(getSrc(0));
242 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
243 Str << "#:lower16:";
244 CR->emitWithoutPrefix(Func->getTarget());
245 } else {
246 Src0->emit(Func);
247 }
248 }
249
250 template <> void InstARM32Movt::emit(const Cfg *Func) const {
251 if (!ALLOW_DUMP)
252 return;
253 Ostream &Str = Func->getContext()->getStrEmit();
254 assert(getSrcSize() == 2);
255 Variable *Dest = getDest();
256 Constant *Src1 = llvm::cast<Constant>(getSrc(1));
257 Str << "\t" << Opcode << "\t";
258 Dest->emit(Func);
259 Str << ", ";
260 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
261 Str << "#:upper16:";
262 CR->emitWithoutPrefix(Func->getTarget());
263 } else {
264 Src1->emit(Func);
265 }
266 }
267
75 void InstARM32Ret::emit(const Cfg *Func) const { 268 void InstARM32Ret::emit(const Cfg *Func) const {
76 if (!ALLOW_DUMP) 269 if (!ALLOW_DUMP)
77 return; 270 return;
78 assert(getSrcSize() > 0); 271 assert(getSrcSize() > 0);
79 Variable *LR = llvm::cast<Variable>(getSrc(0)); 272 Variable *LR = llvm::cast<Variable>(getSrc(0));
80 assert(LR->hasReg()); 273 assert(LR->hasReg());
81 assert(LR->getRegNum() == RegARM32::Reg_lr); 274 assert(LR->getRegNum() == RegARM32::Reg_lr);
82 Ostream &Str = Func->getContext()->getStrEmit(); 275 Ostream &Str = Func->getContext()->getStrEmit();
83 Str << "\tbx\t"; 276 Str << "\tbx\t";
84 LR->emit(Func); 277 LR->emit(Func);
85 } 278 }
86 279
87 void InstARM32Ret::emitIAS(const Cfg *Func) const { 280 void InstARM32Ret::emitIAS(const Cfg *Func) const {
88 (void)Func; 281 (void)Func;
89 llvm_unreachable("Not yet implemented"); 282 llvm_unreachable("Not yet implemented");
90 } 283 }
91 284
92 void InstARM32Ret::dump(const Cfg *Func) const { 285 void InstARM32Ret::dump(const Cfg *Func) const {
93 if (!ALLOW_DUMP) 286 if (!ALLOW_DUMP)
94 return; 287 return;
95 Ostream &Str = Func->getContext()->getStrDump(); 288 Ostream &Str = Func->getContext()->getStrDump();
96 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType()); 289 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
97 Str << "ret." << Ty << " "; 290 Str << "ret." << Ty << " ";
98 dumpSources(Func); 291 dumpSources(Func);
99 } 292 }
100 293
294 void OperandARM32Mem::emit(const Cfg *Func) const {
295 if (!ALLOW_DUMP)
296 return;
297 Ostream &Str = Func->getContext()->getStrEmit();
298 Str << "[";
299 getBase()->emit(Func);
300 switch (getAddrMode()) {
301 case PostIndex:
302 case NegPostIndex:
303 Str << "], ";
304 break;
305 default:
306 Str << ", ";
307 break;
308 }
309 if (isRegReg()) {
310 if (isNegAddrMode()) {
311 Str << "-";
312 }
313 getIndex()->emit(Func);
314 if (getShiftOp() != kNoShift) {
315 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
316 << getShiftAmt();
317 }
318 } else {
319 getOffset()->emit(Func);
320 }
321 switch (getAddrMode()) {
322 case Offset:
323 case NegOffset:
324 Str << "]";
325 break;
326 case PreIndex:
327 case NegPreIndex:
328 Str << "]!";
329 break;
330 case PostIndex:
331 case NegPostIndex:
332 // Brace is already closed off.
333 break;
334 }
335 }
336
337 void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
338 if (!ALLOW_DUMP)
339 return;
340 Str << "[";
341 if (Func)
342 getBase()->dump(Func);
343 else
344 getBase()->dump(Str);
345 Str << ", ";
346 if (isRegReg()) {
347 if (isNegAddrMode()) {
348 Str << "-";
349 }
350 if (Func)
351 getIndex()->dump(Func);
352 else
353 getIndex()->dump(Str);
354 if (getShiftOp() != kNoShift) {
355 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
356 << getShiftAmt();
357 }
358 } else {
359 getOffset()->dump(Func, Str);
360 }
361 Str << "] AddrMode==" << getAddrMode() << "\n";
362 }
363
364 void OperandARM32FlexImm::emit(const Cfg *Func) const {
365 if (!ALLOW_DUMP)
366 return;
367 Ostream &Str = Func->getContext()->getStrEmit();
368 uint32_t Imm = getImm();
369 uint32_t RotateAmt = getRotateAmt();
370 Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
371 }
372
373 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
374 if (!ALLOW_DUMP)
375 return;
376 uint32_t Imm = getImm();
377 uint32_t RotateAmt = getRotateAmt();
378 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
379 }
380
381 void OperandARM32FlexReg::emit(const Cfg *Func) const {
382 if (!ALLOW_DUMP)
383 return;
384 Ostream &Str = Func->getContext()->getStrEmit();
385 getReg()->emit(Func);
386 if (getShiftOp() != kNoShift) {
387 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
388 getShiftAmt()->emit(Func);
389 }
390 }
391
392 void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
393 if (!ALLOW_DUMP)
394 return;
395 Variable *Reg = getReg();
396 if (Func)
397 Reg->dump(Func);
398 else
399 Reg->dump(Str);
400 if (getShiftOp() != kNoShift) {
401 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
402 if (Func)
403 getShiftAmt()->dump(Func);
404 else
405 getShiftAmt()->dump(Str);
406 }
407 }
408
101 } // end of namespace Ice 409 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698