/*
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef CPU_SPARC_VM_FRAME_SPARC_INLINE_HPP
#define CPU_SPARC_VM_FRAME_SPARC_INLINE_HPP

#include "asm/macroAssembler.hpp"
#include "code/vmreg.inline.hpp"

// Inline functions for SPARC frames:

// Constructors

inline frame::frame() {
  _pc = NULL;
  _sp = NULL;
  _younger_sp = NULL;
  _cb = NULL;
  _deopt_state = unknown;
  _sp_adjustment_by_callee = 0;
}

// Accessors:

inline bool frame::equal(frame other) const {
  bool ret =  sp() == other.sp()
           && fp() == other.fp()
           && pc() == other.pc();
  assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction");
  return ret;
}

// Return unique id for this frame. The id must have a value where we can distinguish
// identity and younger/older relationship. NULL represents an invalid (incomparable)
// frame.
inline intptr_t* frame::id(void) const { return unextended_sp(); }

// Relationals on frames based
// Return true if the frame is younger (more recent activation) than the frame represented by id
inline bool frame::is_younger(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id");
                                                    return this->id() < id ; }

// Return true if the frame is older (less recent activation) than the frame represented by id
inline bool frame::is_older(intptr_t* id) const   { assert(this->id() != NULL && id != NULL, "NULL frame id");
                                                    return this->id() > id ; }

inline int frame::frame_size(RegisterMap* map) const { return sender_sp() - sp(); }

inline intptr_t* frame::link() const { return (intptr_t *)(fp()[FP->sp_offset_in_saved_window()] + STACK_BIAS); }

inline void frame::set_link(intptr_t* addr) { assert(link()==addr, "frame nesting is controlled by hardware"); }

inline intptr_t* frame::unextended_sp() const { return sp() + _sp_adjustment_by_callee; }

// return address:

inline address  frame::sender_pc()        const    { return *I7_addr() + pc_return_offset; }

inline address* frame::I7_addr() const  { return (address*) &sp()[ I7->sp_offset_in_saved_window()]; }
inline address* frame::I0_addr() const  { return (address*) &sp()[ I0->sp_offset_in_saved_window()]; }

inline address* frame::O7_addr() const  { return (address*) &younger_sp()[ I7->sp_offset_in_saved_window()]; }
inline address* frame::O0_addr() const  { return (address*) &younger_sp()[ I0->sp_offset_in_saved_window()]; }

inline intptr_t*    frame::sender_sp() const  { return fp(); }

inline intptr_t* frame::real_fp() const { return fp(); }

// Used only in frame::oopmapreg_to_location
// This return a value in VMRegImpl::slot_size
inline int frame::pd_oop_map_offset_adjustment() const {
  return _sp_adjustment_by_callee * VMRegImpl::slots_per_word;
}

#ifdef CC_INTERP
inline intptr_t** frame::interpreter_frame_locals_addr() const {
  interpreterState istate = get_interpreterState();
  return (intptr_t**) &istate->_locals;
}

inline intptr_t* frame::interpreter_frame_bcp_addr() const {
  interpreterState istate = get_interpreterState();
  return (intptr_t*) &istate->_bcp;
}

inline intptr_t* frame::interpreter_frame_mdp_addr() const {
  interpreterState istate = get_interpreterState();
  return (intptr_t*) &istate->_mdx;
}

inline jint frame::interpreter_frame_expression_stack_direction() { return -1; }

// bottom(base) of the expression stack (highest address)
inline intptr_t* frame::interpreter_frame_expression_stack() const {
  return (intptr_t*)interpreter_frame_monitor_end() - 1;
}

// top of expression stack (lowest address)
inline intptr_t* frame::interpreter_frame_tos_address() const {
  interpreterState istate = get_interpreterState();
  return istate->_stack + 1; // Is this off by one? QQQ
}

// monitor elements

// in keeping with Intel side: end is lower in memory than begin;
// and beginning element is oldest element
// Also begin is one past last monitor.

inline BasicObjectLock* frame::interpreter_frame_monitor_begin()       const  {
  return get_interpreterState()->monitor_base();
}

inline BasicObjectLock* frame::interpreter_frame_monitor_end()         const  {
  return (BasicObjectLock*) get_interpreterState()->stack_base();
}


inline int frame::interpreter_frame_monitor_size() {
  return round_to(BasicObjectLock::size(), WordsPerLong);
}

inline Method** frame::interpreter_frame_method_addr() const {
  interpreterState istate = get_interpreterState();
  return &istate->_method;
}


// Constant pool cache

// where LcpoolCache is saved:
inline ConstantPoolCache** frame::interpreter_frame_cpoolcache_addr() const {
  interpreterState istate = get_interpreterState();
  return &istate->_constants; // should really use accessor
  }

inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const {
  interpreterState istate = get_interpreterState();
  return &istate->_constants;
}

#else // !CC_INTERP

inline intptr_t** frame::interpreter_frame_locals_addr() const {
  return (intptr_t**) sp_addr_at( Llocals->sp_offset_in_saved_window());
}

inline intptr_t* frame::interpreter_frame_bcp_addr() const {
  return (intptr_t*) sp_addr_at( Lbcp->sp_offset_in_saved_window());
}

inline intptr_t* frame::interpreter_frame_mdp_addr() const {
  // %%%%% reinterpreting ImethodDataPtr as a mdx
  return (intptr_t*) sp_addr_at( ImethodDataPtr->sp_offset_in_saved_window());
}

inline jint frame::interpreter_frame_expression_stack_direction() { return -1; }

// bottom(base) of the expression stack (highest address)
inline intptr_t* frame::interpreter_frame_expression_stack() const {
  return (intptr_t*)interpreter_frame_monitors() - 1;
}

// top of expression stack (lowest address)
inline intptr_t* frame::interpreter_frame_tos_address() const {
  return *interpreter_frame_esp_addr() + 1;
}

inline BasicObjectLock** frame::interpreter_frame_monitors_addr() const {
  return (BasicObjectLock**) sp_addr_at(Lmonitors->sp_offset_in_saved_window());
}
inline intptr_t** frame::interpreter_frame_esp_addr() const {
  return (intptr_t**)sp_addr_at(Lesp->sp_offset_in_saved_window());
}

inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) {
  *interpreter_frame_esp_addr() = x - 1;
}

// monitor elements

// in keeping with Intel side: end is lower in memory than begin;
// and beginning element is oldest element
// Also begin is one past last monitor.

inline BasicObjectLock* frame::interpreter_frame_monitor_begin()       const  {
  int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong);
  return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words);
}

inline BasicObjectLock* frame::interpreter_frame_monitor_end()         const  {
  return interpreter_frame_monitors();
}


inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
  interpreter_frame_set_monitors(value);
}

inline int frame::interpreter_frame_monitor_size() {
  return round_to(BasicObjectLock::size(), WordsPerLong);
}

inline Method** frame::interpreter_frame_method_addr() const {
  return (Method**)sp_addr_at( Lmethod->sp_offset_in_saved_window());
}

inline BasicObjectLock* frame::interpreter_frame_monitors() const {
  return *interpreter_frame_monitors_addr();
}

inline void frame::interpreter_frame_set_monitors(BasicObjectLock* monitors) {
  *interpreter_frame_monitors_addr() = monitors;
}

// Constant pool cache

// where LcpoolCache is saved:
inline ConstantPoolCache** frame::interpreter_frame_cpoolcache_addr() const {
    return (ConstantPoolCache**)sp_addr_at(LcpoolCache->sp_offset_in_saved_window());
  }

inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const {
  return (ConstantPoolCache**)sp_addr_at( LcpoolCache->sp_offset_in_saved_window());
}

inline oop* frame::interpreter_frame_temp_oop_addr() const {
  return (oop *)(fp() + interpreter_frame_oop_temp_offset);
}
#endif // CC_INTERP


inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
  // note: adjust this code if the link argument in StubGenerator::call_stub() changes!
  const Argument link = Argument(0, false);
  return (JavaCallWrapper**)&sp()[link.as_in().as_register()->sp_offset_in_saved_window()];
}


inline int frame::local_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors) {
   // always allocate non-argument locals 0..5 as if they were arguments:
  int allocated_above_frame = nof_args;
  if (allocated_above_frame < callee_register_argument_save_area_words)
    allocated_above_frame = callee_register_argument_save_area_words;
  if (allocated_above_frame > max_nof_locals)
    allocated_above_frame = max_nof_locals;

  // Note: monitors (BasicLock blocks) are never allocated in argument slots
  //assert(local_index >= 0 && local_index < max_nof_locals, "bad local index");
  if (local_index < allocated_above_frame)
    return local_index + callee_register_argument_save_area_sp_offset;
  else
    return local_index - (max_nof_locals + max_nof_monitors*2) + compiler_frame_vm_locals_fp_offset;
}

inline int frame::monitor_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors) {
  assert(local_index >= max_nof_locals && ((local_index - max_nof_locals) & 1) && (local_index - max_nof_locals) < max_nof_monitors*2, "bad monitor index");

  // The compiler uses the __higher__ of two indexes allocated to the monitor.
  // Increasing local indexes are mapped to increasing memory locations,
  // so the start of the BasicLock is associated with the __lower__ index.

  int offset = (local_index-1) - (max_nof_locals + max_nof_monitors*2) + compiler_frame_vm_locals_fp_offset;

  // We allocate monitors aligned zero mod 8:
  assert((offset & 1) == 0, "monitor must be an an even address.");
  // This works because all monitors are allocated after
  // all locals, and because the highest address corresponding to any
  // monitor index is always even.
  assert((compiler_frame_vm_locals_fp_offset & 1) == 0, "end of monitors must be even address");

  return offset;
}

inline int frame::min_local_offset_for_compiler(int nof_args, int max_nof_locals, int max_nof_monitors) {
   // always allocate non-argument locals 0..5 as if they were arguments:
  int allocated_above_frame = nof_args;
  if (allocated_above_frame < callee_register_argument_save_area_words)
    allocated_above_frame = callee_register_argument_save_area_words;
  if (allocated_above_frame > max_nof_locals)
    allocated_above_frame = max_nof_locals;

  int allocated_in_frame = (max_nof_locals + max_nof_monitors*2) - allocated_above_frame;

  return compiler_frame_vm_locals_fp_offset - allocated_in_frame;
}

// On SPARC, the %lN and %iN registers are non-volatile.
inline bool frame::volatile_across_calls(Register reg) {
  // This predicate is (presently) applied only to temporary registers,
  // and so it need not recognize non-volatile globals.
  return reg->is_out() || reg->is_global();
}

inline oop  frame::saved_oop_result(RegisterMap* map) const      {
  return *((oop*) map->location(O0->as_VMReg()));
}

inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
  *((oop*) map->location(O0->as_VMReg())) = obj;
}

#endif // CPU_SPARC_VM_FRAME_SPARC_INLINE_HPP
