1 | /* |
2 | * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "c1/c1_FpuStackSim.hpp" |
27 | #include "c1/c1_FrameMap.hpp" |
28 | #include "utilities/growableArray.hpp" |
29 | #include "utilities/ostream.hpp" |
30 | |
31 | //-------------------------------------------------------- |
32 | // FpuStackSim |
33 | //-------------------------------------------------------- |
34 | |
35 | // This class maps the FPU registers to their stack locations; it computes |
36 | // the offsets between individual registers and simulates the FPU stack. |
37 | |
38 | const int EMPTY = -1; |
39 | |
40 | int FpuStackSim::regs_at(int i) const { |
41 | assert(i >= 0 && i < FrameMap::nof_fpu_regs, "out of bounds" ); |
42 | return _regs[i]; |
43 | } |
44 | |
45 | void FpuStackSim::set_regs_at(int i, int val) { |
46 | assert(i >= 0 && i < FrameMap::nof_fpu_regs, "out of bounds" ); |
47 | _regs[i] = val; |
48 | } |
49 | |
50 | void FpuStackSim::dec_stack_size() { |
51 | _stack_size--; |
52 | assert(_stack_size >= 0, "FPU stack underflow" ); |
53 | } |
54 | |
55 | void FpuStackSim::inc_stack_size() { |
56 | _stack_size++; |
57 | assert(_stack_size <= FrameMap::nof_fpu_regs, "FPU stack overflow" ); |
58 | } |
59 | |
60 | FpuStackSim::FpuStackSim(Compilation* compilation) |
61 | : _compilation(compilation) |
62 | { |
63 | _stack_size = 0; |
64 | for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { |
65 | set_regs_at(i, EMPTY); |
66 | } |
67 | } |
68 | |
69 | |
70 | void FpuStackSim::pop() { |
71 | if (TraceFPUStack) { tty->print("FPU-pop " ); print(); tty->cr(); } |
72 | set_regs_at(tos_index(), EMPTY); |
73 | dec_stack_size(); |
74 | } |
75 | |
76 | void FpuStackSim::pop(int rnr) { |
77 | if (TraceFPUStack) { tty->print("FPU-pop %d" , rnr); print(); tty->cr(); } |
78 | assert(regs_at(tos_index()) == rnr, "rnr is not on TOS" ); |
79 | set_regs_at(tos_index(), EMPTY); |
80 | dec_stack_size(); |
81 | } |
82 | |
83 | |
84 | void FpuStackSim::push(int rnr) { |
85 | if (TraceFPUStack) { tty->print("FPU-push %d" , rnr); print(); tty->cr(); } |
86 | assert(regs_at(stack_size()) == EMPTY, "should be empty" ); |
87 | set_regs_at(stack_size(), rnr); |
88 | inc_stack_size(); |
89 | } |
90 | |
91 | |
92 | void FpuStackSim::swap(int offset) { |
93 | if (TraceFPUStack) { tty->print("FPU-swap %d" , offset); print(); tty->cr(); } |
94 | int t = regs_at(tos_index() - offset); |
95 | set_regs_at(tos_index() - offset, regs_at(tos_index())); |
96 | set_regs_at(tos_index(), t); |
97 | } |
98 | |
99 | |
100 | int FpuStackSim::offset_from_tos(int rnr) const { |
101 | for (int i = tos_index(); i >= 0; i--) { |
102 | if (regs_at(i) == rnr) { |
103 | return tos_index() - i; |
104 | } |
105 | } |
106 | assert(false, "FpuStackSim: register not found" ); |
107 | BAILOUT_("FpuStackSim: register not found" , 0); |
108 | } |
109 | |
110 | |
111 | int FpuStackSim::get_slot(int tos_offset) const { |
112 | return regs_at(tos_index() - tos_offset); |
113 | } |
114 | |
115 | void FpuStackSim::set_slot(int tos_offset, int rnr) { |
116 | set_regs_at(tos_index() - tos_offset, rnr); |
117 | } |
118 | |
119 | void FpuStackSim::rename(int old_rnr, int new_rnr) { |
120 | if (TraceFPUStack) { tty->print("FPU-rename %d %d" , old_rnr, new_rnr); print(); tty->cr(); } |
121 | if (old_rnr == new_rnr) |
122 | return; |
123 | bool found = false; |
124 | for (int i = 0; i < stack_size(); i++) { |
125 | assert(regs_at(i) != new_rnr, "should not see old occurrences of new_rnr on the stack" ); |
126 | if (regs_at(i) == old_rnr) { |
127 | set_regs_at(i, new_rnr); |
128 | found = true; |
129 | } |
130 | } |
131 | assert(found, "should have found at least one instance of old_rnr" ); |
132 | } |
133 | |
134 | |
135 | bool FpuStackSim::contains(int rnr) { |
136 | for (int i = 0; i < stack_size(); i++) { |
137 | if (regs_at(i) == rnr) { |
138 | return true; |
139 | } |
140 | } |
141 | return false; |
142 | } |
143 | |
144 | bool FpuStackSim::is_empty() { |
145 | #ifdef ASSERT |
146 | if (stack_size() == 0) { |
147 | for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { |
148 | assert(regs_at(i) == EMPTY, "must be empty" ); |
149 | } |
150 | } |
151 | #endif |
152 | return stack_size() == 0; |
153 | } |
154 | |
155 | |
156 | bool FpuStackSim::slot_is_empty(int tos_offset) { |
157 | return (regs_at(tos_index() - tos_offset) == EMPTY); |
158 | } |
159 | |
160 | |
161 | void FpuStackSim::clear() { |
162 | if (TraceFPUStack) { tty->print("FPU-clear" ); print(); tty->cr(); } |
163 | for (int i = tos_index(); i >= 0; i--) { |
164 | set_regs_at(i, EMPTY); |
165 | } |
166 | _stack_size = 0; |
167 | } |
168 | |
169 | |
170 | intArray* FpuStackSim::write_state() { |
171 | intArray* res = new intArray(1 + FrameMap::nof_fpu_regs); |
172 | res->append(stack_size()); |
173 | for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { |
174 | res->append(regs_at(i)); |
175 | } |
176 | return res; |
177 | } |
178 | |
179 | |
180 | void FpuStackSim::read_state(intArray* fpu_stack_state) { |
181 | _stack_size = fpu_stack_state->at(0); |
182 | for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { |
183 | set_regs_at(i, fpu_stack_state->at(1 + i)); |
184 | } |
185 | } |
186 | |
187 | |
188 | #ifndef PRODUCT |
189 | void FpuStackSim::print() { |
190 | tty->print(" N=%d[" , stack_size());\ |
191 | for (int i = 0; i < stack_size(); i++) { |
192 | int reg = regs_at(i); |
193 | if (reg != EMPTY) { |
194 | tty->print("%d" , reg); |
195 | } else { |
196 | tty->print("_" ); |
197 | } |
198 | }; |
199 | tty->print(" ]" ); |
200 | } |
201 | #endif |
202 | |