Tue, 26 Jul 2016 17:06:17 +0800
Add multiply word to GPR instruction (mul) in MIPS assembler.
1 /*
2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
26 #include "precompiled.hpp"
27 #include "asm/macroAssembler.hpp"
28 #include "code/vtableStubs.hpp"
29 #include "interp_masm_mips_64.hpp"
30 #include "memory/resourceArea.hpp"
31 //#include "oops/InstanceKlass.hpp"
32 #include "oops/klassVtable.hpp"
33 #include "runtime/sharedRuntime.hpp"
34 #include "vmreg_mips.inline.hpp"
35 #ifdef COMPILER2
36 #include "opto/runtime.hpp"
37 #endif
40 // machine-dependent part of VtableStubs: create VtableStub of correct size and
41 // initialize its code
43 #define __ masm->
45 #ifndef PRODUCT
46 extern "C" void bad_compiled_vtable_index(JavaThread* thread,
47 oop receiver,
48 int index);
49 #endif
51 // used by compiler only; reciever in T0.
52 // used registers :
53 // Rmethod : receiver klass & method
54 // NOTE: If this code is used by the C1, the receiver_location is always 0.
55 // when reach here, receiver in T0, klass in T8
56 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
57 const int gs2_code_length = VtableStub::pd_code_size_limit(true);
58 //VtableStub* s = new(gs2_code_length) VtableStub(true, vtable_index, receiver_location);
59 //FIXME aoqi
60 VtableStub* s = new(gs2_code_length) VtableStub(true, vtable_index);
61 ResourceMark rm;
62 CodeBuffer cb(s->entry_point(), gs2_code_length);
63 MacroAssembler* masm = new MacroAssembler(&cb);
64 Register t1 = T8, t2 = Rmethod;
65 #ifndef PRODUCT
66 //#ifdef COMPILER2
67 if (CountCompiledCalls) {
68 __ li(AT, SharedRuntime::nof_megamorphic_calls_addr());
69 __ lw(t1, AT , 0);
70 __ addiu(t1, t1, 1);
71 __ sw(t1, AT,0);
72 }
73 //#endif
74 #endif
76 // get receiver (need to skip return address on top of stack)
77 //assert(receiver_location == T0->as_VMReg(), "receiver expected in T0");
79 // get receiver klass
80 address npe_addr = __ pc();
81 //__ ld_ptr(t1, T0, oopDesc::klass_offset_in_bytes());
82 //add for compressedoops
83 __ load_klass(t1, T0);
84 // compute entry offset (in words)
85 int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
86 #ifndef PRODUCT
87 if (DebugVtables) {
88 Label L;
89 // check offset vs vtable length
90 __ lw(t2, t1, InstanceKlass::vtable_length_offset()*wordSize);
91 assert(Assembler::is_simm16(vtable_index*vtableEntry::size()), "change this code");
92 __ move(AT, vtable_index*vtableEntry::size());
93 __ slt(AT, AT, t2);
94 __ bne(AT, R0, L);
95 __ delayed()->nop();
96 __ move(A2, vtable_index);
97 __ move(A1, A0);
98 __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), A1, A2);
99 __ bind(L);
100 }
101 #endif // PRODUCT
102 // load methodOop and target address
103 const Register method = Rmethod;
104 __ ld_ptr(method, t1, entry_offset*wordSize + vtableEntry::method_offset_in_bytes());
105 if (DebugVtables) {
106 Label L;
107 __ beq(method, R0, L);
108 __ delayed()->nop();
109 // __ cmpl(Address(method, Method::from_compiled_offset()), NULL_WORD);
110 __ lw(AT, method,in_bytes(Method::from_compiled_offset()));
111 //__ jcc(Assembler::notZero, L);
112 __ bne(AT, R0, L);
113 __ delayed()->nop();
114 __ stop("Vtable entry is NULL");
115 __ bind(L);
116 }
117 // T8: receiver klass
118 // T0: receiver
119 // Rmethod: methodOop
120 // T9: entry
121 address ame_addr = __ pc();
122 __ ld_ptr(T9, method,in_bytes(Method::from_compiled_offset()));
123 __ jr(T9);
124 __ delayed()->nop();
125 masm->flush();
126 s->set_exception_points(npe_addr, ame_addr);
127 return s;
128 }
131 // i am not sure which register to contain Interface, now i just assume A1. FIXME
132 // used registers :
133 // T1 T2
134 // when reach here, the receiver in T0, klass in T1
135 VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
136 // Note well: pd_code_size_limit is the absolute minimum we can get
137 // away with. If you add code here, bump the code stub size
138 // returned by pd_code_size_limit!
139 const int gs2_code_length = VtableStub::pd_code_size_limit(false);
140 VtableStub* s = new(gs2_code_length) VtableStub(false, vtable_index);
141 ResourceMark rm;
142 CodeBuffer cb(s->entry_point(), gs2_code_length);
143 MacroAssembler* masm = new MacroAssembler(&cb);
144 // we T8,T9 as temparary register, they are free from register allocator
145 Register t1 = T8, t2 = T2;
146 // Entry arguments:
147 // T1: Interface
148 // T0: Receiver
149 #ifndef PRODUCT
150 if (CountCompiledCalls) {
151 //__ incl(Address((int)SharedRuntime::nof_megamorphic_calls_addr(), relocInfo::none));
152 __ li(AT, SharedRuntime::nof_megamorphic_calls_addr());
153 __ lw(T8, AT, 0);
154 __ addi(T8, T8,1);
155 __ sw(T8, AT, 0);
156 }
157 #endif /* PRODUCT */
158 //assert(receiver_location == T0->as_VMReg(), "receiver expected in T0");
159 // get receiver klass (also an implicit null-check)
160 address npe_addr = __ pc();
161 //__ ld_ptr(t1, T0, oopDesc::klass_offset_in_bytes());
162 //add for compressedoops
163 __ load_klass(t1, T0);
164 // compute itable entry offset (in words)
165 const int base = InstanceKlass::vtable_start_offset() * wordSize;
166 assert(vtableEntry::size() * wordSize == 8, "adjust the scaling in the code below");
167 assert(Assembler::is_simm16(base), "change this code");
168 __ daddi(t2, t1, base);
169 assert(Assembler::is_simm16(InstanceKlass::vtable_length_offset() * wordSize), "change this code");
170 __ lw(AT, t1, InstanceKlass::vtable_length_offset() * wordSize);
171 __ dsll(AT, AT, Address::times_8);
172 __ dadd(t2, t2, AT);
173 if (HeapWordsPerLong > 1) {
174 __ round_to(t2, BytesPerLong);
175 }
177 Label hit, entry;
178 assert(Assembler::is_simm16(itableOffsetEntry::size() * wordSize), "change this code");
179 __ bind(entry);
181 #ifdef ASSERT
182 // Check that the entry is non-null
183 if (DebugVtables) {
184 Label L;
185 assert(Assembler::is_simm16(itableOffsetEntry::interface_offset_in_bytes()), "change this code");
186 __ lw(AT, t1, itableOffsetEntry::interface_offset_in_bytes());
187 __ bne(AT, R0, L);
188 __ delayed()->nop();
189 __ stop("null entry point found in itable's offset table");
190 __ bind(L);
191 }
192 #endif
193 assert(Assembler::is_simm16(itableOffsetEntry::interface_offset_in_bytes()), "change this code");
194 __ ld_ptr(AT, t2, itableOffsetEntry::interface_offset_in_bytes());
195 __ bne(AT, T1, entry);
196 __ delayed()->addi(t2, t2, itableOffsetEntry::size() * wordSize);
198 // We found a hit, move offset into T9
199 __ ld_ptr(t2, t2, itableOffsetEntry::offset_offset_in_bytes() - itableOffsetEntry::size() * wordSize);
201 // Compute itableMethodEntry.
202 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
203 itableMethodEntry::method_offset_in_bytes();
205 // Get methodOop and entrypoint for compiler
206 // const Register method = ebx;
207 const Register method = Rmethod;
208 // __ movl(method, Address(esi, edx, Address::times_1, method_offset));
209 __ dsll(AT, t2, Address::times_1);
210 __ add(AT, AT, t1 );
211 __ ld_ptr(method, AT, method_offset);
215 #ifdef ASSERT
216 if (DebugVtables) {
217 Label L1;
218 // __ cmpl(method, NULL_WORD);
219 // __ jcc(Assembler::equal, L1);
220 __ beq(method, R0, L1);
221 __ delayed()->nop();
222 // __ cmpl(Address(method, Method::from_compiled_offset()), NULL_WORD);
223 __ lw(AT, method,in_bytes(Method::from_compiled_offset()));
224 // __ jcc(Assembler::notZero, L1);
225 __ bne(AT, R0, L1);
226 __ delayed()->nop();
227 __ stop("methodOop is null");
228 __ bind(L1);
229 }
230 #endif // ASSERT
231 /*
232 // Rmethod: methodOop
233 // T0: receiver
234 // T9: entry point
235 __ jmp(T9);
236 #endif // COMPILER2
237 */
238 address ame_addr = __ pc();
239 __ ld_ptr(T9, method,in_bytes(Method::from_compiled_offset()));
240 __ jr(T9);
241 __ delayed()->nop();
242 masm->flush();
243 s->set_exception_points(npe_addr, ame_addr);
244 return s;
245 }
247 // NOTE : whenever you change the code above, dont forget to change the const here
248 int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
249 if (is_vtable_stub) {
250 return ( DebugVtables ? 600 : 28) + (CountCompiledCalls ? 24 : 0)+
251 (UseCompressedOops ? 16 : 0);
252 } else {
253 return ( DebugVtables ? 636 : 72) + (CountCompiledCalls ? 24 : 0)+
254 (UseCompressedOops ? 32 : 0);
255 }
256 }
258 int VtableStub::pd_code_alignment() {
259 return wordSize;
260 }