4449N/A// Copyright (c) 2003, 2013, Oracle
and/or its affiliates. All rights reserved.
0N/A// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A// This code is free software; you can redistribute it
and/or modify it
0N/A// under the terms of the GNU General Public License version 2 only, as
0N/A// published by the Free Software Foundation.
0N/A// This code is distributed in the hope that it will be useful, but WITHOUT
0N/A// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A// version 2 for more details (a copy is included in the LICENSE file that
0N/A// accompanied this code).
0N/A// You should have received a copy of the GNU General Public License version
0N/A// 2 along with this work; if not, write to the Free Software Foundation,
0N/A// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1472N/A// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
0N/A// AMD64 Architecture Description File
0N/A//----------REGISTER DEFINITION BLOCK------------------------------------------
0N/A// This information is used by the matcher and the register allocator to
0N/A// describe individual registers and classes of registers within the target
0N/A//----------Architecture Description Register Definitions----------------------
0N/A// "reg_def" name ( register save type, C convention save type,
0N/A// ideal register type, encoding );
0N/A// Register Save Types:
0N/A// NS = No-Save: The register allocator assumes that these registers
0N/A// can be used without saving upon entry to the method, &
0N/A// that they do not need to be saved at call sites.
0N/A// SOC = Save-On-Call: The register allocator assumes that these registers
0N/A// can be used without saving upon entry to the method,
0N/A// but that they must be saved at call sites.
0N/A// SOE = Save-On-Entry: The register allocator assumes that these registers
0N/A// must be saved before using them upon entry to the
0N/A// method, but they do not need to be saved at call
0N/A// AS = Always-Save: The register allocator assumes that these registers
0N/A// must be saved before using them upon entry to the
0N/A// method, & that they must be saved at call sites.
0N/A// Ideal Register Type is used to determine how to save & restore a
0N/A// The encoding number is the actual bit-pattern placed into the opcodes.
0N/A// R8-R15 must be encoded with REX. (RSP, RBP, RSI, RDI need REX when
0N/A// used as byte registers)
0N/A// Previously set RBX, RSI, and RDI as save-on-entry for java code
0N/A// Turn off SOE in java-code due to frequent use of uncommon-traps.
0N/A// Now that allocator is better, turn on RSI and RDI as SOE registers.
0N/Areg_def RAX (SOC, SOC, Op_RegI, 0, rax->as_VMReg());
0N/Areg_def RAX_H(SOC, SOC, Op_RegI, 0, rax->as_VMReg()->next());
0N/Areg_def RCX (SOC, SOC, Op_RegI, 1, rcx->as_VMReg());
0N/Areg_def RCX_H(SOC, SOC, Op_RegI, 1, rcx->as_VMReg()->next());
0N/Areg_def RDX (SOC, SOC, Op_RegI, 2, rdx->as_VMReg());
0N/Areg_def RDX_H(SOC, SOC, Op_RegI, 2, rdx->as_VMReg()->next());
0N/Areg_def RBX (SOC, SOE, Op_RegI, 3, rbx->as_VMReg());
0N/Areg_def RBX_H(SOC, SOE, Op_RegI, 3, rbx->as_VMReg()->next());
0N/Areg_def RSP (NS, NS, Op_RegI, 4, rsp->as_VMReg());
0N/Areg_def RSP_H(NS, NS, Op_RegI, 4, rsp->as_VMReg()->next());
0N/A// now that adapter frames are gone RBP is always saved and restored by the
prolog/epilog code
0N/Areg_def RBP (NS, SOE, Op_RegI, 5, rbp->as_VMReg());
0N/Areg_def RBP_H(NS, SOE, Op_RegI, 5, rbp->as_VMReg()->next());
0N/Areg_def RSI (SOC, SOE, Op_RegI, 6, rsi->as_VMReg());
0N/Areg_def RSI_H(SOC, SOE, Op_RegI, 6, rsi->as_VMReg()->next());
0N/Areg_def RDI (SOC, SOE, Op_RegI, 7, rdi->as_VMReg());
0N/Areg_def RDI_H(SOC, SOE, Op_RegI, 7, rdi->as_VMReg()->next());
0N/Areg_def RSI (SOC, SOC, Op_RegI, 6, rsi->as_VMReg());
0N/Areg_def RSI_H(SOC, SOC, Op_RegI, 6, rsi->as_VMReg()->next());
0N/Areg_def RDI (SOC, SOC, Op_RegI, 7, rdi->as_VMReg());
0N/Areg_def RDI_H(SOC, SOC, Op_RegI, 7, rdi->as_VMReg()->next());
0N/Areg_def R8 (SOC, SOC, Op_RegI, 8, r8->as_VMReg());
0N/Areg_def R8_H (SOC, SOC, Op_RegI, 8, r8->as_VMReg()->next());
0N/Areg_def R9 (SOC, SOC, Op_RegI, 9, r9->as_VMReg());
0N/Areg_def R9_H (SOC, SOC, Op_RegI, 9, r9->as_VMReg()->next());
0N/Areg_def R10 (SOC, SOC, Op_RegI, 10, r10->as_VMReg());
0N/Areg_def R10_H(SOC, SOC, Op_RegI, 10, r10->as_VMReg()->next());
0N/Areg_def R11 (SOC, SOC, Op_RegI, 11, r11->as_VMReg());
0N/Areg_def R11_H(SOC, SOC, Op_RegI, 11, r11->as_VMReg()->next());
0N/Areg_def R12 (SOC, SOE, Op_RegI, 12, r12->as_VMReg());
0N/Areg_def R12_H(SOC, SOE, Op_RegI, 12, r12->as_VMReg()->next());
0N/Areg_def R13 (SOC, SOE, Op_RegI, 13, r13->as_VMReg());
0N/Areg_def R13_H(SOC, SOE, Op_RegI, 13, r13->as_VMReg()->next());
0N/Areg_def R14 (SOC, SOE, Op_RegI, 14, r14->as_VMReg());
0N/Areg_def R14_H(SOC, SOE, Op_RegI, 14, r14->as_VMReg()->next());
0N/Areg_def R15 (SOC, SOE, Op_RegI, 15, r15->as_VMReg());
0N/Areg_def R15_H(SOC, SOE, Op_RegI, 15, r15->as_VMReg()->next());
0N/A// Floating Point Registers
0N/A// Specify priority of register selection within phases of register
0N/A// allocation. Highest priority is first. A useful heuristic is to
0N/A// give registers a low priority when they are required by machine
0N/A// instructions, like EAX and EDX on I486, and choose no-save registers
0N/A// before save-on-call, & save-on-call before save-on-entry. Registers
0N/A// which participate in fixed calling sequences should come last.
0N/A// Registers which are used as pairs must fall on an even boundary.
0N/Aalloc_class chunk0(R10, R10_H,
0N/A//----------Architecture Description Register Classes--------------------------
0N/A// Several register classes are automatically defined based upon information in
0N/A// this architecture description.
0N/A// 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
0N/A// 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ )
0N/A// 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ )
0N/A// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
0N/A// Class for all pointer registers (including RSP)
0N/Areg_class any_reg(RAX, RAX_H,
0N/A// Class for all pointer registers except RSP
0N/Areg_class ptr_reg(RAX, RAX_H,
0N/A// Class for all pointer registers except RAX and RSP
0N/Areg_class ptr_no_rax_reg(RDX, RDX_H,
0N/Areg_class ptr_no_rbp_reg(RDX, RDX_H,
0N/A// Class for all pointer registers except RAX, RBX and RSP
0N/Areg_class ptr_no_rax_rbx_reg(RDX, RDX_H,
0N/A// Singleton class for RAX pointer register
0N/Areg_class ptr_rax_reg(RAX, RAX_H);
0N/A// Singleton class for RBX pointer register
0N/Areg_class ptr_rbx_reg(RBX, RBX_H);
0N/A// Singleton class for RSI pointer register
0N/Areg_class ptr_rsi_reg(RSI, RSI_H);
0N/A// Singleton class for RDI pointer register
0N/Areg_class ptr_rdi_reg(RDI, RDI_H);
0N/A// Singleton class for RBP pointer register
0N/Areg_class ptr_rbp_reg(RBP, RBP_H);
0N/A// Singleton class for stack pointer
0N/Areg_class ptr_rsp_reg(RSP, RSP_H);
0N/A// Singleton class for TLS pointer
0N/Areg_class ptr_r15_reg(R15, R15_H);
0N/A// Class for all long registers (except RSP)
0N/Areg_class long_reg(RAX, RAX_H,
0N/A// Class for all long registers except RAX, RDX (and RSP)
0N/Areg_class long_no_rax_rdx_reg(RBP, RBP_H,
0N/A// Class for all long registers except RCX (and RSP)
0N/Areg_class long_no_rcx_reg(RBP, RBP_H,
0N/A// Class for all long registers except RAX (and RSP)
0N/Areg_class long_no_rax_reg(RBP, RBP_H,
0N/A// Singleton class for RAX long register
0N/Areg_class long_rax_reg(RAX, RAX_H);
0N/A// Singleton class for RCX long register
0N/Areg_class long_rcx_reg(RCX, RCX_H);
0N/A// Singleton class for RDX long register
0N/Areg_class long_rdx_reg(RDX, RDX_H);
0N/A// Class for all int registers (except RSP)
0N/Areg_class int_reg(RAX,
0N/A// Class for all int registers except RCX (and RSP)
0N/Areg_class int_no_rcx_reg(RAX,
0N/A// Class for all int registers except RAX, RDX (and RSP)
0N/Areg_class int_no_rax_rdx_reg(RBP,
0N/A// Singleton class for RAX int register
0N/Areg_class int_rax_reg(RAX);
0N/A// Singleton class for RBX int register
0N/Areg_class int_rbx_reg(RBX);
0N/A// Singleton class for RCX int register
0N/Areg_class int_rcx_reg(RCX);
0N/A// Singleton class for RCX int register
0N/Areg_class int_rdx_reg(RDX);
0N/A// Singleton class for RCX int register
0N/Areg_class int_rdi_reg(RDI);
0N/A// Singleton class for instruction pointer
0N/A// reg_class ip_reg(RIP);
0N/A//----------SOURCE BLOCK-------------------------------------------------------
0N/A// This is a block of C++ code which provides values, functions, and
0N/A// definitions necessary in the rest of the architecture description
304N/A#define RELOC_IMM64 Assembler::imm_operand
0N/A#define RELOC_DISP32 Assembler::disp32_operand
1137N/Astatic int preserve_SP_size() {
4442N/Astatic int clear_avx_size() {
4442N/A return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper
0N/A// !!!!! Special hack to get all types of calls to specify the byte offset
0N/A// from the start of the call to the point where the return address
0N/Aint MachCallStaticJavaNode::ret_addr_offset()
1137N/A int offset = 5; // 5 bytes from start of call to where return address points
4442N/A offset += clear_avx_size();
1137N/A offset += preserve_SP_size();
0N/Aint MachCallDynamicJavaNode::ret_addr_offset()
4442N/A int offset = 15; // 15 bytes from start of call to where return address points
4442N/A offset += clear_avx_size();
4442N/Aint MachCallRuntimeNode::ret_addr_offset() {
4442N/A int offset = 13; // movq r10,#addr; callq (r10)
4442N/A offset += clear_avx_size();
2251N/A// Indicate if the safepoint node needs the polling page as an input,
2251N/A// it does if the polling page is more than disp32 away.
0N/Abool SafePointNode::needs_polling_address_input()
2251N/A return Assembler::is_polling_page_far();
0N/A// Compute padding required for nodes which need alignment
0N/A// The address of the call instruction needs to be 4-byte aligned to
0N/A// ensure that it does not span a cache line so that it can be patched.
0N/Aint CallStaticJavaDirectNode::compute_padding(int current_offset) const
4442N/A current_offset += clear_avx_size(); // skip vzeroupper
0N/A current_offset += 1; // skip call opcode byte
0N/A return round_to(current_offset, alignment_required()) - current_offset;
0N/A// The address of the call instruction needs to be 4-byte aligned to
0N/A// ensure that it does not span a cache line so that it can be patched.
1137N/Aint CallStaticJavaHandleNode::compute_padding(int current_offset) const
1137N/A current_offset += preserve_SP_size(); // skip mov rbp, rsp
4442N/A current_offset += clear_avx_size(); // skip vzeroupper
1137N/A current_offset += 1; // skip call opcode byte
1137N/A return round_to(current_offset, alignment_required()) - current_offset;
1137N/A// The address of the call instruction needs to be 4-byte aligned to
1137N/A// ensure that it does not span a cache line so that it can be patched.
0N/Aint CallDynamicJavaDirectNode::compute_padding(int current_offset) const
4442N/A current_offset += clear_avx_size(); // skip vzeroupper
0N/A current_offset += 11; // skip movq instruction + call opcode byte
0N/A return round_to(current_offset, alignment_required()) - current_offset;
1668N/Avoid emit_rm(CodeBuffer &cbuf, int f1, int f2, int f3) {
0N/A unsigned char c = (unsigned char) ((f1 << 6) | (f2 << 3) | f3);
1668N/Avoid emit_cc(CodeBuffer &cbuf, int f1, int f2) {
0N/A unsigned char c = (unsigned char) (f1 | f2);
1668N/Avoid emit_opcode(CodeBuffer &cbuf, int code) {
0N/A// EMIT_OPCODE() w/ relocation information
0N/Avoid emit_opcode(CodeBuffer &cbuf,
0N/A int code, relocInfo::relocType reloc, int offset, int format)
0N/A emit_opcode(cbuf, code);
1668N/Avoid emit_d8(CodeBuffer &cbuf, int d8) {
1668N/Avoid emit_d16(CodeBuffer &cbuf, int d16) {
1668N/Avoid emit_d32(CodeBuffer &cbuf, int d32) {
1668N/Avoid emit_d64(CodeBuffer &cbuf, int64_t d64) {
0N/A// emit 32 bit value and construct relocation entry from relocInfo::relocType
0N/Avoid emit_d32_reloc(CodeBuffer& cbuf,
0N/A relocInfo::relocType reloc,
0N/A assert(reloc != relocInfo::external_word_type, "use 2-arg emit_d32_reloc");
0N/A// emit 32 bit value and construct relocation entry from RelocationHolder
1668N/Avoid emit_d32_reloc(CodeBuffer& cbuf, int d32, RelocationHolder const& rspec, int format) {
0N/A d32 != 0 && d32 != (intptr_t) Universe::non_oop_word()) {
989N/A assert(oop((intptr_t)d32)->is_oop() && (ScavengeRootsInCode || !oop((intptr_t)d32)->is_scavengable()), "cannot embed scavengable oops in code");
0N/Avoid emit_d32_reloc(CodeBuffer& cbuf, address addr) {
0N/A emit_d32_reloc(cbuf, (int) (addr - next_ip),
0N/A external_word_Relocation::spec(addr),
0N/A// emit 64 bit value and construct relocation entry from relocInfo::relocType
1668N/Avoid emit_d64_reloc(CodeBuffer& cbuf, int64_t d64, relocInfo::relocType reloc, int format) {
0N/A// emit 64 bit value and construct relocation entry from RelocationHolder
1668N/Avoid emit_d64_reloc(CodeBuffer& cbuf, int64_t d64, RelocationHolder const& rspec, int format) {
0N/A d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) {
989N/A assert(oop(d64)->is_oop() && (ScavengeRootsInCode || !oop(d64)->is_scavengable()),
989N/A "cannot embed scavengable oops in code");
0N/A// Access stack slot for load or store
0N/Avoid store_to_stackslot(CodeBuffer &cbuf, int opcode, int rm_field, int disp)
0N/A emit_opcode(cbuf, opcode); // (
e.g., FILD [RSP+src])
0N/A if (-0x80 <= disp && disp < 0x80) {
0N/A emit_rm(cbuf, 0x01, rm_field, RSP_enc); // R/M byte
0N/A emit_rm(cbuf, 0x00, RSP_enc, RSP_enc); // SIB byte
0N/A emit_d8(cbuf, disp); // Displacement // R/M byte
0N/A emit_rm(cbuf, 0x02, rm_field, RSP_enc); // R/M byte
0N/A emit_rm(cbuf, 0x00, RSP_enc, RSP_enc); // SIB byte
0N/A emit_d32(cbuf, disp); // Displacement // R/M byte
0N/A // rRegI ereg, memory mem) %{ // emit_reg_mem
0N/Avoid encode_RegMem(CodeBuffer &cbuf,
0N/A int base, int index, int scale, int disp, bool disp_is_oop)
0N/A assert(!disp_is_oop, "cannot have disp");
0N/A int regenc = reg & 7;
0N/A int baseenc = base & 7;
0N/A int indexenc = index & 7;
0N/A // There is no index & no scale, use form without SIB byte
0N/A if (index == 0x4 && scale == 0 && base != RSP_enc && base != R12_enc) {
0N/A // If no displacement, mode is 0x0; unless base is [RBP] or [R13]
0N/A if (disp == 0 && base != RBP_enc && base != R13_enc) {
0N/A emit_rm(cbuf, 0x0, regenc, baseenc); // *
0N/A } else if (-0x80 <= disp && disp < 0x80 && !disp_is_oop) {
0N/A // If 8-bit displacement, mode 0x1
0N/A emit_rm(cbuf, 0x1, regenc, baseenc); // *
0N/A emit_d8(cbuf, disp);
0N/A // If 32-bit displacement
0N/A if (base == -1) { // Special flag for absolute address
0N/A emit_rm(cbuf, 0x0, regenc, 0x5); // *
0N/A emit_d32_reloc(cbuf, disp, relocInfo::oop_type, RELOC_DISP32);
0N/A emit_d32(cbuf, disp);
0N/A // Normal base + offset
0N/A emit_rm(cbuf, 0x2, regenc, baseenc); // *
0N/A emit_d32_reloc(cbuf, disp, relocInfo::oop_type, RELOC_DISP32);
0N/A emit_d32(cbuf, disp);
0N/A // Else, encode with the SIB byte
0N/A // If no displacement, mode is 0x0; unless base is [RBP] or [R13]
0N/A if (disp == 0 && base != RBP_enc && base != R13_enc) {
0N/A // If no displacement
0N/A emit_rm(cbuf, 0x0, regenc, 0x4); // *
0N/A emit_rm(cbuf, scale, indexenc, baseenc);
0N/A if (-0x80 <= disp && disp < 0x80 && !disp_is_oop) {
0N/A // If 8-bit displacement, mode 0x1
0N/A emit_rm(cbuf, 0x1, regenc, 0x4); // *
0N/A emit_rm(cbuf, scale, indexenc, baseenc);
0N/A emit_d8(cbuf, disp);
0N/A // If 32-bit displacement
0N/A if (base == 0x04 ) {
0N/A emit_rm(cbuf, 0x2, regenc, 0x4);
0N/A emit_rm(cbuf, scale, indexenc, 0x04); // XXX is this valid???
0N/A emit_rm(cbuf, 0x2, regenc, 0x4);
0N/A emit_rm(cbuf, scale, indexenc, baseenc); // *
0N/A
Error!
There was an error!
null
java.lang.NullPointerException