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

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: fix warnings, etc 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
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceInstARM32.def » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 assert(Dest == Inst->getSrc(0));
63 Operand *Src1 = Inst->getSrc(1);
64 Str << "\t" << Opcode << "\t";
65 Dest->emit(Func);
66 Str << ", ";
67 Src1->emit(Func);
68 }
69
70 OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base,
71 ConstantInteger32 *ImmOffset, AddrMode Mode)
72 : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr),
73 ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) {
74 // The Neg modes are only needed for Reg +/- Reg.
75 assert(!isNegAddrMode());
76 NumVars = 1;
77 Vars = &this->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.
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 << "\t"
213 << "ldr" << getWidthString(Ty) << "\t";
214 getDest()->emit(Func);
215 Str << ", ";
216 getSrc(0)->emit(Func);
217 }
218
219 void InstARM32Ldr::emitIAS(const Cfg *Func) const {
220 assert(getSrcSize() == 2);
221 (void)Func;
222 llvm_unreachable("Not yet implemented");
223 }
224
225 void InstARM32Ldr::dump(const Cfg *Func) const {
226 if (!ALLOW_DUMP)
227 return;
228 Ostream &Str = Func->getContext()->getStrDump();
229 dumpDest(Func);
230 Str << "ldr." << getSrc(0)->getType() << " ";
231 dumpSources(Func);
232 }
233
234 template <> void InstARM32Movw::emit(const Cfg *Func) const {
235 if (!ALLOW_DUMP)
236 return;
237 Ostream &Str = Func->getContext()->getStrEmit();
238 assert(getSrcSize() == 1);
239 Str << "\t" << Opcode << "\t";
240 getDest()->emit(Func);
241 Str << ", ";
242 Constant *Src0 = llvm::cast<Constant>(getSrc(0));
243 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
244 Str << "#:lower16:";
245 CR->emitWithoutPrefix(Func->getTarget());
246 } else {
247 Src0->emit(Func);
248 }
249 }
250
251 template <> void InstARM32Movt::emit(const Cfg *Func) const {
252 if (!ALLOW_DUMP)
253 return;
254 Ostream &Str = Func->getContext()->getStrEmit();
255 assert(getSrcSize() == 2);
256 Variable *Dest = getDest();
257 Constant *Src1 = llvm::cast<Constant>(getSrc(1));
258 Str << "\t" << Opcode << "\t";
259 Dest->emit(Func);
260 Str << ", ";
261 if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
262 Str << "#:upper16:";
263 CR->emitWithoutPrefix(Func->getTarget());
264 } else {
265 Src1->emit(Func);
266 }
267 }
268
75 void InstARM32Ret::emit(const Cfg *Func) const { 269 void InstARM32Ret::emit(const Cfg *Func) const {
76 if (!ALLOW_DUMP) 270 if (!ALLOW_DUMP)
77 return; 271 return;
78 assert(getSrcSize() > 0); 272 assert(getSrcSize() > 0);
79 Variable *LR = llvm::cast<Variable>(getSrc(0)); 273 Variable *LR = llvm::cast<Variable>(getSrc(0));
80 assert(LR->hasReg()); 274 assert(LR->hasReg());
81 assert(LR->getRegNum() == RegARM32::Reg_lr); 275 assert(LR->getRegNum() == RegARM32::Reg_lr);
82 Ostream &Str = Func->getContext()->getStrEmit(); 276 Ostream &Str = Func->getContext()->getStrEmit();
83 Str << "\tbx\t"; 277 Str << "\tbx\t";
84 LR->emit(Func); 278 LR->emit(Func);
85 } 279 }
86 280
87 void InstARM32Ret::emitIAS(const Cfg *Func) const { 281 void InstARM32Ret::emitIAS(const Cfg *Func) const {
88 (void)Func; 282 (void)Func;
89 llvm_unreachable("Not yet implemented"); 283 llvm_unreachable("Not yet implemented");
90 } 284 }
91 285
92 void InstARM32Ret::dump(const Cfg *Func) const { 286 void InstARM32Ret::dump(const Cfg *Func) const {
93 if (!ALLOW_DUMP) 287 if (!ALLOW_DUMP)
94 return; 288 return;
95 Ostream &Str = Func->getContext()->getStrDump(); 289 Ostream &Str = Func->getContext()->getStrDump();
96 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType()); 290 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
97 Str << "ret." << Ty << " "; 291 Str << "ret." << Ty << " ";
98 dumpSources(Func); 292 dumpSources(Func);
99 } 293 }
100 294
295 void OperandARM32Mem::emit(const Cfg *Func) const {
296 if (!ALLOW_DUMP)
297 return;
298 Ostream &Str = Func->getContext()->getStrEmit();
299 Str << "[";
300 getBase()->emit(Func);
301 switch (getAddrMode()) {
302 case PostIndex:
303 case NegPostIndex:
304 Str << "], ";
305 break;
306 default:
307 Str << ", ";
308 break;
309 }
310 if (isRegReg()) {
311 if (isNegAddrMode()) {
312 Str << "-";
313 }
314 getIndex()->emit(Func);
315 if (getShiftOp() != kNoShift) {
316 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
317 << getShiftAmt();
318 }
319 } else {
320 getOffset()->emit(Func);
321 }
322 switch (getAddrMode()) {
323 case Offset:
324 case NegOffset:
325 Str << "]";
326 break;
327 case PreIndex:
328 case NegPreIndex:
329 Str << "]!";
330 break;
331 case PostIndex:
332 case NegPostIndex:
333 // Brace is already closed off.
334 break;
335 }
336 }
337
338 void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
339 if (!ALLOW_DUMP)
340 return;
341 Str << "[";
342 if (Func)
343 getBase()->dump(Func);
344 else
345 getBase()->dump(Str);
346 Str << ", ";
347 if (isRegReg()) {
348 if (isNegAddrMode()) {
349 Str << "-";
350 }
351 if (Func)
352 getIndex()->dump(Func);
353 else
354 getIndex()->dump(Str);
355 if (getShiftOp() != kNoShift) {
356 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
357 << getShiftAmt();
358 }
359 } else {
360 getOffset()->dump(Func, Str);
361 }
362 Str << "] AddrMode==" << getAddrMode() << "\n";
363 }
364
365 void OperandARM32FlexImm::emit(const Cfg *Func) const {
366 if (!ALLOW_DUMP)
367 return;
368 Ostream &Str = Func->getContext()->getStrEmit();
369 uint32_t Imm = getImm();
370 uint32_t RotateAmt = getRotateAmt();
371 Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
372 }
373
374 void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
375 if (!ALLOW_DUMP)
376 return;
377 uint32_t Imm = getImm();
378 uint32_t RotateAmt = getRotateAmt();
379 Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
380 }
381
382 void OperandARM32FlexReg::emit(const Cfg *Func) const {
383 if (!ALLOW_DUMP)
384 return;
385 Ostream &Str = Func->getContext()->getStrEmit();
386 getReg()->emit(Func);
387 if (getShiftOp() != kNoShift) {
388 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
389 getShiftAmt()->emit(Func);
390 }
391 }
392
393 void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
394 if (!ALLOW_DUMP)
395 return;
396 Variable *Reg = getReg();
397 if (Func)
398 Reg->dump(Func);
399 else
400 Reg->dump(Str);
401 if (getShiftOp() != kNoShift) {
402 Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
403 if (Func)
404 getShiftAmt()->dump(Func);
405 else
406 getShiftAmt()->dump(Str);
407 }
408 }
409
101 } // end of namespace Ice 410 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceInstARM32.def » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698