blob: b625249234cdf5b382b552433d35b2478cf7fc2d [file] [log] [blame]
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_ASSEMBLER_ARM_H_
4#define ART_SRC_ASSEMBLER_ARM_H_
5
Carl Shapiroa2e18e12011-06-21 18:57:55 -07006#include "src/constants_arm.h"
7#include "src/logging.h"
8#include "src/utils.h"
9
Carl Shapiro6b6b5f02011-06-21 15:05:09 -070010namespace art {
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -070011
Carl Shapiroa2e18e12011-06-21 18:57:55 -070012// Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1.
13class ShifterOperand {
14 public:
15 // Data-processing operands - Uninitialized
16 ShifterOperand() {
17 type_ = -1;
18 }
19
20 // Data-processing operands - Immediate
21 explicit ShifterOperand(uint32_t immediate) {
22 CHECK(immediate < (1 << kImmed8Bits));
23 type_ = 1;
24 encoding_ = immediate;
25 }
26
27 // Data-processing operands - Rotated immediate
28 ShifterOperand(uint32_t rotate, uint32_t immed8) {
29 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
30 type_ = 1;
31 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
32 }
33
34 // Data-processing operands - Register
35 explicit ShifterOperand(Register rm) {
36 type_ = 0;
37 encoding_ = static_cast<uint32_t>(rm);
38 }
39
40 // Data-processing operands - Logical shift/rotate by immediate
41 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
42 CHECK(shift_imm < (1 << kShiftImmBits));
43 type_ = 0;
44 encoding_ = shift_imm << kShiftImmShift |
45 static_cast<uint32_t>(shift) << kShiftShift |
46 static_cast<uint32_t>(rm);
47 }
48
49 // Data-processing operands - Logical shift/rotate by register
50 ShifterOperand(Register rm, Shift shift, Register rs) {
51 type_ = 0;
52 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
53 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
54 static_cast<uint32_t>(rm);
55 }
56
57 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
58 // Avoid the more expensive test for frequent small immediate values.
59 if (immediate < (1 << kImmed8Bits)) {
60 shifter_op->type_ = 1;
61 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
62 return true;
63 }
64 // Note that immediate must be unsigned for the test to work correctly.
65 for (int rot = 0; rot < 16; rot++) {
66 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
67 if (imm8 < (1 << kImmed8Bits)) {
68 shifter_op->type_ = 1;
69 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
70 return true;
71 }
72 }
73 return false;
74 }
75
76 private:
77 bool is_valid() const { return (type_ == 0) || (type_ == 1); }
78
79 uint32_t type() const {
80 CHECK(is_valid());
81 return type_;
82 }
83
84 uint32_t encoding() const {
85 CHECK(is_valid());
86 return encoding_;
87 }
88
89 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
90 uint32_t encoding_;
91
92 friend class Assembler;
93#ifdef SOURCE_ASSEMBLER_SUPPORT
94 friend class BinaryAssembler;
95#endif
96};
97
98
99enum LoadOperandType {
100 kLoadSignedByte,
101 kLoadUnsignedByte,
102 kLoadSignedHalfword,
103 kLoadUnsignedHalfword,
104 kLoadWord,
105 kLoadWordPair,
106 kLoadSWord,
107 kLoadDWord
108};
109
110
111enum StoreOperandType {
112 kStoreByte,
113 kStoreHalfword,
114 kStoreWord,
115 kStoreWordPair,
116 kStoreSWord,
117 kStoreDWord
118};
119
120
121// Load/store multiple addressing mode.
122enum BlockAddressMode {
123 // bit encoding P U W
124 DA = (0|0|0) << 21, // decrement after
125 IA = (0|4|0) << 21, // increment after
126 DB = (8|0|0) << 21, // decrement before
127 IB = (8|4|0) << 21, // increment before
128 DA_W = (0|0|1) << 21, // decrement after with writeback to base
129 IA_W = (0|4|1) << 21, // increment after with writeback to base
130 DB_W = (8|0|1) << 21, // decrement before with writeback to base
131 IB_W = (8|4|1) << 21 // increment before with writeback to base
132};
133
134
135class Address {
136 public:
137 // Memory operand addressing mode
138 enum Mode {
139 // bit encoding P U W
140 Offset = (8|4|0) << 21, // offset (w/o writeback to base)
141 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
142 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
143 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
144 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
145 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
146 };
147
148 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
149 CHECK(IsAbsoluteUint(12, offset));
150 if (offset < 0) {
151 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
152 } else {
153 encoding_ = am | offset;
154 }
155 encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
156 }
157
158 static bool CanHoldLoadOffset(LoadOperandType type, int offset);
159 static bool CanHoldStoreOffset(StoreOperandType type, int offset);
160
161 private:
162 uint32_t encoding() const { return encoding_; }
163
164 // Encoding for addressing mode 3.
165 uint32_t encoding3() const {
166 const uint32_t offset_mask = (1 << 12) - 1;
167 uint32_t offset = encoding_ & offset_mask;
168 CHECK(offset < 256);
169 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf);
170 }
171
172 // Encoding for vfp load/store addressing.
173 uint32_t vencoding() const {
174 const uint32_t offset_mask = (1 << 12) - 1;
175 uint32_t offset = encoding_ & offset_mask;
176 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020.
177 CHECK(IsAligned(offset, 2)); // Multiple of 4.
178 int mode = encoding_ & ((8|4|1) << 21);
179 CHECK((mode == Offset) || (mode == NegOffset));
180 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2);
181 if (mode == Offset) {
182 vencoding |= 1 << 23;
183 }
184 return vencoding;
185 }
186
187 uint32_t encoding_;
188
189 friend class Assembler;
190};
191
192
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700193class Assembler {
Carl Shapiroa2e18e12011-06-21 18:57:55 -0700194 public:
195 Assembler() : buffer_() {}
196
197 // Data-processing instructions.
198 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
199
200 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
201
202 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
203 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
204
205 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
206 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
207
208 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
209
210 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
211
212 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
213
214 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
215
216 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
217
218 void tst(Register rn, ShifterOperand so, Condition cond = AL);
219
220 void teq(Register rn, ShifterOperand so, Condition cond = AL);
221
222 void cmp(Register rn, ShifterOperand so, Condition cond = AL);
223
224 void cmn(Register rn, ShifterOperand so, Condition cond = AL);
225
226 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
227 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
228
229 void mov(Register rd, ShifterOperand so, Condition cond = AL);
230 void movs(Register rd, ShifterOperand so, Condition cond = AL);
231
232 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
233
234 void mvn(Register rd, ShifterOperand so, Condition cond = AL);
235 void mvns(Register rd, ShifterOperand so, Condition cond = AL);
236
237 // Miscellaneous data-processing instructions.
238 void clz(Register rd, Register rm, Condition cond = AL);
239 void movw(Register rd, uint16_t imm16, Condition cond = AL);
240 void movt(Register rd, uint16_t imm16, Condition cond = AL);
241
242 // Multiply instructions.
243 void mul(Register rd, Register rn, Register rm, Condition cond = AL);
244 void mla(Register rd, Register rn, Register rm, Register ra,
245 Condition cond = AL);
246 void mls(Register rd, Register rn, Register rm, Register ra,
247 Condition cond = AL);
248 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
249 Condition cond = AL);
250
251 // Load/store instructions.
252 void ldr(Register rd, Address ad, Condition cond = AL);
253 void str(Register rd, Address ad, Condition cond = AL);
254
255 void ldrb(Register rd, Address ad, Condition cond = AL);
256 void strb(Register rd, Address ad, Condition cond = AL);
257
258 void ldrh(Register rd, Address ad, Condition cond = AL);
259 void strh(Register rd, Address ad, Condition cond = AL);
260
261 void ldrsb(Register rd, Address ad, Condition cond = AL);
262 void ldrsh(Register rd, Address ad, Condition cond = AL);
263
264 void ldrd(Register rd, Address ad, Condition cond = AL);
265 void strd(Register rd, Address ad, Condition cond = AL);
266
267 void ldm(BlockAddressMode am, Register base,
268 RegList regs, Condition cond = AL);
269 void stm(BlockAddressMode am, Register base,
270 RegList regs, Condition cond = AL);
271
272 void ldrex(Register rd, Register rn, Condition cond = AL);
273 void strex(Register rd, Register rt, Register rn, Condition cond = AL);
274
275 // Miscellaneous instructions.
276 void clrex();
277 void nop(Condition cond = AL);
278
279 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
280 void bkpt(uint16_t imm16);
281 void svc(uint32_t imm24);
282
283 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
284 void vmovsr(SRegister sn, Register rt, Condition cond = AL);
285 void vmovrs(Register rt, SRegister sn, Condition cond = AL);
286 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
287 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
288 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
289 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
290 void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
291 void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
292
293 // Returns false if the immediate cannot be encoded.
294 bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
295 bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
296
297 void vldrs(SRegister sd, Address ad, Condition cond = AL);
298 void vstrs(SRegister sd, Address ad, Condition cond = AL);
299 void vldrd(DRegister dd, Address ad, Condition cond = AL);
300 void vstrd(DRegister dd, Address ad, Condition cond = AL);
301
302 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
303 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
304 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
305 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
306 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
307 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
308 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
309 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
310 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
311 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
312 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
313 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
314
315 void vabss(SRegister sd, SRegister sm, Condition cond = AL);
316 void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
317 void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
318 void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
319 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
320 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
321
322 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
323 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
324 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
325 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
326 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
327 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
328 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
329 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
330 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
331 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
332
333 void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
334 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
335 void vcmpsz(SRegister sd, Condition cond = AL);
336 void vcmpdz(DRegister dd, Condition cond = AL);
337 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
338
339 // Branch instructions.
340 void b(Label* label, Condition cond = AL);
341 void bl(Label* label, Condition cond = AL);
342 void blx(Register rm, Condition cond = AL);
343
344 // Macros.
345 // Add signed constant value to rd. May clobber IP.
346 void AddConstant(Register rd, int32_t value, Condition cond = AL);
347 void AddConstant(Register rd, Register rn, int32_t value,
348 Condition cond = AL);
349 void AddConstantSetFlags(Register rd, Register rn, int32_t value,
350 Condition cond = AL);
351 void AddConstantWithCarry(Register rd, Register rn, int32_t value,
352 Condition cond = AL);
353
354 // Load and Store. May clobber IP.
355 void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
356 void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
357 void LoadDImmediate(DRegister dd, double value,
358 Register scratch, Condition cond = AL);
359 void MarkExceptionHandler(Label* label);
360 void LoadFromOffset(LoadOperandType type,
361 Register reg,
362 Register base,
363 int32_t offset,
364 Condition cond = AL);
365 void StoreToOffset(StoreOperandType type,
366 Register reg,
367 Register base,
368 int32_t offset,
369 Condition cond = AL);
370 void LoadSFromOffset(SRegister reg,
371 Register base,
372 int32_t offset,
373 Condition cond = AL);
374 void StoreSToOffset(SRegister reg,
375 Register base,
376 int32_t offset,
377 Condition cond = AL);
378 void LoadDFromOffset(DRegister reg,
379 Register base,
380 int32_t offset,
381 Condition cond = AL);
382 void StoreDToOffset(DRegister reg,
383 Register base,
384 int32_t offset,
385 Condition cond = AL);
386
387 void Push(Register rd, Condition cond = AL);
388 void Pop(Register rd, Condition cond = AL);
389
390 void PushList(RegList regs, Condition cond = AL);
391 void PopList(RegList regs, Condition cond = AL);
392
393 void Mov(Register rd, Register rm, Condition cond = AL);
394
395 // Convenience shift instructions. Use mov instruction with shifter operand
396 // for variants setting the status flags or using a register shift count.
397 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
398 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
399 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
400 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
401 void Rrx(Register rd, Register rm, Condition cond = AL);
402
403 // Encode a signed constant in tst instructions, only affecting the flags.
404 void EncodeUint32InTstInstructions(uint32_t data);
405 // ... and decode from a pc pointing to the start of encoding instructions.
406 static uint32_t DecodeUint32FromTstInstructions(uword pc);
407 static bool IsInstructionForExceptionHandling(uword pc);
408
409 // Debugging and bringup support.
410 void Stop(const char* message);
411 void Unimplemented(const char* message);
412 void Untested(const char* message);
413 void Unreachable(const char* message);
414
415 // Emit data (e.g. encoded instruction or immediate) to the
416 // instruction stream.
417 void Emit(int32_t value);
418
419 void Bind(Label* label);
420
421 private:
422 AssemblerBuffer buffer_;
423
424 void EmitType01(Condition cond,
425 int type,
426 Opcode opcode,
427 int set_cc,
428 Register rn,
429 Register rd,
430 ShifterOperand so);
431
432 void EmitType5(Condition cond, int offset, bool link);
433
434 void EmitMemOp(Condition cond,
435 bool load,
436 bool byte,
437 Register rd,
438 Address ad);
439
440 void EmitMemOpAddressMode3(Condition cond,
441 int32_t mode,
442 Register rd,
443 Address ad);
444
445 void EmitMultiMemOp(Condition cond,
446 BlockAddressMode am,
447 bool load,
448 Register base,
449 RegList regs);
450
451 void EmitShiftImmediate(Condition cond,
452 Shift opcode,
453 Register rd,
454 Register rm,
455 ShifterOperand so);
456
457 void EmitShiftRegister(Condition cond,
458 Shift opcode,
459 Register rd,
460 Register rm,
461 ShifterOperand so);
462
463 void EmitMulOp(Condition cond,
464 int32_t opcode,
465 Register rd,
466 Register rn,
467 Register rm,
468 Register rs);
469
470 void EmitVFPsss(Condition cond,
471 int32_t opcode,
472 SRegister sd,
473 SRegister sn,
474 SRegister sm);
475
476 void EmitVFPddd(Condition cond,
477 int32_t opcode,
478 DRegister dd,
479 DRegister dn,
480 DRegister dm);
481
482 void EmitVFPsd(Condition cond,
483 int32_t opcode,
484 SRegister sd,
485 DRegister dm);
486
487 void EmitVFPds(Condition cond,
488 int32_t opcode,
489 DRegister dd,
490 SRegister sm);
491
492 void EmitBranch(Condition cond, Label* label, bool link);
493 static int32_t EncodeBranchOffset(int offset, int32_t inst);
494 static int DecodeBranchOffset(int32_t inst);
495 int32_t EncodeTstOffset(int offset, int32_t inst);
496 int DecodeTstOffset(int32_t inst);
497
498 // Returns whether or not the given register is used for passing parameters.
499 static int RegisterCompare(const Register* reg1, const Register* reg2) {
500 return *reg1 - *reg2;
501 }
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700502};
503
Carl Shapiro6b6b5f02011-06-21 15:05:09 -0700504} // namespace art
Carl Shapiroa5d5cfd2011-06-21 12:46:59 -0700505
506#endif // ART_SRC_ASSEMBLER_ARM_H_