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