0
|
1 /*
|
|
2 * Copyright 2000-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.runtime.sparc;
|
|
26
|
|
27 import java.util.*;
|
|
28
|
|
29 import sun.jvm.hotspot.asm.sparc.*;
|
|
30 import sun.jvm.hotspot.debugger.*;
|
|
31 import sun.jvm.hotspot.runtime.*;
|
|
32 import sun.jvm.hotspot.types.*;
|
|
33 import sun.jvm.hotspot.utilities.*;
|
|
34
|
|
35 public class SPARCRegisterMap extends RegisterMap {
|
|
36 /** Register window save area (for L and I regs) */
|
|
37 private Address window;
|
|
38 /** Previous save area (for O regs, if needed) */
|
|
39 private Address youngerWindow;
|
|
40
|
|
41 private static int registerImplNumberOfRegisters;
|
|
42
|
|
43 // Unified register numbering scheme: each 32-bits counts as a register
|
|
44 // number, so all the V9 registers take 2 slots.
|
|
45 private static int[] R_L_nums = new int[] {0+040,2+040,4+040,6+040,8+040,10+040,12+040,14+040};
|
|
46 private static int[] R_I_nums = new int[] {0+060,2+060,4+060,6+060,8+060,10+060,12+060,14+060};
|
|
47 private static int[] R_O_nums = new int[] {0+020,2+020,4+020,6+020,8+020,10+020,12+020,14+020};
|
|
48 private static int[] R_G_nums = new int[] {0+000,2+000,4+000,6+000,8+000,10+000,12+000,14+000};
|
|
49
|
|
50 private static long badMask;
|
|
51 private static long R_LIO_mask;
|
|
52
|
|
53 private static int sizeofJint;
|
|
54
|
|
55 static {
|
|
56 VM.registerVMInitializedObserver(new Observer() {
|
|
57 public void update(Observable o, Object data) {
|
|
58 initialize(VM.getVM().getTypeDataBase());
|
|
59 }
|
|
60 });
|
|
61 }
|
|
62
|
|
63 private static void initialize(TypeDataBase db) {
|
|
64 badMask = 0;
|
|
65 R_LIO_mask = 0;
|
|
66
|
|
67 sizeofJint = (int) db.lookupType("jint").getSize();
|
|
68 registerImplNumberOfRegisters = db.lookupIntConstant("RegisterImpl::number_of_registers").intValue();
|
|
69
|
|
70 for (int i = 0; i < 8; i++) {
|
|
71 Assert.that(R_L_nums[i] < locationValidTypeSize, "in first chunk");
|
|
72 Assert.that(R_I_nums[i] < locationValidTypeSize, "in first chunk");
|
|
73 Assert.that(R_O_nums[i] < locationValidTypeSize, "in first chunk");
|
|
74 Assert.that(R_G_nums[i] < locationValidTypeSize, "in first chunk");
|
|
75 }
|
|
76
|
|
77 badMask |= ((long) 1 << R_O_nums[6]); // SP
|
|
78 badMask |= ((long) 1 << R_O_nums[7]); // cPC
|
|
79 badMask |= ((long) 1 << R_I_nums[6]); // FP
|
|
80 badMask |= ((long) 1 << R_I_nums[7]); // rPC
|
|
81 badMask |= ((long) 1 << R_G_nums[2]); // TLS
|
|
82 badMask |= ((long) 1 << R_G_nums[7]); // reserved by libthread
|
|
83
|
|
84 for (int i = 0; i < 8; i++) {
|
|
85 R_LIO_mask |= ((long) 1 << R_L_nums[i]);
|
|
86 R_LIO_mask |= ((long) 1 << R_I_nums[i]);
|
|
87 R_LIO_mask |= ((long) 1 << R_O_nums[i]);
|
|
88 }
|
|
89 }
|
|
90
|
|
91 /** This is the only public constructor, and is only called by
|
|
92 SolarisSPARCJavaThread */
|
|
93 public SPARCRegisterMap(JavaThread thread, boolean updateMap) {
|
|
94 super(thread, updateMap);
|
|
95 }
|
|
96
|
|
97 protected SPARCRegisterMap(RegisterMap map) {
|
|
98 super(map);
|
|
99 }
|
|
100
|
|
101 public Object clone() {
|
|
102 SPARCRegisterMap retval = new SPARCRegisterMap(this);
|
|
103 return retval;
|
|
104 }
|
|
105
|
|
106 protected void clearPD() {
|
|
107 if (thread.hasLastJavaFrame()) {
|
|
108 Frame fr = thread.getLastFrame();
|
|
109 window = fr.getSP();
|
|
110 } else {
|
|
111 window = null;
|
|
112 if (VM.getVM().isDebugging()) {
|
|
113 Frame fr = thread.getCurrentFrameGuess();
|
|
114 if (fr != null) {
|
|
115 window = fr.getSP();
|
|
116 }
|
|
117 }
|
|
118 }
|
|
119 youngerWindow = null;
|
|
120 }
|
|
121
|
|
122 protected Address getLocationPD(VMReg vmreg) {
|
|
123 VM vm = VM.getVM();
|
|
124 int regname = vmreg.getValue();
|
|
125 if (Assert.ASSERTS_ENABLED) {
|
|
126 Assert.that(0 <= regname && regname < regCount, "sanity check");
|
|
127 }
|
|
128
|
|
129 // Only the GPRs get handled this way
|
|
130 if (regname >= (registerImplNumberOfRegisters << 1)) {
|
|
131 return null;
|
|
132 }
|
|
133
|
|
134 // don't talk about bad registers
|
|
135 if ((badMask & ((long) 1 << regname)) != 0) {
|
|
136 return null;
|
|
137 }
|
|
138
|
|
139 // Convert to a GPR
|
|
140 int secondWord = 0;
|
|
141 // 32-bit registers for in, out and local
|
|
142 if (!isEven(regname)) {
|
|
143 if (vm.isLP64()) {
|
|
144 secondWord = sizeofJint;
|
|
145 } else {
|
|
146 return null;
|
|
147 }
|
|
148 }
|
|
149
|
|
150 SPARCRegister reg = new SPARCRegister(regname >> 1);
|
|
151 if (reg.isOut()) {
|
|
152 if (Assert.ASSERTS_ENABLED) {
|
|
153 Assert.that(youngerWindow != null, "Younger window should be available");
|
|
154 }
|
|
155 return youngerWindow.addOffsetTo(reg.afterSave().spOffsetInSavedWindow() + secondWord);
|
|
156 }
|
|
157 if (reg.isLocal() || reg.isIn()) {
|
|
158 if (Assert.ASSERTS_ENABLED) {
|
|
159 Assert.that(window != null, "Window should be available");
|
|
160 }
|
|
161 return window.addOffsetTo(reg.spOffsetInSavedWindow() + secondWord);
|
|
162 }
|
|
163
|
|
164 // Only the window'd GPRs get handled this way; not the globals.
|
|
165 return null;
|
|
166 }
|
|
167
|
|
168 protected void initializePD() {
|
|
169 window = null;
|
|
170 youngerWindow = null;
|
|
171 // avoid the shift_individual_registers game
|
|
172 makeIntegerRegsUnsaved();
|
|
173 }
|
|
174
|
|
175 protected void initializeFromPD(RegisterMap map) {
|
|
176 SPARCRegisterMap srm = (SPARCRegisterMap) map;
|
|
177 window = srm.window;
|
|
178 youngerWindow = srm.youngerWindow;
|
|
179 // avoid the shift_individual_registers game
|
|
180 makeIntegerRegsUnsaved();
|
|
181 }
|
|
182
|
|
183 public void shiftWindow(Address sp, Address youngerSP) {
|
|
184 window = sp;
|
|
185 youngerWindow = youngerSP;
|
|
186 // Throw away locations for %i, %o, and %l registers:
|
|
187 // But do not throw away %g register locs.
|
|
188 if (locationValid[0] != 0) {
|
|
189 shiftIndividualRegisters();
|
|
190 }
|
|
191 }
|
|
192
|
|
193 /** When popping out of compiled frames, we make all IRegs disappear. */
|
|
194 public void makeIntegerRegsUnsaved() {
|
|
195 locationValid[0] = 0;
|
|
196 }
|
|
197
|
|
198 //--------------------------------------------------------------------------------
|
|
199 // Internals only below this point
|
|
200 //
|
|
201
|
|
202 private void shiftIndividualRegisters() {
|
|
203 if (!getUpdateMap()) {
|
|
204 return;
|
|
205 }
|
|
206
|
|
207 checkLocationValid();
|
|
208
|
|
209 long lv = locationValid[0];
|
|
210 long lv0 = lv;
|
|
211
|
|
212 lv &= ~R_LIO_mask; // clear %l, %o, %i regs
|
|
213
|
|
214 // if we cleared some non-%g locations, we may have to do some shifting
|
|
215 if (lv != lv0) {
|
|
216 // copy %i0-%i5 to %o0-%o5, if they have special locations
|
|
217 // This can happen in within stubs which spill argument registers
|
|
218 // around a dynamic link operation, such as resolve_opt_virtual_call.
|
|
219 for (int i = 0; i < 8; i++) {
|
|
220 if ((lv0 & ((long) 1 << R_I_nums[i])) != 0) {
|
|
221 location[R_O_nums[i]] = location[R_I_nums[i]];
|
|
222 lv |= ((long) 1 << R_O_nums[i]);
|
|
223 }
|
|
224 }
|
|
225 }
|
|
226
|
|
227 locationValid[0] = lv;
|
|
228 checkLocationValid();
|
|
229 }
|
|
230
|
|
231 private boolean isEven(int i) {
|
|
232 return (i & 1) == 0;
|
|
233 }
|
|
234
|
|
235 private void checkLocationValid() {
|
|
236 if (Assert.ASSERTS_ENABLED) {
|
|
237 Assert.that((locationValid[0] & badMask) == 0, "cannot have special locations for SP,FP,TLS,etc.");
|
|
238 }
|
|
239 }
|
|
240 }
|