1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
18 #define ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
19
20 #include <vector>
21
22 #include "base/arena_containers.h"
23 #include "base/bit_utils.h"
24 #include "base/macros.h"
25 #include "constants_x86_64.h"
26 #include "globals.h"
27 #include "managed_register_x86_64.h"
28 #include "offsets.h"
29 #include "utils/array_ref.h"
30 #include "utils/assembler.h"
31
32 namespace art {
33 namespace x86_64 {
34
35 // Encodes an immediate value for operands.
36 //
37 // Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted
38 // to 32b.
39 //
40 // Note: As we support cross-compilation, the value type must be int64_t. Please be aware of
41 // conversion rules in expressions regarding negation, especially size_t on 32b.
42 class Immediate : public ValueObject {
43 public:
Immediate(int64_t value_in)44 explicit Immediate(int64_t value_in) : value_(value_in) {}
45
value()46 int64_t value() const { return value_; }
47
is_int8()48 bool is_int8() const { return IsInt<8>(value_); }
is_uint8()49 bool is_uint8() const { return IsUint<8>(value_); }
is_int16()50 bool is_int16() const { return IsInt<16>(value_); }
is_uint16()51 bool is_uint16() const { return IsUint<16>(value_); }
is_int32()52 bool is_int32() const { return IsInt<32>(value_); }
53
54 private:
55 const int64_t value_;
56 };
57
58
59 class Operand : public ValueObject {
60 public:
mod()61 uint8_t mod() const {
62 return (encoding_at(0) >> 6) & 3;
63 }
64
rm()65 Register rm() const {
66 return static_cast<Register>(encoding_at(0) & 7);
67 }
68
scale()69 ScaleFactor scale() const {
70 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
71 }
72
index()73 Register index() const {
74 return static_cast<Register>((encoding_at(1) >> 3) & 7);
75 }
76
base()77 Register base() const {
78 return static_cast<Register>(encoding_at(1) & 7);
79 }
80
rex()81 uint8_t rex() const {
82 return rex_;
83 }
84
disp8()85 int8_t disp8() const {
86 CHECK_GE(length_, 2);
87 return static_cast<int8_t>(encoding_[length_ - 1]);
88 }
89
disp32()90 int32_t disp32() const {
91 CHECK_GE(length_, 5);
92 int32_t value;
93 memcpy(&value, &encoding_[length_ - 4], sizeof(value));
94 return value;
95 }
96
IsRegister(CpuRegister reg)97 bool IsRegister(CpuRegister reg) const {
98 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
99 && ((encoding_[0] & 0x07) == reg.LowBits()) // Register codes match.
100 && (reg.NeedsRex() == ((rex_ & 1) != 0)); // REX.000B bits match.
101 }
102
GetFixup()103 AssemblerFixup* GetFixup() const {
104 return fixup_;
105 }
106
107 protected:
108 // Operand can be sub classed (e.g: Address).
Operand()109 Operand() : rex_(0), length_(0), fixup_(nullptr) { }
110
SetModRM(uint8_t mod_in,CpuRegister rm_in)111 void SetModRM(uint8_t mod_in, CpuRegister rm_in) {
112 CHECK_EQ(mod_in & ~3, 0);
113 if (rm_in.NeedsRex()) {
114 rex_ |= 0x41; // REX.000B
115 }
116 encoding_[0] = (mod_in << 6) | rm_in.LowBits();
117 length_ = 1;
118 }
119
SetSIB(ScaleFactor scale_in,CpuRegister index_in,CpuRegister base_in)120 void SetSIB(ScaleFactor scale_in, CpuRegister index_in, CpuRegister base_in) {
121 CHECK_EQ(length_, 1);
122 CHECK_EQ(scale_in & ~3, 0);
123 if (base_in.NeedsRex()) {
124 rex_ |= 0x41; // REX.000B
125 }
126 if (index_in.NeedsRex()) {
127 rex_ |= 0x42; // REX.00X0
128 }
129 encoding_[1] = (scale_in << 6) | (static_cast<uint8_t>(index_in.LowBits()) << 3) |
130 static_cast<uint8_t>(base_in.LowBits());
131 length_ = 2;
132 }
133
SetDisp8(int8_t disp)134 void SetDisp8(int8_t disp) {
135 CHECK(length_ == 1 || length_ == 2);
136 encoding_[length_++] = static_cast<uint8_t>(disp);
137 }
138
SetDisp32(int32_t disp)139 void SetDisp32(int32_t disp) {
140 CHECK(length_ == 1 || length_ == 2);
141 int disp_size = sizeof(disp);
142 memmove(&encoding_[length_], &disp, disp_size);
143 length_ += disp_size;
144 }
145
SetFixup(AssemblerFixup * fixup)146 void SetFixup(AssemblerFixup* fixup) {
147 fixup_ = fixup;
148 }
149
150 private:
151 uint8_t rex_;
152 uint8_t length_;
153 uint8_t encoding_[6];
154 AssemblerFixup* fixup_;
155
Operand(CpuRegister reg)156 explicit Operand(CpuRegister reg) : rex_(0), length_(0), fixup_(nullptr) { SetModRM(3, reg); }
157
158 // Get the operand encoding byte at the given index.
encoding_at(int index_in)159 uint8_t encoding_at(int index_in) const {
160 CHECK_GE(index_in, 0);
161 CHECK_LT(index_in, length_);
162 return encoding_[index_in];
163 }
164
165 friend class X86_64Assembler;
166 };
167
168
169 class Address : public Operand {
170 public:
Address(CpuRegister base_in,int32_t disp)171 Address(CpuRegister base_in, int32_t disp) {
172 Init(base_in, disp);
173 }
174
Address(CpuRegister base_in,Offset disp)175 Address(CpuRegister base_in, Offset disp) {
176 Init(base_in, disp.Int32Value());
177 }
178
Address(CpuRegister base_in,FrameOffset disp)179 Address(CpuRegister base_in, FrameOffset disp) {
180 CHECK_EQ(base_in.AsRegister(), RSP);
181 Init(CpuRegister(RSP), disp.Int32Value());
182 }
183
Address(CpuRegister base_in,MemberOffset disp)184 Address(CpuRegister base_in, MemberOffset disp) {
185 Init(base_in, disp.Int32Value());
186 }
187
Init(CpuRegister base_in,int32_t disp)188 void Init(CpuRegister base_in, int32_t disp) {
189 if (disp == 0 && base_in.LowBits() != RBP) {
190 SetModRM(0, base_in);
191 if (base_in.LowBits() == RSP) {
192 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
193 }
194 } else if (disp >= -128 && disp <= 127) {
195 SetModRM(1, base_in);
196 if (base_in.LowBits() == RSP) {
197 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
198 }
199 SetDisp8(disp);
200 } else {
201 SetModRM(2, base_in);
202 if (base_in.LowBits() == RSP) {
203 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
204 }
205 SetDisp32(disp);
206 }
207 }
208
209
Address(CpuRegister index_in,ScaleFactor scale_in,int32_t disp)210 Address(CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
211 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode.
212 SetModRM(0, CpuRegister(RSP));
213 SetSIB(scale_in, index_in, CpuRegister(RBP));
214 SetDisp32(disp);
215 }
216
Address(CpuRegister base_in,CpuRegister index_in,ScaleFactor scale_in,int32_t disp)217 Address(CpuRegister base_in, CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
218 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode.
219 if (disp == 0 && base_in.LowBits() != RBP) {
220 SetModRM(0, CpuRegister(RSP));
221 SetSIB(scale_in, index_in, base_in);
222 } else if (disp >= -128 && disp <= 127) {
223 SetModRM(1, CpuRegister(RSP));
224 SetSIB(scale_in, index_in, base_in);
225 SetDisp8(disp);
226 } else {
227 SetModRM(2, CpuRegister(RSP));
228 SetSIB(scale_in, index_in, base_in);
229 SetDisp32(disp);
230 }
231 }
232
233 // If no_rip is true then the Absolute address isn't RIP relative.
234 static Address Absolute(uintptr_t addr, bool no_rip = false) {
235 Address result;
236 if (no_rip) {
237 result.SetModRM(0, CpuRegister(RSP));
238 result.SetSIB(TIMES_1, CpuRegister(RSP), CpuRegister(RBP));
239 result.SetDisp32(addr);
240 } else {
241 // RIP addressing is done using RBP as the base register.
242 // The value in RBP isn't used. Instead the offset is added to RIP.
243 result.SetModRM(0, CpuRegister(RBP));
244 result.SetDisp32(addr);
245 }
246 return result;
247 }
248
249 // An RIP relative address that will be fixed up later.
RIP(AssemblerFixup * fixup)250 static Address RIP(AssemblerFixup* fixup) {
251 Address result;
252 // RIP addressing is done using RBP as the base register.
253 // The value in RBP isn't used. Instead the offset is added to RIP.
254 result.SetModRM(0, CpuRegister(RBP));
255 result.SetDisp32(0);
256 result.SetFixup(fixup);
257 return result;
258 }
259
260 // If no_rip is true then the Absolute address isn't RIP relative.
261 static Address Absolute(ThreadOffset<8> addr, bool no_rip = false) {
262 return Absolute(addr.Int32Value(), no_rip);
263 }
264
265 private:
Address()266 Address() {}
267 };
268
269
270 /**
271 * Class to handle constant area values.
272 */
273 class ConstantArea {
274 public:
ConstantArea(ArenaAllocator * arena)275 explicit ConstantArea(ArenaAllocator* arena) : buffer_(arena->Adapter(kArenaAllocAssembler)) {}
276
277 // Add a double to the constant area, returning the offset into
278 // the constant area where the literal resides.
279 size_t AddDouble(double v);
280
281 // Add a float to the constant area, returning the offset into
282 // the constant area where the literal resides.
283 size_t AddFloat(float v);
284
285 // Add an int32_t to the constant area, returning the offset into
286 // the constant area where the literal resides.
287 size_t AddInt32(int32_t v);
288
289 // Add an int32_t to the end of the constant area, returning the offset into
290 // the constant area where the literal resides.
291 size_t AppendInt32(int32_t v);
292
293 // Add an int64_t to the constant area, returning the offset into
294 // the constant area where the literal resides.
295 size_t AddInt64(int64_t v);
296
GetSize()297 size_t GetSize() const {
298 return buffer_.size() * elem_size_;
299 }
300
GetBuffer()301 ArrayRef<const int32_t> GetBuffer() const {
302 return ArrayRef<const int32_t>(buffer_);
303 }
304
305 private:
306 static constexpr size_t elem_size_ = sizeof(int32_t);
307 ArenaVector<int32_t> buffer_;
308 };
309
310
311 // This is equivalent to the Label class, used in a slightly different context. We
312 // inherit the functionality of the Label class, but prevent unintended
313 // derived-to-base conversions by making the base class private.
314 class NearLabel : private Label {
315 public:
NearLabel()316 NearLabel() : Label() {}
317
318 // Expose the Label routines that we need.
319 using Label::Position;
320 using Label::LinkPosition;
321 using Label::IsBound;
322 using Label::IsUnused;
323 using Label::IsLinked;
324
325 private:
326 using Label::BindTo;
327 using Label::LinkTo;
328
329 friend class x86_64::X86_64Assembler;
330
331 DISALLOW_COPY_AND_ASSIGN(NearLabel);
332 };
333
334
335 class X86_64Assembler FINAL : public Assembler {
336 public:
X86_64Assembler(ArenaAllocator * arena)337 explicit X86_64Assembler(ArenaAllocator* arena) : Assembler(arena), constant_area_(arena) {}
~X86_64Assembler()338 virtual ~X86_64Assembler() {}
339
340 /*
341 * Emit Machine Instructions.
342 */
343 void call(CpuRegister reg);
344 void call(const Address& address);
345 void call(Label* label);
346
347 void pushq(CpuRegister reg);
348 void pushq(const Address& address);
349 void pushq(const Immediate& imm);
350
351 void popq(CpuRegister reg);
352 void popq(const Address& address);
353
354 void movq(CpuRegister dst, const Immediate& src);
355 void movl(CpuRegister dst, const Immediate& src);
356 void movq(CpuRegister dst, CpuRegister src);
357 void movl(CpuRegister dst, CpuRegister src);
358
359 void movntl(const Address& dst, CpuRegister src);
360 void movntq(const Address& dst, CpuRegister src);
361
362 void movq(CpuRegister dst, const Address& src);
363 void movl(CpuRegister dst, const Address& src);
364 void movq(const Address& dst, CpuRegister src);
365 void movq(const Address& dst, const Immediate& imm);
366 void movl(const Address& dst, CpuRegister src);
367 void movl(const Address& dst, const Immediate& imm);
368
369 void cmov(Condition c, CpuRegister dst, CpuRegister src); // This is the 64b version.
370 void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit);
371 void cmov(Condition c, CpuRegister dst, const Address& src, bool is64bit);
372
373 void movzxb(CpuRegister dst, CpuRegister src);
374 void movzxb(CpuRegister dst, const Address& src);
375 void movsxb(CpuRegister dst, CpuRegister src);
376 void movsxb(CpuRegister dst, const Address& src);
377 void movb(CpuRegister dst, const Address& src);
378 void movb(const Address& dst, CpuRegister src);
379 void movb(const Address& dst, const Immediate& imm);
380
381 void movzxw(CpuRegister dst, CpuRegister src);
382 void movzxw(CpuRegister dst, const Address& src);
383 void movsxw(CpuRegister dst, CpuRegister src);
384 void movsxw(CpuRegister dst, const Address& src);
385 void movw(CpuRegister dst, const Address& src);
386 void movw(const Address& dst, CpuRegister src);
387 void movw(const Address& dst, const Immediate& imm);
388
389 void leaq(CpuRegister dst, const Address& src);
390 void leal(CpuRegister dst, const Address& src);
391
392 void movaps(XmmRegister dst, XmmRegister src);
393
394 void movss(XmmRegister dst, const Address& src);
395 void movss(const Address& dst, XmmRegister src);
396 void movss(XmmRegister dst, XmmRegister src);
397
398 void movsxd(CpuRegister dst, CpuRegister src);
399 void movsxd(CpuRegister dst, const Address& src);
400
401 void movd(XmmRegister dst, CpuRegister src); // Note: this is the r64 version, formally movq.
402 void movd(CpuRegister dst, XmmRegister src); // Note: this is the r64 version, formally movq.
403 void movd(XmmRegister dst, CpuRegister src, bool is64bit);
404 void movd(CpuRegister dst, XmmRegister src, bool is64bit);
405
406 void addss(XmmRegister dst, XmmRegister src);
407 void addss(XmmRegister dst, const Address& src);
408 void subss(XmmRegister dst, XmmRegister src);
409 void subss(XmmRegister dst, const Address& src);
410 void mulss(XmmRegister dst, XmmRegister src);
411 void mulss(XmmRegister dst, const Address& src);
412 void divss(XmmRegister dst, XmmRegister src);
413 void divss(XmmRegister dst, const Address& src);
414
415 void movsd(XmmRegister dst, const Address& src);
416 void movsd(const Address& dst, XmmRegister src);
417 void movsd(XmmRegister dst, XmmRegister src);
418
419 void addsd(XmmRegister dst, XmmRegister src);
420 void addsd(XmmRegister dst, const Address& src);
421 void subsd(XmmRegister dst, XmmRegister src);
422 void subsd(XmmRegister dst, const Address& src);
423 void mulsd(XmmRegister dst, XmmRegister src);
424 void mulsd(XmmRegister dst, const Address& src);
425 void divsd(XmmRegister dst, XmmRegister src);
426 void divsd(XmmRegister dst, const Address& src);
427
428 void cvtsi2ss(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
429 void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit);
430 void cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit);
431 void cvtsi2sd(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
432 void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit);
433 void cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit);
434
435 void cvtss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
436 void cvtss2sd(XmmRegister dst, XmmRegister src);
437 void cvtss2sd(XmmRegister dst, const Address& src);
438
439 void cvtsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
440 void cvtsd2ss(XmmRegister dst, XmmRegister src);
441 void cvtsd2ss(XmmRegister dst, const Address& src);
442
443 void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
444 void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit);
445 void cvttsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
446 void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit);
447
448 void cvtdq2pd(XmmRegister dst, XmmRegister src);
449
450 void comiss(XmmRegister a, XmmRegister b);
451 void comiss(XmmRegister a, const Address& b);
452 void comisd(XmmRegister a, XmmRegister b);
453 void comisd(XmmRegister a, const Address& b);
454 void ucomiss(XmmRegister a, XmmRegister b);
455 void ucomiss(XmmRegister a, const Address& b);
456 void ucomisd(XmmRegister a, XmmRegister b);
457 void ucomisd(XmmRegister a, const Address& b);
458
459 void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
460 void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
461
462 void sqrtsd(XmmRegister dst, XmmRegister src);
463 void sqrtss(XmmRegister dst, XmmRegister src);
464
465 void xorpd(XmmRegister dst, const Address& src);
466 void xorpd(XmmRegister dst, XmmRegister src);
467 void xorps(XmmRegister dst, const Address& src);
468 void xorps(XmmRegister dst, XmmRegister src);
469
470 void andpd(XmmRegister dst, const Address& src);
471 void andpd(XmmRegister dst, XmmRegister src);
472 void andps(XmmRegister dst, XmmRegister src);
473
474 void orpd(XmmRegister dst, XmmRegister src);
475 void orps(XmmRegister dst, XmmRegister src);
476
477 void flds(const Address& src);
478 void fstps(const Address& dst);
479 void fsts(const Address& dst);
480
481 void fldl(const Address& src);
482 void fstpl(const Address& dst);
483 void fstl(const Address& dst);
484
485 void fstsw();
486
487 void fucompp();
488
489 void fnstcw(const Address& dst);
490 void fldcw(const Address& src);
491
492 void fistpl(const Address& dst);
493 void fistps(const Address& dst);
494 void fildl(const Address& src);
495 void filds(const Address& src);
496
497 void fincstp();
498 void ffree(const Immediate& index);
499
500 void fsin();
501 void fcos();
502 void fptan();
503 void fprem();
504
505 void xchgl(CpuRegister dst, CpuRegister src);
506 void xchgq(CpuRegister dst, CpuRegister src);
507 void xchgl(CpuRegister reg, const Address& address);
508
509 void cmpw(const Address& address, const Immediate& imm);
510
511 void cmpl(CpuRegister reg, const Immediate& imm);
512 void cmpl(CpuRegister reg0, CpuRegister reg1);
513 void cmpl(CpuRegister reg, const Address& address);
514 void cmpl(const Address& address, CpuRegister reg);
515 void cmpl(const Address& address, const Immediate& imm);
516
517 void cmpq(CpuRegister reg0, CpuRegister reg1);
518 void cmpq(CpuRegister reg0, const Immediate& imm);
519 void cmpq(CpuRegister reg0, const Address& address);
520 void cmpq(const Address& address, const Immediate& imm);
521
522 void testl(CpuRegister reg1, CpuRegister reg2);
523 void testl(CpuRegister reg, const Address& address);
524 void testl(CpuRegister reg, const Immediate& imm);
525
526 void testq(CpuRegister reg1, CpuRegister reg2);
527 void testq(CpuRegister reg, const Address& address);
528
529 void andl(CpuRegister dst, const Immediate& imm);
530 void andl(CpuRegister dst, CpuRegister src);
531 void andl(CpuRegister reg, const Address& address);
532 void andq(CpuRegister dst, const Immediate& imm);
533 void andq(CpuRegister dst, CpuRegister src);
534 void andq(CpuRegister reg, const Address& address);
535
536 void orl(CpuRegister dst, const Immediate& imm);
537 void orl(CpuRegister dst, CpuRegister src);
538 void orl(CpuRegister reg, const Address& address);
539 void orq(CpuRegister dst, CpuRegister src);
540 void orq(CpuRegister dst, const Immediate& imm);
541 void orq(CpuRegister reg, const Address& address);
542
543 void xorl(CpuRegister dst, CpuRegister src);
544 void xorl(CpuRegister dst, const Immediate& imm);
545 void xorl(CpuRegister reg, const Address& address);
546 void xorq(CpuRegister dst, const Immediate& imm);
547 void xorq(CpuRegister dst, CpuRegister src);
548 void xorq(CpuRegister reg, const Address& address);
549
550 void addl(CpuRegister dst, CpuRegister src);
551 void addl(CpuRegister reg, const Immediate& imm);
552 void addl(CpuRegister reg, const Address& address);
553 void addl(const Address& address, CpuRegister reg);
554 void addl(const Address& address, const Immediate& imm);
555
556 void addq(CpuRegister reg, const Immediate& imm);
557 void addq(CpuRegister dst, CpuRegister src);
558 void addq(CpuRegister dst, const Address& address);
559
560 void subl(CpuRegister dst, CpuRegister src);
561 void subl(CpuRegister reg, const Immediate& imm);
562 void subl(CpuRegister reg, const Address& address);
563
564 void subq(CpuRegister reg, const Immediate& imm);
565 void subq(CpuRegister dst, CpuRegister src);
566 void subq(CpuRegister dst, const Address& address);
567
568 void cdq();
569 void cqo();
570
571 void idivl(CpuRegister reg);
572 void idivq(CpuRegister reg);
573
574 void imull(CpuRegister dst, CpuRegister src);
575 void imull(CpuRegister reg, const Immediate& imm);
576 void imull(CpuRegister dst, CpuRegister src, const Immediate& imm);
577 void imull(CpuRegister reg, const Address& address);
578
579 void imulq(CpuRegister src);
580 void imulq(CpuRegister dst, CpuRegister src);
581 void imulq(CpuRegister reg, const Immediate& imm);
582 void imulq(CpuRegister reg, const Address& address);
583 void imulq(CpuRegister dst, CpuRegister reg, const Immediate& imm);
584
585 void imull(CpuRegister reg);
586 void imull(const Address& address);
587
588 void mull(CpuRegister reg);
589 void mull(const Address& address);
590
591 void shll(CpuRegister reg, const Immediate& imm);
592 void shll(CpuRegister operand, CpuRegister shifter);
593 void shrl(CpuRegister reg, const Immediate& imm);
594 void shrl(CpuRegister operand, CpuRegister shifter);
595 void sarl(CpuRegister reg, const Immediate& imm);
596 void sarl(CpuRegister operand, CpuRegister shifter);
597
598 void shlq(CpuRegister reg, const Immediate& imm);
599 void shlq(CpuRegister operand, CpuRegister shifter);
600 void shrq(CpuRegister reg, const Immediate& imm);
601 void shrq(CpuRegister operand, CpuRegister shifter);
602 void sarq(CpuRegister reg, const Immediate& imm);
603 void sarq(CpuRegister operand, CpuRegister shifter);
604
605 void negl(CpuRegister reg);
606 void negq(CpuRegister reg);
607
608 void notl(CpuRegister reg);
609 void notq(CpuRegister reg);
610
611 void enter(const Immediate& imm);
612 void leave();
613
614 void ret();
615 void ret(const Immediate& imm);
616
617 void nop();
618 void int3();
619 void hlt();
620
621 void j(Condition condition, Label* label);
622 void j(Condition condition, NearLabel* label);
623 void jrcxz(NearLabel* label);
624
625 void jmp(CpuRegister reg);
626 void jmp(const Address& address);
627 void jmp(Label* label);
628 void jmp(NearLabel* label);
629
630 X86_64Assembler* lock();
631 void cmpxchgl(const Address& address, CpuRegister reg);
632 void cmpxchgq(const Address& address, CpuRegister reg);
633
634 void mfence();
635
636 X86_64Assembler* gs();
637
638 void setcc(Condition condition, CpuRegister dst);
639
640 void bswapl(CpuRegister dst);
641 void bswapq(CpuRegister dst);
642
643 void bsfl(CpuRegister dst, CpuRegister src);
644 void bsfl(CpuRegister dst, const Address& src);
645 void bsfq(CpuRegister dst, CpuRegister src);
646 void bsfq(CpuRegister dst, const Address& src);
647
648 void bsrl(CpuRegister dst, CpuRegister src);
649 void bsrl(CpuRegister dst, const Address& src);
650 void bsrq(CpuRegister dst, CpuRegister src);
651 void bsrq(CpuRegister dst, const Address& src);
652
653 void popcntl(CpuRegister dst, CpuRegister src);
654 void popcntl(CpuRegister dst, const Address& src);
655 void popcntq(CpuRegister dst, CpuRegister src);
656 void popcntq(CpuRegister dst, const Address& src);
657
658 void rorl(CpuRegister reg, const Immediate& imm);
659 void rorl(CpuRegister operand, CpuRegister shifter);
660 void roll(CpuRegister reg, const Immediate& imm);
661 void roll(CpuRegister operand, CpuRegister shifter);
662
663 void rorq(CpuRegister reg, const Immediate& imm);
664 void rorq(CpuRegister operand, CpuRegister shifter);
665 void rolq(CpuRegister reg, const Immediate& imm);
666 void rolq(CpuRegister operand, CpuRegister shifter);
667
668 void repne_scasw();
669 void repe_cmpsw();
670 void repe_cmpsl();
671 void repe_cmpsq();
672 void rep_movsw();
673
674 //
675 // Macros for High-level operations.
676 //
677
678 void AddImmediate(CpuRegister reg, const Immediate& imm);
679
680 void LoadDoubleConstant(XmmRegister dst, double value);
681
LockCmpxchgl(const Address & address,CpuRegister reg)682 void LockCmpxchgl(const Address& address, CpuRegister reg) {
683 lock()->cmpxchgl(address, reg);
684 }
685
LockCmpxchgq(const Address & address,CpuRegister reg)686 void LockCmpxchgq(const Address& address, CpuRegister reg) {
687 lock()->cmpxchgq(address, reg);
688 }
689
690 //
691 // Misc. functionality
692 //
PreferredLoopAlignment()693 int PreferredLoopAlignment() { return 16; }
694 void Align(int alignment, int offset);
695 void Bind(Label* label) OVERRIDE;
Jump(Label * label)696 void Jump(Label* label) OVERRIDE {
697 jmp(label);
698 }
699 void Bind(NearLabel* label);
700
701 //
702 // Overridden common assembler high-level functionality
703 //
704
705 // Emit code that will create an activation on the stack
706 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
707 const std::vector<ManagedRegister>& callee_save_regs,
708 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
709
710 // Emit code that will remove an activation from the stack
711 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
712 OVERRIDE;
713
714 void IncreaseFrameSize(size_t adjust) OVERRIDE;
715 void DecreaseFrameSize(size_t adjust) OVERRIDE;
716
717 // Store routines
718 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
719 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
720 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
721
722 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
723
724 void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch)
725 OVERRIDE;
726
727 void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
728 ManagedRegister scratch) OVERRIDE;
729
730 void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE;
731
732 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
733 ManagedRegister scratch) OVERRIDE;
734
735 // Load routines
736 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
737
738 void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE;
739
740 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
741
742 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
743 bool unpoison_reference) OVERRIDE;
744
745 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
746
747 void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE;
748
749 // Copying routines
750 void Move(ManagedRegister dest, ManagedRegister src, size_t size);
751
752 void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
753 ManagedRegister scratch) OVERRIDE;
754
755 void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
756 OVERRIDE;
757
758 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
759
760 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
761
762 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
763 size_t size) OVERRIDE;
764
765 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
766 size_t size) OVERRIDE;
767
768 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
769 size_t size) OVERRIDE;
770
771 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
772 ManagedRegister scratch, size_t size) OVERRIDE;
773
774 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
775 ManagedRegister scratch, size_t size) OVERRIDE;
776
777 void MemoryBarrier(ManagedRegister) OVERRIDE;
778
779 // Sign extension
780 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
781
782 // Zero extension
783 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
784
785 // Exploit fast access in managed code to Thread::Current()
786 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
787 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
788
789 // Set up out_reg to hold a Object** into the handle scope, or to be null if the
790 // value is null and null_allowed. in_reg holds a possibly stale reference
791 // that can be used to avoid loading the handle scope entry to see if the value is
792 // null.
793 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
794 ManagedRegister in_reg, bool null_allowed) OVERRIDE;
795
796 // Set up out_off to hold a Object** into the handle scope, or to be null if the
797 // value is null and null_allowed.
798 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
799 ManagedRegister scratch, bool null_allowed) OVERRIDE;
800
801 // src holds a handle scope entry (Object**) load this into dst
802 virtual void LoadReferenceFromHandleScope(ManagedRegister dst,
803 ManagedRegister src);
804
805 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
806 // know that src may not be null.
807 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
808 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
809
810 // Call to address held at [base+offset]
811 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
812 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
813 void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE;
814
815 // Generate code to check if Thread::Current()->exception_ is non-null
816 // and branch to a ExceptionSlowPath if it is.
817 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
818
819 // Add a double to the constant area, returning the offset into
820 // the constant area where the literal resides.
AddDouble(double v)821 size_t AddDouble(double v) { return constant_area_.AddDouble(v); }
822
823 // Add a float to the constant area, returning the offset into
824 // the constant area where the literal resides.
AddFloat(float v)825 size_t AddFloat(float v) { return constant_area_.AddFloat(v); }
826
827 // Add an int32_t to the constant area, returning the offset into
828 // the constant area where the literal resides.
AddInt32(int32_t v)829 size_t AddInt32(int32_t v) {
830 return constant_area_.AddInt32(v);
831 }
832
833 // Add an int32_t to the end of the constant area, returning the offset into
834 // the constant area where the literal resides.
AppendInt32(int32_t v)835 size_t AppendInt32(int32_t v) {
836 return constant_area_.AppendInt32(v);
837 }
838
839 // Add an int64_t to the constant area, returning the offset into
840 // the constant area where the literal resides.
AddInt64(int64_t v)841 size_t AddInt64(int64_t v) { return constant_area_.AddInt64(v); }
842
843 // Add the contents of the constant area to the assembler buffer.
844 void AddConstantArea();
845
846 // Is the constant area empty? Return true if there are no literals in the constant area.
IsConstantAreaEmpty()847 bool IsConstantAreaEmpty() const { return constant_area_.GetSize() == 0; }
848
849 // Return the current size of the constant area.
ConstantAreaSize()850 size_t ConstantAreaSize() const { return constant_area_.GetSize(); }
851
852 //
853 // Heap poisoning.
854 //
855
856 // Poison a heap reference contained in `reg`.
PoisonHeapReference(CpuRegister reg)857 void PoisonHeapReference(CpuRegister reg) { negl(reg); }
858 // Unpoison a heap reference contained in `reg`.
UnpoisonHeapReference(CpuRegister reg)859 void UnpoisonHeapReference(CpuRegister reg) { negl(reg); }
860 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
MaybeUnpoisonHeapReference(CpuRegister reg)861 void MaybeUnpoisonHeapReference(CpuRegister reg) {
862 if (kPoisonHeapReferences) {
863 UnpoisonHeapReference(reg);
864 }
865 }
866
867 private:
868 void EmitUint8(uint8_t value);
869 void EmitInt32(int32_t value);
870 void EmitInt64(int64_t value);
871 void EmitRegisterOperand(uint8_t rm, uint8_t reg);
872 void EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg);
873 void EmitFixup(AssemblerFixup* fixup);
874 void EmitOperandSizeOverride();
875
876 void EmitOperand(uint8_t rm, const Operand& operand);
877 void EmitImmediate(const Immediate& imm);
878 void EmitComplex(uint8_t rm, const Operand& operand, const Immediate& immediate);
879 void EmitLabel(Label* label, int instruction_size);
880 void EmitLabelLink(Label* label);
881 void EmitLabelLink(NearLabel* label);
882
883 void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm);
884 void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter);
885
886 // If any input is not false, output the necessary rex prefix.
887 void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b);
888
889 // Emit a rex prefix byte if necessary for reg. ie if reg is a register in the range R8 to R15.
890 void EmitOptionalRex32(CpuRegister reg);
891 void EmitOptionalRex32(CpuRegister dst, CpuRegister src);
892 void EmitOptionalRex32(XmmRegister dst, XmmRegister src);
893 void EmitOptionalRex32(CpuRegister dst, XmmRegister src);
894 void EmitOptionalRex32(XmmRegister dst, CpuRegister src);
895 void EmitOptionalRex32(const Operand& operand);
896 void EmitOptionalRex32(CpuRegister dst, const Operand& operand);
897 void EmitOptionalRex32(XmmRegister dst, const Operand& operand);
898
899 // Emit a REX.W prefix plus necessary register bit encodings.
900 void EmitRex64();
901 void EmitRex64(CpuRegister reg);
902 void EmitRex64(const Operand& operand);
903 void EmitRex64(CpuRegister dst, CpuRegister src);
904 void EmitRex64(CpuRegister dst, const Operand& operand);
905 void EmitRex64(XmmRegister dst, const Operand& operand);
906 void EmitRex64(XmmRegister dst, CpuRegister src);
907 void EmitRex64(CpuRegister dst, XmmRegister src);
908
909 // Emit a REX prefix to normalize byte registers plus necessary register bit encodings.
910 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src);
911 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand);
912
913 ConstantArea constant_area_;
914
915 DISALLOW_COPY_AND_ASSIGN(X86_64Assembler);
916 };
917
EmitUint8(uint8_t value)918 inline void X86_64Assembler::EmitUint8(uint8_t value) {
919 buffer_.Emit<uint8_t>(value);
920 }
921
EmitInt32(int32_t value)922 inline void X86_64Assembler::EmitInt32(int32_t value) {
923 buffer_.Emit<int32_t>(value);
924 }
925
EmitInt64(int64_t value)926 inline void X86_64Assembler::EmitInt64(int64_t value) {
927 // Write this 64-bit value as two 32-bit words for alignment reasons
928 // (this is essentially when running on ARM, which does not allow
929 // 64-bit unaligned accesses). We assume little-endianness here.
930 EmitInt32(Low32Bits(value));
931 EmitInt32(High32Bits(value));
932 }
933
EmitRegisterOperand(uint8_t rm,uint8_t reg)934 inline void X86_64Assembler::EmitRegisterOperand(uint8_t rm, uint8_t reg) {
935 CHECK_GE(rm, 0);
936 CHECK_LT(rm, 8);
937 buffer_.Emit<uint8_t>((0xC0 | (reg & 7)) + (rm << 3));
938 }
939
EmitXmmRegisterOperand(uint8_t rm,XmmRegister reg)940 inline void X86_64Assembler::EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg) {
941 EmitRegisterOperand(rm, static_cast<uint8_t>(reg.AsFloatRegister()));
942 }
943
EmitFixup(AssemblerFixup * fixup)944 inline void X86_64Assembler::EmitFixup(AssemblerFixup* fixup) {
945 buffer_.EmitFixup(fixup);
946 }
947
EmitOperandSizeOverride()948 inline void X86_64Assembler::EmitOperandSizeOverride() {
949 EmitUint8(0x66);
950 }
951
952 } // namespace x86_64
953 } // namespace art
954
955 #endif // ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
956