duke@435: /* duke@435: * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: # include "incls/_precompiled.incl" duke@435: # include "incls/_c1_FpuStackSim_x86.cpp.incl" duke@435: duke@435: //-------------------------------------------------------- duke@435: // FpuStackSim duke@435: //-------------------------------------------------------- duke@435: duke@435: // This class maps the FPU registers to their stack locations; it computes duke@435: // the offsets between individual registers and simulates the FPU stack. duke@435: duke@435: const int EMPTY = -1; duke@435: duke@435: int FpuStackSim::regs_at(int i) const { duke@435: assert(i >= 0 && i < FrameMap::nof_fpu_regs, "out of bounds"); duke@435: return _regs[i]; duke@435: } duke@435: duke@435: void FpuStackSim::set_regs_at(int i, int val) { duke@435: assert(i >= 0 && i < FrameMap::nof_fpu_regs, "out of bounds"); duke@435: _regs[i] = val; duke@435: } duke@435: duke@435: void FpuStackSim::dec_stack_size() { duke@435: _stack_size--; duke@435: assert(_stack_size >= 0, "FPU stack underflow"); duke@435: } duke@435: duke@435: void FpuStackSim::inc_stack_size() { duke@435: _stack_size++; duke@435: assert(_stack_size <= FrameMap::nof_fpu_regs, "FPU stack overflow"); duke@435: } duke@435: duke@435: FpuStackSim::FpuStackSim(Compilation* compilation) duke@435: : _compilation(compilation) duke@435: { duke@435: _stack_size = 0; duke@435: for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { duke@435: set_regs_at(i, EMPTY); duke@435: } duke@435: } duke@435: duke@435: duke@435: void FpuStackSim::pop() { duke@435: if (TraceFPUStack) { tty->print("FPU-pop "); print(); tty->cr(); } duke@435: set_regs_at(tos_index(), EMPTY); duke@435: dec_stack_size(); duke@435: } duke@435: duke@435: void FpuStackSim::pop(int rnr) { duke@435: if (TraceFPUStack) { tty->print("FPU-pop %d", rnr); print(); tty->cr(); } duke@435: assert(regs_at(tos_index()) == rnr, "rnr is not on TOS"); duke@435: set_regs_at(tos_index(), EMPTY); duke@435: dec_stack_size(); duke@435: } duke@435: duke@435: duke@435: void FpuStackSim::push(int rnr) { duke@435: if (TraceFPUStack) { tty->print("FPU-push %d", rnr); print(); tty->cr(); } duke@435: assert(regs_at(stack_size()) == EMPTY, "should be empty"); duke@435: set_regs_at(stack_size(), rnr); duke@435: inc_stack_size(); duke@435: } duke@435: duke@435: duke@435: void FpuStackSim::swap(int offset) { duke@435: if (TraceFPUStack) { tty->print("FPU-swap %d", offset); print(); tty->cr(); } duke@435: int t = regs_at(tos_index() - offset); duke@435: set_regs_at(tos_index() - offset, regs_at(tos_index())); duke@435: set_regs_at(tos_index(), t); duke@435: } duke@435: duke@435: duke@435: int FpuStackSim::offset_from_tos(int rnr) const { duke@435: for (int i = tos_index(); i >= 0; i--) { duke@435: if (regs_at(i) == rnr) { duke@435: return tos_index() - i; duke@435: } duke@435: } duke@435: assert(false, "FpuStackSim: register not found"); duke@435: BAILOUT_("FpuStackSim: register not found", 0); duke@435: } duke@435: duke@435: duke@435: int FpuStackSim::get_slot(int tos_offset) const { duke@435: return regs_at(tos_index() - tos_offset); duke@435: } duke@435: duke@435: void FpuStackSim::set_slot(int tos_offset, int rnr) { duke@435: set_regs_at(tos_index() - tos_offset, rnr); duke@435: } duke@435: duke@435: void FpuStackSim::rename(int old_rnr, int new_rnr) { duke@435: if (TraceFPUStack) { tty->print("FPU-rename %d %d", old_rnr, new_rnr); print(); tty->cr(); } duke@435: if (old_rnr == new_rnr) duke@435: return; duke@435: bool found = false; duke@435: for (int i = 0; i < stack_size(); i++) { duke@435: assert(regs_at(i) != new_rnr, "should not see old occurrences of new_rnr on the stack"); duke@435: if (regs_at(i) == old_rnr) { duke@435: set_regs_at(i, new_rnr); duke@435: found = true; duke@435: } duke@435: } duke@435: assert(found, "should have found at least one instance of old_rnr"); duke@435: } duke@435: duke@435: duke@435: bool FpuStackSim::contains(int rnr) { duke@435: for (int i = 0; i < stack_size(); i++) { duke@435: if (regs_at(i) == rnr) { duke@435: return true; duke@435: } duke@435: } duke@435: return false; duke@435: } duke@435: duke@435: bool FpuStackSim::is_empty() { duke@435: #ifdef ASSERT duke@435: if (stack_size() == 0) { duke@435: for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { duke@435: assert(regs_at(i) == EMPTY, "must be empty"); duke@435: } duke@435: } duke@435: #endif duke@435: return stack_size() == 0; duke@435: } duke@435: duke@435: duke@435: bool FpuStackSim::slot_is_empty(int tos_offset) { duke@435: return (regs_at(tos_index() - tos_offset) == EMPTY); duke@435: } duke@435: duke@435: duke@435: void FpuStackSim::clear() { duke@435: if (TraceFPUStack) { tty->print("FPU-clear"); print(); tty->cr(); } duke@435: for (int i = tos_index(); i >= 0; i--) { duke@435: set_regs_at(i, EMPTY); duke@435: } duke@435: _stack_size = 0; duke@435: } duke@435: duke@435: duke@435: intArray* FpuStackSim::write_state() { duke@435: intArray* res = new intArray(1 + FrameMap::nof_fpu_regs); duke@435: (*res)[0] = stack_size(); duke@435: for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { duke@435: (*res)[1 + i] = regs_at(i); duke@435: } duke@435: return res; duke@435: } duke@435: duke@435: duke@435: void FpuStackSim::read_state(intArray* fpu_stack_state) { duke@435: _stack_size = (*fpu_stack_state)[0]; duke@435: for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { duke@435: set_regs_at(i, (*fpu_stack_state)[1 + i]); duke@435: } duke@435: } duke@435: duke@435: duke@435: #ifndef PRODUCT duke@435: void FpuStackSim::print() { duke@435: tty->print(" N=%d[", stack_size());\ duke@435: for (int i = 0; i < stack_size(); i++) { duke@435: int reg = regs_at(i); duke@435: if (reg != EMPTY) { duke@435: tty->print("%d", reg); duke@435: } else { duke@435: tty->print("_"); duke@435: } duke@435: }; duke@435: tty->print(" ]"); duke@435: } duke@435: #endif