13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_X64_ASSEMBLER_X64_INL_H_
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_X64_ASSEMBLER_X64_INL_H_
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/x64/assembler-x64.h"
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/cpu.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8memory.h"
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CpuFeatures::SupportsCrankshaft() { return true; }
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool CpuFeatures::SupportsSimd128() { return false; }
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Assembler
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kCallOpcode = 0xE8;
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The length of pushq(rbp), movp(rbp, rsp), Push(rsi) and Push(rdi).
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kNoCodeAgeSequenceLength = kPointerSize == kInt64Size ? 6 : 17;
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emitl(uint32_t x) {
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Memory::uint32_at(pc_) = x;
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += sizeof(uint32_t);
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::emitp(void* x, RelocInfo::Mode rmode) {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uintptr_t value = reinterpret_cast<uintptr_t>(x);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Memory::uintptr_at(pc_) = value;
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!RelocInfo::IsNone(rmode)) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordRelocInfo(rmode, value);
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pc_ += sizeof(uintptr_t);
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::emitq(uint64_t x) {
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Memory::uint64_at(pc_) = x;
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += sizeof(uint64_t);
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emitw(uint16_t x) {
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Memory::uint16_at(pc_) = x;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pc_ += sizeof(uint16_t);
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid Assembler::emit_code_target(Handle<Code> target,
59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 RelocInfo::Mode rmode,
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 TypeFeedbackId ast_id) {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsCodeTarget(rmode) ||
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rmode == RelocInfo::CODE_AGE_SEQUENCE);
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, ast_id.ToInt());
65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    RecordRelocInfo(rmode);
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int current = code_targets_.length();
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (current > 0 && code_targets_.last().address() == target.address()) {
703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Optimization if we keep jumping to the same code target.
713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    emitl(current - 1);
723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    code_targets_.Add(target);
743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    emitl(current);
753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(RelocInfo::IsRuntimeEntry(rmode));
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordRelocInfo(rmode);
82bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  emitl(static_cast<uint32_t>(
83bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      entry - isolate()->heap()->memory_allocator()->code_range()->start()));
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_64(Register reg, Register rm_reg) {
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_64(Register reg, const Operand& op) {
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x48 | reg.high_bit() << 2 | op.rex_);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_64(XMMRegister reg, const Operand& op) {
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_);
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_64(Register rm_reg) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(rm_reg.code() & 0xf, rm_reg.code());
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x48 | rm_reg.high_bit());
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_64(const Operand& op) {
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x48 | op.rex_);
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_32(Register reg, Register rm_reg) {
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_32(Register reg, const Operand& op) {
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x40 | reg.high_bit() << 2  | op.rex_);
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_32(Register rm_reg) {
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x40 | rm_reg.high_bit());
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_rex_32(const Operand& op) {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  emit(0x40 | op.rex_);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rex_bits != 0) emit(0x40 | rex_bits);
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(Register reg, const Operand& op) {
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_bits =  reg.high_bit() << 2 | op.rex_;
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rex_bits != 0) emit(0x40 | rex_bits);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(XMMRegister reg, const Operand& op) {
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_bits =  (reg.code() & 0x8) >> 1 | op.rex_;
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rex_bits != 0) emit(0x40 | rex_bits);
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rex_bits != 0) emit(0x40 | rex_bits);
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rex_bits != 0) emit(0x40 | rex_bits);
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (rex_bits != 0) emit(0x40 | rex_bits);
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(Register rm_reg) {
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (rm_reg.high_bit()) emit(0x41);
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rm_reg.high_bit()) emit(0x41);
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Assembler::emit_optional_rex_32(const Operand& op) {
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op.rex_ != 0) emit(0x40 | op.rex_);
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// byte 1 of 3-byte VEX
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                LeadingOpcode m) {
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte rxb = ~((reg.high_bit() << 2) | rm.high_bit()) << 5;
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(rxb | m);
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// byte 1 of 3-byte VEX
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_vex3_byte1(XMMRegister reg, const Operand& rm,
202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                LeadingOpcode m) {
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte rxb = ~((reg.high_bit() << 2) | rm.rex_) << 5;
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(rxb | m);
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// byte 1 of 2-byte VEX
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                SIMDPrefix pp) {
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte rv = ~((reg.high_bit() << 4) | v.code()) << 3;
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(rv | l | pp);
213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// byte 2 of 3-byte VEX
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                SIMDPrefix pp) {
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  emit(w | ((~v.code() & 0xf) << 3) | l | pp);
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                XMMRegister rm, VectorLength l, SIMDPrefix pp,
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                LeadingOpcode mm, VexW w) {
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rm.high_bit() || mm != k0F || w != kW0) {
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex3_byte0();
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex3_byte1(reg, rm, mm);
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex3_byte2(w, vreg, l, pp);
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex2_byte0();
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex2_byte1(reg, vreg, l, pp);
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::emit_vex_prefix(Register reg, Register vreg, Register rm,
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                VexW w) {
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  XMMRegister ireg = {reg.code()};
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  XMMRegister ivreg = {vreg.code()};
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  XMMRegister irm = {rm.code()};
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                const Operand& rm, VectorLength l,
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                SIMDPrefix pp, LeadingOpcode mm, VexW w) {
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (rm.rex_ || mm != k0F || w != kW0) {
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex3_byte0();
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex3_byte1(reg, rm, mm);
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex3_byte2(w, vreg, l, pp);
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex2_byte0();
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    emit_vex2_byte1(reg, vreg, l, pp);
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::emit_vex_prefix(Register reg, Register vreg, const Operand& rm,
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                VexW w) {
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  XMMRegister ireg = {reg.code()};
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  XMMRegister ivreg = {vreg.code()};
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochAddress Assembler::target_address_at(Address pc, Address constant_pool) {
2713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return Memory::int32_at(pc) + pc + 4;
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::set_target_address_at(Isolate* isolate, Address pc,
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      Address constant_pool, Address target,
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      ICacheFlushMode icache_flush_mode) {
278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Memory::int32_at(pc) = static_cast<int32_t>(target - pc - 4);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(isolate, pc, sizeof(int32_t));
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::deserialization_set_target_internal_reference_at(
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Memory::Address_at(pc) = target;
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochAddress Assembler::target_address_from_return_address(Address pc) {
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return pc - kCallTargetAddressOffset;
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockHandle<Object> Assembler::code_target_object_handle_at(Address pc) {
2973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return code_targets_[Memory::int32_at(pc)];
2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAddress Assembler::runtime_entry_at(Address pc) {
302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return Memory::int32_at(pc) +
303bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch         isolate()->heap()->memory_allocator()->code_range()->start();
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of RelocInfo
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The modes possibly affected by apply must be in kApplyMask.
310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid RelocInfo::apply(intptr_t delta) {
311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Memory::int32_at(pc_) -= static_cast<int32_t>(delta);
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (IsCodeAgeSequence(rmode_)) {
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (*pc_ == kCallOpcode) {
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *p -= static_cast<int32_t>(delta);  // Relocate entry.
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (IsInternalReference(rmode_)) {
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // absolute code pointer inside code object moves with the code object.
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Memory::Address_at(pc_) += delta;
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress RelocInfo::target_address() {
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Assembler::target_address_at(pc_, host_);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress RelocInfo::target_address_address() {
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              || rmode_ == EMBEDDED_OBJECT
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              || rmode_ == EXTERNAL_REFERENCE);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return reinterpret_cast<Address>(pc_);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAddress RelocInfo::constant_pool_entry_address() {
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NULL;
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeint RelocInfo::target_address_size() {
345f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (IsCodedSpecially()) {
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Assembler::kSpecialTargetSize;
347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return kPointerSize;
349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
352f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject* RelocInfo::target_object() {
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
3553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return Memory::Object_at(pc_);
3563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Object> RelocInfo::target_object_handle(Assembler* origin) {
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
3613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (rmode_ == EMBEDDED_OBJECT) {
3623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return Memory::Object_Handle_at(pc_);
3633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else {
3643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return origin->code_target_object_handle_at(pc_);
3653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochAddress RelocInfo::target_external_reference() {
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Memory::Address_at(pc_);
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochAddress RelocInfo::target_internal_reference() {
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rmode_ == INTERNAL_REFERENCE);
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Memory::Address_at(pc_);
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochAddress RelocInfo::target_internal_reference_address() {
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(rmode_ == INTERNAL_REFERENCE);
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return reinterpret_cast<Address>(pc_);
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RelocInfo::set_target_object(Object* target,
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  WriteBarrierMode write_barrier_mode,
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  ICacheFlushMode icache_flush_mode) {
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Memory::Object_at(pc_) = target;
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(isolate_, pc_, sizeof(Address));
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      host() != NULL &&
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      target->IsHeapObject()) {
3983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
3993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        host(), this, HeapObject::cast(target));
400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAddress RelocInfo::target_runtime_entry(Assembler* origin) {
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsRuntimeEntry(rmode_));
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return origin->runtime_entry_at(pc_);
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RelocInfo::set_target_runtime_entry(Address target,
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         WriteBarrierMode write_barrier_mode,
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         ICacheFlushMode icache_flush_mode) {
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsRuntimeEntry(rmode_));
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (target_address() != target) {
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_target_address(target, write_barrier_mode, icache_flush_mode);
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Cell> RelocInfo::target_cell_handle() {
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::CELL);
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Address address = Memory::Address_at(pc_);
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Handle<Cell>(reinterpret_cast<Cell**>(address));
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCell* RelocInfo::target_cell() {
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::CELL);
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Cell::FromValueAddress(Memory::Address_at(pc_));
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RelocInfo::set_target_cell(Cell* cell,
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                WriteBarrierMode write_barrier_mode,
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                ICacheFlushMode icache_flush_mode) {
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::CELL);
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address address = cell->address() + Cell::kValueOffset;
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Memory::Address_at(pc_) = address;
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(isolate_, pc_, sizeof(Address));
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      host() != NULL) {
445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
446109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                                                  cell);
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RelocInfo::WipeOut() {
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      IsInternalReference(rmode_)) {
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Memory::Address_at(pc_) = NULL;
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Effectively write zero into the relocation.
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::set_target_address_at(isolate_, pc_, host_,
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     pc_ + sizeof(int32_t));
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(*pc_ == kCallOpcode);
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return origin->code_target_object_handle_at(pc_ + 1);
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCode* RelocInfo::code_age_stub() {
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(*pc_ == kCallOpcode);
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Code::GetCodeFromTargetAddress(
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Assembler::target_address_at(pc_ + 1, host_));
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RelocInfo::set_code_age_stub(Code* stub,
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  ICacheFlushMode icache_flush_mode) {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(*pc_ == kCallOpcode);
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::set_target_address_at(
485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      isolate_, pc_ + 1, host_, stub->instruction_start(), icache_flush_mode);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochAddress RelocInfo::debug_call_address() {
490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid RelocInfo::set_debug_call_address(Address target) {
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset) =
4983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      target;
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(isolate_,
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         pc_ + Assembler::kPatchDebugBreakSlotAddressOffset,
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         sizeof(Address));
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (host() != NULL) {
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* target_code = Code::GetCodeFromTargetAddress(target);
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        host(), this, HeapObject::cast(target_code));
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochtemplate <typename ObjectVisitor>
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
511f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  RelocInfo::Mode mode = rmode();
512f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (mode == RelocInfo::EMBEDDED_OBJECT) {
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    visitor->VisitEmbeddedPointer(this);
514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(isolate, pc_, sizeof(Address));
515f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (RelocInfo::IsCodeTarget(mode)) {
516f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    visitor->VisitCodeTarget(this);
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (mode == RelocInfo::CELL) {
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    visitor->VisitCell(this);
519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    visitor->VisitExternalReference(this);
521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    visitor->VisitInternalReference(this);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (RelocInfo::IsCodeAgeSequence(mode)) {
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    visitor->VisitCodeAgeSequence(this);
525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (RelocInfo::IsDebugBreakSlot(mode) &&
526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             IsPatchedDebugBreakSlotSequence()) {
527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    visitor->VisitDebugTarget(this);
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (RelocInfo::IsRuntimeEntry(mode)) {
529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    visitor->VisitRuntimeEntry(this);
530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
534756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merricktemplate<typename StaticVisitor>
53544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RelocInfo::Visit(Heap* heap) {
536756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  RelocInfo::Mode mode = rmode();
537756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (mode == RelocInfo::EMBEDDED_OBJECT) {
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StaticVisitor::VisitEmbeddedPointer(heap, this);
539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Assembler::FlushICache(heap->isolate(), pc_, sizeof(Address));
540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (RelocInfo::IsCodeTarget(mode)) {
5418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticVisitor::VisitCodeTarget(heap, this);
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (mode == RelocInfo::CELL) {
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StaticVisitor::VisitCell(heap, this);
544756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StaticVisitor::VisitExternalReference(this);
546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    StaticVisitor::VisitInternalReference(this);
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (RelocInfo::IsCodeAgeSequence(mode)) {
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StaticVisitor::VisitCodeAgeSequence(heap, this);
550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (RelocInfo::IsDebugBreakSlot(mode) &&
551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             IsPatchedDebugBreakSlotSequence()) {
5528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    StaticVisitor::VisitDebugTarget(heap, this);
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (RelocInfo::IsRuntimeEntry(mode)) {
554756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    StaticVisitor::VisitRuntimeEntry(this);
555756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
557756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
558756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Operand
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Operand::set_modrm(int mod, Register rm_reg) {
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint2(mod));
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buf_[0] = mod << 6 | rm_reg.low_bits();
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set REX.B to the high bit of rm.code().
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rex_ |= rm_reg.high_bit();
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Operand::set_sib(ScaleFactor scale, Register index, Register base) {
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(len_ == 1);
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_uint2(scale));
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use SIB with no index register only for base rsp or r12. Otherwise we
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // would skip the SIB byte entirely.
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!index.is(rsp) || base.is(rsp) || base.is(r12));
5761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  buf_[1] = (scale << 6) | (index.low_bits() << 3) | base.low_bits();
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rex_ |= index.high_bit() << 1 | base.high_bit();
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len_ = 2;
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Operand::set_disp8(int disp) {
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_int8(disp));
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(len_ == 1 || len_ == 2);
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int8_t* p = reinterpret_cast<int8_t*>(&buf_[len_]);
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *p = disp;
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len_ += sizeof(int8_t);
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Operand::set_disp32(int disp) {
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(len_ == 1 || len_ == 2);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *p = disp;
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len_ += sizeof(int32_t);
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Operand::set_disp64(int64_t disp) {
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(1, len_);
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int64_t* p = reinterpret_cast<int64_t*>(&buf_[len_]);
599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  *p = disp;
600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  len_ += sizeof(disp);
601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_X64_ASSEMBLER_X64_INL_H_
606