Mercurial > hg > truffle
annotate src/cpu/x86/vm/assembler_x86.cpp @ 2007:5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation.
Reviewed-by: kvn, never
author | iveresov |
---|---|
date | Thu, 02 Dec 2010 17:21:12 -0800 |
parents | f95d63e2154a |
children | 0fc262af204f 2f644f85485d |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "assembler_x86.inline.hpp" | |
27 #include "gc_interface/collectedHeap.inline.hpp" | |
28 #include "interpreter/interpreter.hpp" | |
29 #include "memory/cardTableModRefBS.hpp" | |
30 #include "memory/resourceArea.hpp" | |
31 #include "prims/methodHandles.hpp" | |
32 #include "runtime/biasedLocking.hpp" | |
33 #include "runtime/interfaceSupport.hpp" | |
34 #include "runtime/objectMonitor.hpp" | |
35 #include "runtime/os.hpp" | |
36 #include "runtime/sharedRuntime.hpp" | |
37 #include "runtime/stubRoutines.hpp" | |
38 #ifndef SERIALGC | |
39 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | |
40 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" | |
41 #include "gc_implementation/g1/heapRegion.hpp" | |
42 #endif | |
0 | 43 |
44 // Implementation of AddressLiteral | |
45 | |
46 AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) { | |
47 _is_lval = false; | |
48 _target = target; | |
49 switch (rtype) { | |
50 case relocInfo::oop_type: | |
51 // Oops are a special case. Normally they would be their own section | |
52 // but in cases like icBuffer they are literals in the code stream that | |
53 // we don't have a section for. We use none so that we get a literal address | |
54 // which is always patchable. | |
55 break; | |
56 case relocInfo::external_word_type: | |
57 _rspec = external_word_Relocation::spec(target); | |
58 break; | |
59 case relocInfo::internal_word_type: | |
60 _rspec = internal_word_Relocation::spec(target); | |
61 break; | |
62 case relocInfo::opt_virtual_call_type: | |
63 _rspec = opt_virtual_call_Relocation::spec(); | |
64 break; | |
65 case relocInfo::static_call_type: | |
66 _rspec = static_call_Relocation::spec(); | |
67 break; | |
68 case relocInfo::runtime_call_type: | |
69 _rspec = runtime_call_Relocation::spec(); | |
70 break; | |
71 case relocInfo::poll_type: | |
72 case relocInfo::poll_return_type: | |
73 _rspec = Relocation::spec_simple(rtype); | |
74 break; | |
75 case relocInfo::none: | |
76 break; | |
77 default: | |
78 ShouldNotReachHere(); | |
79 break; | |
80 } | |
81 } | |
82 | |
83 // Implementation of Address | |
84 | |
304 | 85 #ifdef _LP64 |
86 | |
0 | 87 Address Address::make_array(ArrayAddress adr) { |
88 // Not implementable on 64bit machines | |
89 // Should have been handled higher up the call chain. | |
90 ShouldNotReachHere(); | |
304 | 91 return Address(); |
92 } | |
93 | |
94 // exceedingly dangerous constructor | |
95 Address::Address(int disp, address loc, relocInfo::relocType rtype) { | |
96 _base = noreg; | |
97 _index = noreg; | |
98 _scale = no_scale; | |
99 _disp = disp; | |
100 switch (rtype) { | |
101 case relocInfo::external_word_type: | |
102 _rspec = external_word_Relocation::spec(loc); | |
103 break; | |
104 case relocInfo::internal_word_type: | |
105 _rspec = internal_word_Relocation::spec(loc); | |
106 break; | |
107 case relocInfo::runtime_call_type: | |
108 // HMM | |
109 _rspec = runtime_call_Relocation::spec(); | |
110 break; | |
111 case relocInfo::poll_type: | |
112 case relocInfo::poll_return_type: | |
113 _rspec = Relocation::spec_simple(rtype); | |
114 break; | |
115 case relocInfo::none: | |
116 break; | |
117 default: | |
118 ShouldNotReachHere(); | |
119 } | |
120 } | |
121 #else // LP64 | |
122 | |
123 Address Address::make_array(ArrayAddress adr) { | |
0 | 124 AddressLiteral base = adr.base(); |
125 Address index = adr.index(); | |
126 assert(index._disp == 0, "must not have disp"); // maybe it can? | |
127 Address array(index._base, index._index, index._scale, (intptr_t) base.target()); | |
128 array._rspec = base._rspec; | |
129 return array; | |
304 | 130 } |
0 | 131 |
132 // exceedingly dangerous constructor | |
133 Address::Address(address loc, RelocationHolder spec) { | |
134 _base = noreg; | |
135 _index = noreg; | |
136 _scale = no_scale; | |
137 _disp = (intptr_t) loc; | |
138 _rspec = spec; | |
139 } | |
304 | 140 |
0 | 141 #endif // _LP64 |
142 | |
304 | 143 |
144 | |
0 | 145 // Convert the raw encoding form into the form expected by the constructor for |
146 // Address. An index of 4 (rsp) corresponds to having no index, so convert | |
147 // that to noreg for the Address constructor. | |
624 | 148 Address Address::make_raw(int base, int index, int scale, int disp, bool disp_is_oop) { |
149 RelocationHolder rspec; | |
150 if (disp_is_oop) { | |
151 rspec = Relocation::spec_simple(relocInfo::oop_type); | |
152 } | |
0 | 153 bool valid_index = index != rsp->encoding(); |
154 if (valid_index) { | |
155 Address madr(as_Register(base), as_Register(index), (Address::ScaleFactor)scale, in_ByteSize(disp)); | |
624 | 156 madr._rspec = rspec; |
0 | 157 return madr; |
158 } else { | |
159 Address madr(as_Register(base), noreg, Address::no_scale, in_ByteSize(disp)); | |
624 | 160 madr._rspec = rspec; |
0 | 161 return madr; |
162 } | |
163 } | |
164 | |
165 // Implementation of Assembler | |
166 | |
167 int AbstractAssembler::code_fill_byte() { | |
168 return (u_char)'\xF4'; // hlt | |
169 } | |
170 | |
171 // make this go away someday | |
172 void Assembler::emit_data(jint data, relocInfo::relocType rtype, int format) { | |
173 if (rtype == relocInfo::none) | |
174 emit_long(data); | |
175 else emit_data(data, Relocation::spec_simple(rtype), format); | |
176 } | |
177 | |
178 void Assembler::emit_data(jint data, RelocationHolder const& rspec, int format) { | |
304 | 179 assert(imm_operand == 0, "default format must be immediate in this file"); |
0 | 180 assert(inst_mark() != NULL, "must be inside InstructionMark"); |
181 if (rspec.type() != relocInfo::none) { | |
182 #ifdef ASSERT | |
183 check_relocation(rspec, format); | |
184 #endif | |
185 // Do not use AbstractAssembler::relocate, which is not intended for | |
186 // embedded words. Instead, relocate to the enclosing instruction. | |
187 | |
188 // hack. call32 is too wide for mask so use disp32 | |
189 if (format == call32_operand) | |
190 code_section()->relocate(inst_mark(), rspec, disp32_operand); | |
191 else | |
192 code_section()->relocate(inst_mark(), rspec, format); | |
193 } | |
194 emit_long(data); | |
195 } | |
196 | |
304 | 197 static int encode(Register r) { |
198 int enc = r->encoding(); | |
199 if (enc >= 8) { | |
200 enc -= 8; | |
201 } | |
202 return enc; | |
203 } | |
204 | |
205 static int encode(XMMRegister r) { | |
206 int enc = r->encoding(); | |
207 if (enc >= 8) { | |
208 enc -= 8; | |
209 } | |
210 return enc; | |
211 } | |
0 | 212 |
213 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) { | |
214 assert(dst->has_byte_register(), "must have byte register"); | |
215 assert(isByte(op1) && isByte(op2), "wrong opcode"); | |
216 assert(isByte(imm8), "not a byte"); | |
217 assert((op1 & 0x01) == 0, "should be 8bit operation"); | |
218 emit_byte(op1); | |
304 | 219 emit_byte(op2 | encode(dst)); |
0 | 220 emit_byte(imm8); |
221 } | |
222 | |
223 | |
304 | 224 void Assembler::emit_arith(int op1, int op2, Register dst, int32_t imm32) { |
0 | 225 assert(isByte(op1) && isByte(op2), "wrong opcode"); |
226 assert((op1 & 0x01) == 1, "should be 32bit operation"); | |
227 assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); | |
228 if (is8bit(imm32)) { | |
229 emit_byte(op1 | 0x02); // set sign bit | |
304 | 230 emit_byte(op2 | encode(dst)); |
0 | 231 emit_byte(imm32 & 0xFF); |
232 } else { | |
233 emit_byte(op1); | |
304 | 234 emit_byte(op2 | encode(dst)); |
0 | 235 emit_long(imm32); |
236 } | |
237 } | |
238 | |
239 // immediate-to-memory forms | |
304 | 240 void Assembler::emit_arith_operand(int op1, Register rm, Address adr, int32_t imm32) { |
0 | 241 assert((op1 & 0x01) == 1, "should be 32bit operation"); |
242 assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); | |
243 if (is8bit(imm32)) { | |
244 emit_byte(op1 | 0x02); // set sign bit | |
304 | 245 emit_operand(rm, adr, 1); |
0 | 246 emit_byte(imm32 & 0xFF); |
247 } else { | |
248 emit_byte(op1); | |
304 | 249 emit_operand(rm, adr, 4); |
0 | 250 emit_long(imm32); |
251 } | |
252 } | |
253 | |
254 void Assembler::emit_arith(int op1, int op2, Register dst, jobject obj) { | |
304 | 255 LP64_ONLY(ShouldNotReachHere()); |
0 | 256 assert(isByte(op1) && isByte(op2), "wrong opcode"); |
257 assert((op1 & 0x01) == 1, "should be 32bit operation"); | |
258 assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); | |
259 InstructionMark im(this); | |
260 emit_byte(op1); | |
304 | 261 emit_byte(op2 | encode(dst)); |
262 emit_data((intptr_t)obj, relocInfo::oop_type, 0); | |
0 | 263 } |
264 | |
265 | |
266 void Assembler::emit_arith(int op1, int op2, Register dst, Register src) { | |
267 assert(isByte(op1) && isByte(op2), "wrong opcode"); | |
268 emit_byte(op1); | |
304 | 269 emit_byte(op2 | encode(dst) << 3 | encode(src)); |
270 } | |
271 | |
272 | |
273 void Assembler::emit_operand(Register reg, Register base, Register index, | |
274 Address::ScaleFactor scale, int disp, | |
275 RelocationHolder const& rspec, | |
276 int rip_relative_correction) { | |
0 | 277 relocInfo::relocType rtype = (relocInfo::relocType) rspec.type(); |
304 | 278 |
279 // Encode the registers as needed in the fields they are used in | |
280 | |
281 int regenc = encode(reg) << 3; | |
282 int indexenc = index->is_valid() ? encode(index) << 3 : 0; | |
283 int baseenc = base->is_valid() ? encode(base) : 0; | |
284 | |
0 | 285 if (base->is_valid()) { |
286 if (index->is_valid()) { | |
287 assert(scale != Address::no_scale, "inconsistent address"); | |
288 // [base + index*scale + disp] | |
304 | 289 if (disp == 0 && rtype == relocInfo::none && |
290 base != rbp LP64_ONLY(&& base != r13)) { | |
0 | 291 // [base + index*scale] |
292 // [00 reg 100][ss index base] | |
293 assert(index != rsp, "illegal addressing mode"); | |
304 | 294 emit_byte(0x04 | regenc); |
295 emit_byte(scale << 6 | indexenc | baseenc); | |
0 | 296 } else if (is8bit(disp) && rtype == relocInfo::none) { |
297 // [base + index*scale + imm8] | |
298 // [01 reg 100][ss index base] imm8 | |
299 assert(index != rsp, "illegal addressing mode"); | |
304 | 300 emit_byte(0x44 | regenc); |
301 emit_byte(scale << 6 | indexenc | baseenc); | |
0 | 302 emit_byte(disp & 0xFF); |
303 } else { | |
304 | 304 // [base + index*scale + disp32] |
305 // [10 reg 100][ss index base] disp32 | |
0 | 306 assert(index != rsp, "illegal addressing mode"); |
304 | 307 emit_byte(0x84 | regenc); |
308 emit_byte(scale << 6 | indexenc | baseenc); | |
0 | 309 emit_data(disp, rspec, disp32_operand); |
310 } | |
304 | 311 } else if (base == rsp LP64_ONLY(|| base == r12)) { |
312 // [rsp + disp] | |
0 | 313 if (disp == 0 && rtype == relocInfo::none) { |
304 | 314 // [rsp] |
0 | 315 // [00 reg 100][00 100 100] |
304 | 316 emit_byte(0x04 | regenc); |
0 | 317 emit_byte(0x24); |
318 } else if (is8bit(disp) && rtype == relocInfo::none) { | |
304 | 319 // [rsp + imm8] |
320 // [01 reg 100][00 100 100] disp8 | |
321 emit_byte(0x44 | regenc); | |
0 | 322 emit_byte(0x24); |
323 emit_byte(disp & 0xFF); | |
324 } else { | |
304 | 325 // [rsp + imm32] |
326 // [10 reg 100][00 100 100] disp32 | |
327 emit_byte(0x84 | regenc); | |
0 | 328 emit_byte(0x24); |
329 emit_data(disp, rspec, disp32_operand); | |
330 } | |
331 } else { | |
332 // [base + disp] | |
304 | 333 assert(base != rsp LP64_ONLY(&& base != r12), "illegal addressing mode"); |
334 if (disp == 0 && rtype == relocInfo::none && | |
335 base != rbp LP64_ONLY(&& base != r13)) { | |
0 | 336 // [base] |
337 // [00 reg base] | |
304 | 338 emit_byte(0x00 | regenc | baseenc); |
0 | 339 } else if (is8bit(disp) && rtype == relocInfo::none) { |
304 | 340 // [base + disp8] |
341 // [01 reg base] disp8 | |
342 emit_byte(0x40 | regenc | baseenc); | |
0 | 343 emit_byte(disp & 0xFF); |
344 } else { | |
304 | 345 // [base + disp32] |
346 // [10 reg base] disp32 | |
347 emit_byte(0x80 | regenc | baseenc); | |
0 | 348 emit_data(disp, rspec, disp32_operand); |
349 } | |
350 } | |
351 } else { | |
352 if (index->is_valid()) { | |
353 assert(scale != Address::no_scale, "inconsistent address"); | |
354 // [index*scale + disp] | |
304 | 355 // [00 reg 100][ss index 101] disp32 |
0 | 356 assert(index != rsp, "illegal addressing mode"); |
304 | 357 emit_byte(0x04 | regenc); |
358 emit_byte(scale << 6 | indexenc | 0x05); | |
0 | 359 emit_data(disp, rspec, disp32_operand); |
304 | 360 } else if (rtype != relocInfo::none ) { |
361 // [disp] (64bit) RIP-RELATIVE (32bit) abs | |
362 // [00 000 101] disp32 | |
363 | |
364 emit_byte(0x05 | regenc); | |
365 // Note that the RIP-rel. correction applies to the generated | |
366 // disp field, but _not_ to the target address in the rspec. | |
367 | |
368 // disp was created by converting the target address minus the pc | |
369 // at the start of the instruction. That needs more correction here. | |
370 // intptr_t disp = target - next_ip; | |
371 assert(inst_mark() != NULL, "must be inside InstructionMark"); | |
372 address next_ip = pc() + sizeof(int32_t) + rip_relative_correction; | |
373 int64_t adjusted = disp; | |
374 // Do rip-rel adjustment for 64bit | |
375 LP64_ONLY(adjusted -= (next_ip - inst_mark())); | |
376 assert(is_simm32(adjusted), | |
377 "must be 32bit offset (RIP relative address)"); | |
378 emit_data((int32_t) adjusted, rspec, disp32_operand); | |
379 | |
0 | 380 } else { |
304 | 381 // 32bit never did this, did everything as the rip-rel/disp code above |
382 // [disp] ABSOLUTE | |
383 // [00 reg 100][00 100 101] disp32 | |
384 emit_byte(0x04 | regenc); | |
385 emit_byte(0x25); | |
0 | 386 emit_data(disp, rspec, disp32_operand); |
387 } | |
388 } | |
389 } | |
390 | |
304 | 391 void Assembler::emit_operand(XMMRegister reg, Register base, Register index, |
392 Address::ScaleFactor scale, int disp, | |
393 RelocationHolder const& rspec) { | |
394 emit_operand((Register)reg, base, index, scale, disp, rspec); | |
395 } | |
396 | |
0 | 397 // Secret local extension to Assembler::WhichOperand: |
398 #define end_pc_operand (_WhichOperand_limit) | |
399 | |
400 address Assembler::locate_operand(address inst, WhichOperand which) { | |
401 // Decode the given instruction, and return the address of | |
402 // an embedded 32-bit operand word. | |
403 | |
404 // If "which" is disp32_operand, selects the displacement portion | |
405 // of an effective address specifier. | |
304 | 406 // If "which" is imm64_operand, selects the trailing immediate constant. |
0 | 407 // If "which" is call32_operand, selects the displacement of a call or jump. |
408 // Caller is responsible for ensuring that there is such an operand, | |
304 | 409 // and that it is 32/64 bits wide. |
0 | 410 |
411 // If "which" is end_pc_operand, find the end of the instruction. | |
412 | |
413 address ip = inst; | |
304 | 414 bool is_64bit = false; |
415 | |
416 debug_only(bool has_disp32 = false); | |
417 int tail_size = 0; // other random bytes (#32, #16, etc.) at end of insn | |
418 | |
419 again_after_prefix: | |
0 | 420 switch (0xFF & *ip++) { |
421 | |
422 // These convenience macros generate groups of "case" labels for the switch. | |
304 | 423 #define REP4(x) (x)+0: case (x)+1: case (x)+2: case (x)+3 |
424 #define REP8(x) (x)+0: case (x)+1: case (x)+2: case (x)+3: \ | |
0 | 425 case (x)+4: case (x)+5: case (x)+6: case (x)+7 |
304 | 426 #define REP16(x) REP8((x)+0): \ |
0 | 427 case REP8((x)+8) |
428 | |
429 case CS_segment: | |
430 case SS_segment: | |
431 case DS_segment: | |
432 case ES_segment: | |
433 case FS_segment: | |
434 case GS_segment: | |
304 | 435 // Seems dubious |
436 LP64_ONLY(assert(false, "shouldn't have that prefix")); | |
0 | 437 assert(ip == inst+1, "only one prefix allowed"); |
438 goto again_after_prefix; | |
439 | |
304 | 440 case 0x67: |
441 case REX: | |
442 case REX_B: | |
443 case REX_X: | |
444 case REX_XB: | |
445 case REX_R: | |
446 case REX_RB: | |
447 case REX_RX: | |
448 case REX_RXB: | |
449 NOT_LP64(assert(false, "64bit prefixes")); | |
450 goto again_after_prefix; | |
451 | |
452 case REX_W: | |
453 case REX_WB: | |
454 case REX_WX: | |
455 case REX_WXB: | |
456 case REX_WR: | |
457 case REX_WRB: | |
458 case REX_WRX: | |
459 case REX_WRXB: | |
460 NOT_LP64(assert(false, "64bit prefixes")); | |
461 is_64bit = true; | |
462 goto again_after_prefix; | |
463 | |
464 case 0xFF: // pushq a; decl a; incl a; call a; jmp a | |
0 | 465 case 0x88: // movb a, r |
466 case 0x89: // movl a, r | |
467 case 0x8A: // movb r, a | |
468 case 0x8B: // movl r, a | |
469 case 0x8F: // popl a | |
304 | 470 debug_only(has_disp32 = true); |
0 | 471 break; |
472 | |
304 | 473 case 0x68: // pushq #32 |
474 if (which == end_pc_operand) { | |
475 return ip + 4; | |
476 } | |
477 assert(which == imm_operand && !is_64bit, "pushl has no disp32 or 64bit immediate"); | |
0 | 478 return ip; // not produced by emit_operand |
479 | |
480 case 0x66: // movw ... (size prefix) | |
304 | 481 again_after_size_prefix2: |
0 | 482 switch (0xFF & *ip++) { |
304 | 483 case REX: |
484 case REX_B: | |
485 case REX_X: | |
486 case REX_XB: | |
487 case REX_R: | |
488 case REX_RB: | |
489 case REX_RX: | |
490 case REX_RXB: | |
491 case REX_W: | |
492 case REX_WB: | |
493 case REX_WX: | |
494 case REX_WXB: | |
495 case REX_WR: | |
496 case REX_WRB: | |
497 case REX_WRX: | |
498 case REX_WRXB: | |
499 NOT_LP64(assert(false, "64bit prefix found")); | |
500 goto again_after_size_prefix2; | |
0 | 501 case 0x8B: // movw r, a |
502 case 0x89: // movw a, r | |
304 | 503 debug_only(has_disp32 = true); |
0 | 504 break; |
505 case 0xC7: // movw a, #16 | |
304 | 506 debug_only(has_disp32 = true); |
0 | 507 tail_size = 2; // the imm16 |
508 break; | |
509 case 0x0F: // several SSE/SSE2 variants | |
510 ip--; // reparse the 0x0F | |
511 goto again_after_prefix; | |
512 default: | |
513 ShouldNotReachHere(); | |
514 } | |
515 break; | |
516 | |
304 | 517 case REP8(0xB8): // movl/q r, #32/#64(oop?) |
518 if (which == end_pc_operand) return ip + (is_64bit ? 8 : 4); | |
519 // these asserts are somewhat nonsensical | |
520 #ifndef _LP64 | |
521 assert(which == imm_operand || which == disp32_operand, ""); | |
522 #else | |
523 assert((which == call32_operand || which == imm_operand) && is_64bit || | |
524 which == narrow_oop_operand && !is_64bit, ""); | |
525 #endif // _LP64 | |
0 | 526 return ip; |
527 | |
528 case 0x69: // imul r, a, #32 | |
529 case 0xC7: // movl a, #32(oop?) | |
530 tail_size = 4; | |
304 | 531 debug_only(has_disp32 = true); // has both kinds of operands! |
0 | 532 break; |
533 | |
534 case 0x0F: // movx..., etc. | |
535 switch (0xFF & *ip++) { | |
536 case 0x12: // movlps | |
537 case 0x28: // movaps | |
538 case 0x2E: // ucomiss | |
539 case 0x2F: // comiss | |
540 case 0x54: // andps | |
541 case 0x55: // andnps | |
542 case 0x56: // orps | |
543 case 0x57: // xorps | |
544 case 0x6E: // movd | |
545 case 0x7E: // movd | |
546 case 0xAE: // ldmxcsr a | |
304 | 547 // 64bit side says it these have both operands but that doesn't |
548 // appear to be true | |
549 debug_only(has_disp32 = true); | |
0 | 550 break; |
551 | |
552 case 0xAD: // shrd r, a, %cl | |
553 case 0xAF: // imul r, a | |
304 | 554 case 0xBE: // movsbl r, a (movsxb) |
555 case 0xBF: // movswl r, a (movsxw) | |
556 case 0xB6: // movzbl r, a (movzxb) | |
557 case 0xB7: // movzwl r, a (movzxw) | |
0 | 558 case REP16(0x40): // cmovl cc, r, a |
559 case 0xB0: // cmpxchgb | |
560 case 0xB1: // cmpxchg | |
561 case 0xC1: // xaddl | |
562 case 0xC7: // cmpxchg8 | |
563 case REP16(0x90): // setcc a | |
304 | 564 debug_only(has_disp32 = true); |
0 | 565 // fall out of the switch to decode the address |
566 break; | |
304 | 567 |
0 | 568 case 0xAC: // shrd r, a, #8 |
304 | 569 debug_only(has_disp32 = true); |
0 | 570 tail_size = 1; // the imm8 |
571 break; | |
304 | 572 |
0 | 573 case REP16(0x80): // jcc rdisp32 |
574 if (which == end_pc_operand) return ip + 4; | |
304 | 575 assert(which == call32_operand, "jcc has no disp32 or imm"); |
0 | 576 return ip; |
577 default: | |
578 ShouldNotReachHere(); | |
579 } | |
580 break; | |
581 | |
582 case 0x81: // addl a, #32; addl r, #32 | |
583 // also: orl, adcl, sbbl, andl, subl, xorl, cmpl | |
304 | 584 // on 32bit in the case of cmpl, the imm might be an oop |
0 | 585 tail_size = 4; |
304 | 586 debug_only(has_disp32 = true); // has both kinds of operands! |
0 | 587 break; |
588 | |
589 case 0x83: // addl a, #8; addl r, #8 | |
590 // also: orl, adcl, sbbl, andl, subl, xorl, cmpl | |
304 | 591 debug_only(has_disp32 = true); // has both kinds of operands! |
0 | 592 tail_size = 1; |
593 break; | |
594 | |
595 case 0x9B: | |
596 switch (0xFF & *ip++) { | |
597 case 0xD9: // fnstcw a | |
304 | 598 debug_only(has_disp32 = true); |
0 | 599 break; |
600 default: | |
601 ShouldNotReachHere(); | |
602 } | |
603 break; | |
604 | |
605 case REP4(0x00): // addb a, r; addl a, r; addb r, a; addl r, a | |
606 case REP4(0x10): // adc... | |
607 case REP4(0x20): // and... | |
608 case REP4(0x30): // xor... | |
609 case REP4(0x08): // or... | |
610 case REP4(0x18): // sbb... | |
611 case REP4(0x28): // sub... | |
304 | 612 case 0xF7: // mull a |
613 case 0x8D: // lea r, a | |
614 case 0x87: // xchg r, a | |
0 | 615 case REP4(0x38): // cmp... |
304 | 616 case 0x85: // test r, a |
617 debug_only(has_disp32 = true); // has both kinds of operands! | |
0 | 618 break; |
619 | |
620 case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8 | |
621 case 0xC6: // movb a, #8 | |
622 case 0x80: // cmpb a, #8 | |
623 case 0x6B: // imul r, a, #8 | |
304 | 624 debug_only(has_disp32 = true); // has both kinds of operands! |
0 | 625 tail_size = 1; // the imm8 |
626 break; | |
627 | |
628 case 0xE8: // call rdisp32 | |
629 case 0xE9: // jmp rdisp32 | |
630 if (which == end_pc_operand) return ip + 4; | |
304 | 631 assert(which == call32_operand, "call has no disp32 or imm"); |
0 | 632 return ip; |
633 | |
634 case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1 | |
635 case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl | |
636 case 0xD9: // fld_s a; fst_s a; fstp_s a; fldcw a | |
637 case 0xDD: // fld_d a; fst_d a; fstp_d a | |
638 case 0xDB: // fild_s a; fistp_s a; fld_x a; fstp_x a | |
639 case 0xDF: // fild_d a; fistp_d a | |
640 case 0xD8: // fadd_s a; fsubr_s a; fmul_s a; fdivr_s a; fcomp_s a | |
641 case 0xDC: // fadd_d a; fsubr_d a; fmul_d a; fdivr_d a; fcomp_d a | |
642 case 0xDE: // faddp_d a; fsubrp_d a; fmulp_d a; fdivrp_d a; fcompp_d a | |
304 | 643 debug_only(has_disp32 = true); |
0 | 644 break; |
645 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
405
diff
changeset
|
646 case 0xF0: // Lock |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
405
diff
changeset
|
647 assert(os::is_MP(), "only on MP"); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
405
diff
changeset
|
648 goto again_after_prefix; |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
405
diff
changeset
|
649 |
0 | 650 case 0xF3: // For SSE |
651 case 0xF2: // For SSE2 | |
304 | 652 switch (0xFF & *ip++) { |
653 case REX: | |
654 case REX_B: | |
655 case REX_X: | |
656 case REX_XB: | |
657 case REX_R: | |
658 case REX_RB: | |
659 case REX_RX: | |
660 case REX_RXB: | |
661 case REX_W: | |
662 case REX_WB: | |
663 case REX_WX: | |
664 case REX_WXB: | |
665 case REX_WR: | |
666 case REX_WRB: | |
667 case REX_WRX: | |
668 case REX_WRXB: | |
669 NOT_LP64(assert(false, "found 64bit prefix")); | |
670 ip++; | |
671 default: | |
672 ip++; | |
673 } | |
674 debug_only(has_disp32 = true); // has both kinds of operands! | |
0 | 675 break; |
676 | |
677 default: | |
678 ShouldNotReachHere(); | |
679 | |
304 | 680 #undef REP8 |
681 #undef REP16 | |
0 | 682 } |
683 | |
684 assert(which != call32_operand, "instruction is not a call, jmp, or jcc"); | |
304 | 685 #ifdef _LP64 |
686 assert(which != imm_operand, "instruction is not a movq reg, imm64"); | |
687 #else | |
688 // assert(which != imm_operand || has_imm32, "instruction has no imm32 field"); | |
689 assert(which != imm_operand || has_disp32, "instruction has no imm32 field"); | |
690 #endif // LP64 | |
691 assert(which != disp32_operand || has_disp32, "instruction has no disp32 field"); | |
0 | 692 |
693 // parse the output of emit_operand | |
694 int op2 = 0xFF & *ip++; | |
695 int base = op2 & 0x07; | |
696 int op3 = -1; | |
697 const int b100 = 4; | |
698 const int b101 = 5; | |
699 if (base == b100 && (op2 >> 6) != 3) { | |
700 op3 = 0xFF & *ip++; | |
701 base = op3 & 0x07; // refetch the base | |
702 } | |
703 // now ip points at the disp (if any) | |
704 | |
705 switch (op2 >> 6) { | |
706 case 0: | |
707 // [00 reg 100][ss index base] | |
304 | 708 // [00 reg 100][00 100 esp] |
0 | 709 // [00 reg base] |
710 // [00 reg 100][ss index 101][disp32] | |
711 // [00 reg 101] [disp32] | |
712 | |
713 if (base == b101) { | |
714 if (which == disp32_operand) | |
715 return ip; // caller wants the disp32 | |
716 ip += 4; // skip the disp32 | |
717 } | |
718 break; | |
719 | |
720 case 1: | |
721 // [01 reg 100][ss index base][disp8] | |
304 | 722 // [01 reg 100][00 100 esp][disp8] |
0 | 723 // [01 reg base] [disp8] |
724 ip += 1; // skip the disp8 | |
725 break; | |
726 | |
727 case 2: | |
728 // [10 reg 100][ss index base][disp32] | |
304 | 729 // [10 reg 100][00 100 esp][disp32] |
0 | 730 // [10 reg base] [disp32] |
731 if (which == disp32_operand) | |
732 return ip; // caller wants the disp32 | |
733 ip += 4; // skip the disp32 | |
734 break; | |
735 | |
736 case 3: | |
737 // [11 reg base] (not a memory addressing mode) | |
738 break; | |
739 } | |
740 | |
741 if (which == end_pc_operand) { | |
742 return ip + tail_size; | |
743 } | |
744 | |
304 | 745 #ifdef _LP64 |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
746 assert(which == narrow_oop_operand && !is_64bit, "instruction is not a movl adr, imm32"); |
304 | 747 #else |
748 assert(which == imm_operand, "instruction has only an imm field"); | |
749 #endif // LP64 | |
0 | 750 return ip; |
751 } | |
752 | |
753 address Assembler::locate_next_instruction(address inst) { | |
754 // Secretly share code with locate_operand: | |
755 return locate_operand(inst, end_pc_operand); | |
756 } | |
757 | |
758 | |
759 #ifdef ASSERT | |
760 void Assembler::check_relocation(RelocationHolder const& rspec, int format) { | |
761 address inst = inst_mark(); | |
762 assert(inst != NULL && inst < pc(), "must point to beginning of instruction"); | |
763 address opnd; | |
764 | |
765 Relocation* r = rspec.reloc(); | |
766 if (r->type() == relocInfo::none) { | |
767 return; | |
768 } else if (r->is_call() || format == call32_operand) { | |
769 // assert(format == imm32_operand, "cannot specify a nonzero format"); | |
770 opnd = locate_operand(inst, call32_operand); | |
771 } else if (r->is_data()) { | |
304 | 772 assert(format == imm_operand || format == disp32_operand |
773 LP64_ONLY(|| format == narrow_oop_operand), "format ok"); | |
0 | 774 opnd = locate_operand(inst, (WhichOperand)format); |
775 } else { | |
304 | 776 assert(format == imm_operand, "cannot specify a format"); |
0 | 777 return; |
778 } | |
779 assert(opnd == pc(), "must put operand where relocs can find it"); | |
780 } | |
304 | 781 #endif // ASSERT |
782 | |
783 void Assembler::emit_operand32(Register reg, Address adr) { | |
784 assert(reg->encoding() < 8, "no extended registers"); | |
785 assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers"); | |
786 emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp, | |
787 adr._rspec); | |
788 } | |
789 | |
790 void Assembler::emit_operand(Register reg, Address adr, | |
791 int rip_relative_correction) { | |
792 emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp, | |
793 adr._rspec, | |
794 rip_relative_correction); | |
795 } | |
796 | |
797 void Assembler::emit_operand(XMMRegister reg, Address adr) { | |
798 emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp, | |
799 adr._rspec); | |
800 } | |
801 | |
802 // MMX operations | |
803 void Assembler::emit_operand(MMXRegister reg, Address adr) { | |
804 assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers"); | |
805 emit_operand((Register)reg, adr._base, adr._index, adr._scale, adr._disp, adr._rspec); | |
806 } | |
807 | |
808 // work around gcc (3.2.1-7a) bug | |
809 void Assembler::emit_operand(Address adr, MMXRegister reg) { | |
810 assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers"); | |
811 emit_operand((Register)reg, adr._base, adr._index, adr._scale, adr._disp, adr._rspec); | |
0 | 812 } |
813 | |
814 | |
815 void Assembler::emit_farith(int b1, int b2, int i) { | |
816 assert(isByte(b1) && isByte(b2), "wrong opcode"); | |
817 assert(0 <= i && i < 8, "illegal stack offset"); | |
818 emit_byte(b1); | |
819 emit_byte(b2 + i); | |
820 } | |
821 | |
822 | |
304 | 823 // Now the Assembler instruction (identical for 32/64 bits) |
824 | |
825 void Assembler::adcl(Register dst, int32_t imm32) { | |
826 prefix(dst); | |
0 | 827 emit_arith(0x81, 0xD0, dst, imm32); |
828 } | |
829 | |
830 void Assembler::adcl(Register dst, Address src) { | |
831 InstructionMark im(this); | |
304 | 832 prefix(src, dst); |
0 | 833 emit_byte(0x13); |
834 emit_operand(dst, src); | |
835 } | |
836 | |
837 void Assembler::adcl(Register dst, Register src) { | |
304 | 838 (void) prefix_and_encode(dst->encoding(), src->encoding()); |
0 | 839 emit_arith(0x13, 0xC0, dst, src); |
840 } | |
841 | |
304 | 842 void Assembler::addl(Address dst, int32_t imm32) { |
843 InstructionMark im(this); | |
844 prefix(dst); | |
845 emit_arith_operand(0x81, rax, dst, imm32); | |
846 } | |
0 | 847 |
848 void Assembler::addl(Address dst, Register src) { | |
849 InstructionMark im(this); | |
304 | 850 prefix(dst, src); |
0 | 851 emit_byte(0x01); |
852 emit_operand(src, dst); | |
853 } | |
854 | |
304 | 855 void Assembler::addl(Register dst, int32_t imm32) { |
856 prefix(dst); | |
0 | 857 emit_arith(0x81, 0xC0, dst, imm32); |
858 } | |
859 | |
860 void Assembler::addl(Register dst, Address src) { | |
861 InstructionMark im(this); | |
304 | 862 prefix(src, dst); |
0 | 863 emit_byte(0x03); |
864 emit_operand(dst, src); | |
865 } | |
866 | |
867 void Assembler::addl(Register dst, Register src) { | |
304 | 868 (void) prefix_and_encode(dst->encoding(), src->encoding()); |
0 | 869 emit_arith(0x03, 0xC0, dst, src); |
870 } | |
871 | |
872 void Assembler::addr_nop_4() { | |
873 // 4 bytes: NOP DWORD PTR [EAX+0] | |
874 emit_byte(0x0F); | |
875 emit_byte(0x1F); | |
876 emit_byte(0x40); // emit_rm(cbuf, 0x1, EAX_enc, EAX_enc); | |
877 emit_byte(0); // 8-bits offset (1 byte) | |
878 } | |
879 | |
880 void Assembler::addr_nop_5() { | |
881 // 5 bytes: NOP DWORD PTR [EAX+EAX*0+0] 8-bits offset | |
882 emit_byte(0x0F); | |
883 emit_byte(0x1F); | |
884 emit_byte(0x44); // emit_rm(cbuf, 0x1, EAX_enc, 0x4); | |
885 emit_byte(0x00); // emit_rm(cbuf, 0x0, EAX_enc, EAX_enc); | |
886 emit_byte(0); // 8-bits offset (1 byte) | |
887 } | |
888 | |
889 void Assembler::addr_nop_7() { | |
890 // 7 bytes: NOP DWORD PTR [EAX+0] 32-bits offset | |
891 emit_byte(0x0F); | |
892 emit_byte(0x1F); | |
893 emit_byte(0x80); // emit_rm(cbuf, 0x2, EAX_enc, EAX_enc); | |
894 emit_long(0); // 32-bits offset (4 bytes) | |
895 } | |
896 | |
897 void Assembler::addr_nop_8() { | |
898 // 8 bytes: NOP DWORD PTR [EAX+EAX*0+0] 32-bits offset | |
899 emit_byte(0x0F); | |
900 emit_byte(0x1F); | |
901 emit_byte(0x84); // emit_rm(cbuf, 0x2, EAX_enc, 0x4); | |
902 emit_byte(0x00); // emit_rm(cbuf, 0x0, EAX_enc, EAX_enc); | |
903 emit_long(0); // 32-bits offset (4 bytes) | |
904 } | |
905 | |
304 | 906 void Assembler::addsd(XMMRegister dst, XMMRegister src) { |
907 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
908 emit_byte(0xF2); | |
909 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
910 emit_byte(0x0F); | |
911 emit_byte(0x58); | |
912 emit_byte(0xC0 | encode); | |
913 } | |
914 | |
915 void Assembler::addsd(XMMRegister dst, Address src) { | |
916 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
917 InstructionMark im(this); | |
918 emit_byte(0xF2); | |
919 prefix(src, dst); | |
920 emit_byte(0x0F); | |
921 emit_byte(0x58); | |
922 emit_operand(dst, src); | |
923 } | |
924 | |
925 void Assembler::addss(XMMRegister dst, XMMRegister src) { | |
926 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
927 emit_byte(0xF3); | |
928 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
929 emit_byte(0x0F); | |
930 emit_byte(0x58); | |
931 emit_byte(0xC0 | encode); | |
932 } | |
933 | |
934 void Assembler::addss(XMMRegister dst, Address src) { | |
935 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
936 InstructionMark im(this); | |
937 emit_byte(0xF3); | |
938 prefix(src, dst); | |
939 emit_byte(0x0F); | |
940 emit_byte(0x58); | |
941 emit_operand(dst, src); | |
942 } | |
943 | |
944 void Assembler::andl(Register dst, int32_t imm32) { | |
945 prefix(dst); | |
946 emit_arith(0x81, 0xE0, dst, imm32); | |
947 } | |
948 | |
949 void Assembler::andl(Register dst, Address src) { | |
950 InstructionMark im(this); | |
951 prefix(src, dst); | |
952 emit_byte(0x23); | |
953 emit_operand(dst, src); | |
954 } | |
955 | |
956 void Assembler::andl(Register dst, Register src) { | |
957 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
958 emit_arith(0x23, 0xC0, dst, src); | |
959 } | |
960 | |
961 void Assembler::andpd(XMMRegister dst, Address src) { | |
962 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
963 InstructionMark im(this); | |
964 emit_byte(0x66); | |
965 prefix(src, dst); | |
966 emit_byte(0x0F); | |
967 emit_byte(0x54); | |
968 emit_operand(dst, src); | |
969 } | |
970 | |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
971 void Assembler::bsfl(Register dst, Register src) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
972 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
973 emit_byte(0x0F); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
974 emit_byte(0xBC); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
975 emit_byte(0xC0 | encode); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
976 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
977 |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
978 void Assembler::bsrl(Register dst, Register src) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
979 assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT"); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
980 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
981 emit_byte(0x0F); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
982 emit_byte(0xBD); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
983 emit_byte(0xC0 | encode); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
984 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
985 |
304 | 986 void Assembler::bswapl(Register reg) { // bswap |
987 int encode = prefix_and_encode(reg->encoding()); | |
988 emit_byte(0x0F); | |
989 emit_byte(0xC8 | encode); | |
990 } | |
991 | |
992 void Assembler::call(Label& L, relocInfo::relocType rtype) { | |
993 // suspect disp32 is always good | |
994 int operand = LP64_ONLY(disp32_operand) NOT_LP64(imm_operand); | |
995 | |
996 if (L.is_bound()) { | |
997 const int long_size = 5; | |
998 int offs = (int)( target(L) - pc() ); | |
999 assert(offs <= 0, "assembler error"); | |
1000 InstructionMark im(this); | |
1001 // 1110 1000 #32-bit disp | |
1002 emit_byte(0xE8); | |
1003 emit_data(offs - long_size, rtype, operand); | |
1004 } else { | |
1005 InstructionMark im(this); | |
1006 // 1110 1000 #32-bit disp | |
1007 L.add_patch_at(code(), locator()); | |
1008 | |
1009 emit_byte(0xE8); | |
1010 emit_data(int(0), rtype, operand); | |
1011 } | |
1012 } | |
1013 | |
1014 void Assembler::call(Register dst) { | |
1015 // This was originally using a 32bit register encoding | |
1016 // and surely we want 64bit! | |
1017 // this is a 32bit encoding but in 64bit mode the default | |
1018 // operand size is 64bit so there is no need for the | |
1019 // wide prefix. So prefix only happens if we use the | |
1020 // new registers. Much like push/pop. | |
1021 int x = offset(); | |
1022 // this may be true but dbx disassembles it as if it | |
1023 // were 32bits... | |
1024 // int encode = prefix_and_encode(dst->encoding()); | |
1025 // if (offset() != x) assert(dst->encoding() >= 8, "what?"); | |
1026 int encode = prefixq_and_encode(dst->encoding()); | |
1027 | |
1028 emit_byte(0xFF); | |
1029 emit_byte(0xD0 | encode); | |
1030 } | |
1031 | |
1032 | |
1033 void Assembler::call(Address adr) { | |
1034 InstructionMark im(this); | |
1035 prefix(adr); | |
1036 emit_byte(0xFF); | |
1037 emit_operand(rdx, adr); | |
1038 } | |
1039 | |
1040 void Assembler::call_literal(address entry, RelocationHolder const& rspec) { | |
1041 assert(entry != NULL, "call most probably wrong"); | |
1042 InstructionMark im(this); | |
1043 emit_byte(0xE8); | |
1044 intptr_t disp = entry - (_code_pos + sizeof(int32_t)); | |
1045 assert(is_simm32(disp), "must be 32bit offset (call2)"); | |
1046 // Technically, should use call32_operand, but this format is | |
1047 // implied by the fact that we're emitting a call instruction. | |
1048 | |
1049 int operand = LP64_ONLY(disp32_operand) NOT_LP64(call32_operand); | |
1050 emit_data((int) disp, rspec, operand); | |
1051 } | |
1052 | |
1053 void Assembler::cdql() { | |
1054 emit_byte(0x99); | |
1055 } | |
1056 | |
1057 void Assembler::cmovl(Condition cc, Register dst, Register src) { | |
1058 NOT_LP64(guarantee(VM_Version::supports_cmov(), "illegal instruction")); | |
1059 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1060 emit_byte(0x0F); | |
1061 emit_byte(0x40 | cc); | |
1062 emit_byte(0xC0 | encode); | |
1063 } | |
1064 | |
1065 | |
1066 void Assembler::cmovl(Condition cc, Register dst, Address src) { | |
1067 NOT_LP64(guarantee(VM_Version::supports_cmov(), "illegal instruction")); | |
1068 prefix(src, dst); | |
1069 emit_byte(0x0F); | |
1070 emit_byte(0x40 | cc); | |
1071 emit_operand(dst, src); | |
1072 } | |
1073 | |
1074 void Assembler::cmpb(Address dst, int imm8) { | |
1075 InstructionMark im(this); | |
1076 prefix(dst); | |
1077 emit_byte(0x80); | |
1078 emit_operand(rdi, dst, 1); | |
1079 emit_byte(imm8); | |
1080 } | |
1081 | |
1082 void Assembler::cmpl(Address dst, int32_t imm32) { | |
1083 InstructionMark im(this); | |
1084 prefix(dst); | |
1085 emit_byte(0x81); | |
1086 emit_operand(rdi, dst, 4); | |
1087 emit_long(imm32); | |
1088 } | |
1089 | |
1090 void Assembler::cmpl(Register dst, int32_t imm32) { | |
1091 prefix(dst); | |
1092 emit_arith(0x81, 0xF8, dst, imm32); | |
1093 } | |
1094 | |
1095 void Assembler::cmpl(Register dst, Register src) { | |
1096 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
1097 emit_arith(0x3B, 0xC0, dst, src); | |
1098 } | |
1099 | |
1100 | |
1101 void Assembler::cmpl(Register dst, Address src) { | |
1102 InstructionMark im(this); | |
1103 prefix(src, dst); | |
1104 emit_byte(0x3B); | |
1105 emit_operand(dst, src); | |
1106 } | |
1107 | |
1108 void Assembler::cmpw(Address dst, int imm16) { | |
1109 InstructionMark im(this); | |
1110 assert(!dst.base_needs_rex() && !dst.index_needs_rex(), "no extended registers"); | |
1111 emit_byte(0x66); | |
1112 emit_byte(0x81); | |
1113 emit_operand(rdi, dst, 2); | |
1114 emit_word(imm16); | |
1115 } | |
1116 | |
1117 // The 32-bit cmpxchg compares the value at adr with the contents of rax, | |
1118 // and stores reg into adr if so; otherwise, the value at adr is loaded into rax,. | |
1119 // The ZF is set if the compared values were equal, and cleared otherwise. | |
1120 void Assembler::cmpxchgl(Register reg, Address adr) { // cmpxchg | |
1121 if (Atomics & 2) { | |
1122 // caveat: no instructionmark, so this isn't relocatable. | |
1123 // Emit a synthetic, non-atomic, CAS equivalent. | |
1124 // Beware. The synthetic form sets all ICCs, not just ZF. | |
1125 // cmpxchg r,[m] is equivalent to rax, = CAS (m, rax, r) | |
1126 cmpl(rax, adr); | |
1127 movl(rax, adr); | |
1128 if (reg != rax) { | |
1129 Label L ; | |
1130 jcc(Assembler::notEqual, L); | |
1131 movl(adr, reg); | |
1132 bind(L); | |
1133 } | |
1134 } else { | |
1135 InstructionMark im(this); | |
1136 prefix(adr, reg); | |
1137 emit_byte(0x0F); | |
1138 emit_byte(0xB1); | |
1139 emit_operand(reg, adr); | |
1140 } | |
1141 } | |
1142 | |
1143 void Assembler::comisd(XMMRegister dst, Address src) { | |
1144 // NOTE: dbx seems to decode this as comiss even though the | |
1145 // 0x66 is there. Strangly ucomisd comes out correct | |
1146 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1147 emit_byte(0x66); | |
1148 comiss(dst, src); | |
1149 } | |
1150 | |
1151 void Assembler::comiss(XMMRegister dst, Address src) { | |
1152 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1153 | |
1154 InstructionMark im(this); | |
1155 prefix(src, dst); | |
1156 emit_byte(0x0F); | |
1157 emit_byte(0x2F); | |
1158 emit_operand(dst, src); | |
1159 } | |
1160 | |
1161 void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) { | |
1162 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1163 emit_byte(0xF3); | |
1164 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1165 emit_byte(0x0F); | |
1166 emit_byte(0xE6); | |
1167 emit_byte(0xC0 | encode); | |
1168 } | |
1169 | |
1170 void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) { | |
1171 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1172 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1173 emit_byte(0x0F); | |
1174 emit_byte(0x5B); | |
1175 emit_byte(0xC0 | encode); | |
1176 } | |
1177 | |
1178 void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { | |
1179 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1180 emit_byte(0xF2); | |
1181 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1182 emit_byte(0x0F); | |
1183 emit_byte(0x5A); | |
1184 emit_byte(0xC0 | encode); | |
1185 } | |
1186 | |
1187 void Assembler::cvtsi2sdl(XMMRegister dst, Register src) { | |
1188 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1189 emit_byte(0xF2); | |
1190 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1191 emit_byte(0x0F); | |
1192 emit_byte(0x2A); | |
1193 emit_byte(0xC0 | encode); | |
1194 } | |
1195 | |
1196 void Assembler::cvtsi2ssl(XMMRegister dst, Register src) { | |
1197 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1198 emit_byte(0xF3); | |
1199 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1200 emit_byte(0x0F); | |
1201 emit_byte(0x2A); | |
1202 emit_byte(0xC0 | encode); | |
1203 } | |
1204 | |
1205 void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { | |
1206 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1207 emit_byte(0xF3); | |
1208 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1209 emit_byte(0x0F); | |
1210 emit_byte(0x5A); | |
1211 emit_byte(0xC0 | encode); | |
1212 } | |
1213 | |
1214 void Assembler::cvttsd2sil(Register dst, XMMRegister src) { | |
1215 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1216 emit_byte(0xF2); | |
1217 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1218 emit_byte(0x0F); | |
1219 emit_byte(0x2C); | |
1220 emit_byte(0xC0 | encode); | |
1221 } | |
1222 | |
1223 void Assembler::cvttss2sil(Register dst, XMMRegister src) { | |
1224 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1225 emit_byte(0xF3); | |
1226 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1227 emit_byte(0x0F); | |
1228 emit_byte(0x2C); | |
1229 emit_byte(0xC0 | encode); | |
1230 } | |
1231 | |
1232 void Assembler::decl(Address dst) { | |
1233 // Don't use it directly. Use MacroAssembler::decrement() instead. | |
1234 InstructionMark im(this); | |
1235 prefix(dst); | |
1236 emit_byte(0xFF); | |
1237 emit_operand(rcx, dst); | |
1238 } | |
1239 | |
1240 void Assembler::divsd(XMMRegister dst, Address src) { | |
1241 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1242 InstructionMark im(this); | |
1243 emit_byte(0xF2); | |
1244 prefix(src, dst); | |
1245 emit_byte(0x0F); | |
1246 emit_byte(0x5E); | |
1247 emit_operand(dst, src); | |
1248 } | |
1249 | |
1250 void Assembler::divsd(XMMRegister dst, XMMRegister src) { | |
1251 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1252 emit_byte(0xF2); | |
1253 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1254 emit_byte(0x0F); | |
1255 emit_byte(0x5E); | |
1256 emit_byte(0xC0 | encode); | |
1257 } | |
1258 | |
1259 void Assembler::divss(XMMRegister dst, Address src) { | |
1260 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1261 InstructionMark im(this); | |
1262 emit_byte(0xF3); | |
1263 prefix(src, dst); | |
1264 emit_byte(0x0F); | |
1265 emit_byte(0x5E); | |
1266 emit_operand(dst, src); | |
1267 } | |
1268 | |
1269 void Assembler::divss(XMMRegister dst, XMMRegister src) { | |
1270 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1271 emit_byte(0xF3); | |
1272 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1273 emit_byte(0x0F); | |
1274 emit_byte(0x5E); | |
1275 emit_byte(0xC0 | encode); | |
1276 } | |
1277 | |
1278 void Assembler::emms() { | |
1279 NOT_LP64(assert(VM_Version::supports_mmx(), "")); | |
1280 emit_byte(0x0F); | |
1281 emit_byte(0x77); | |
1282 } | |
1283 | |
1284 void Assembler::hlt() { | |
1285 emit_byte(0xF4); | |
1286 } | |
1287 | |
1288 void Assembler::idivl(Register src) { | |
1289 int encode = prefix_and_encode(src->encoding()); | |
1290 emit_byte(0xF7); | |
1291 emit_byte(0xF8 | encode); | |
1292 } | |
1293 | |
1920 | 1294 void Assembler::divl(Register src) { // Unsigned |
1295 int encode = prefix_and_encode(src->encoding()); | |
1296 emit_byte(0xF7); | |
1297 emit_byte(0xF0 | encode); | |
1298 } | |
1299 | |
304 | 1300 void Assembler::imull(Register dst, Register src) { |
1301 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1302 emit_byte(0x0F); | |
1303 emit_byte(0xAF); | |
1304 emit_byte(0xC0 | encode); | |
1305 } | |
1306 | |
1307 | |
1308 void Assembler::imull(Register dst, Register src, int value) { | |
1309 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1310 if (is8bit(value)) { | |
1311 emit_byte(0x6B); | |
1312 emit_byte(0xC0 | encode); | |
1914
ae065c367d93
6987135: Performance regression on Intel platform with 32-bits edition between 6u13 and 6u14.
kvn
parents:
1846
diff
changeset
|
1313 emit_byte(value & 0xFF); |
304 | 1314 } else { |
1315 emit_byte(0x69); | |
1316 emit_byte(0xC0 | encode); | |
1317 emit_long(value); | |
1318 } | |
1319 } | |
1320 | |
1321 void Assembler::incl(Address dst) { | |
1322 // Don't use it directly. Use MacroAssembler::increment() instead. | |
1323 InstructionMark im(this); | |
1324 prefix(dst); | |
1325 emit_byte(0xFF); | |
1326 emit_operand(rax, dst); | |
1327 } | |
1328 | |
1329 void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) { | |
1330 InstructionMark im(this); | |
1331 relocate(rtype); | |
1332 assert((0 <= cc) && (cc < 16), "illegal cc"); | |
1333 if (L.is_bound()) { | |
1334 address dst = target(L); | |
1335 assert(dst != NULL, "jcc most probably wrong"); | |
1336 | |
1337 const int short_size = 2; | |
1338 const int long_size = 6; | |
1339 intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos; | |
1340 if (rtype == relocInfo::none && is8bit(offs - short_size)) { | |
1341 // 0111 tttn #8-bit disp | |
1342 emit_byte(0x70 | cc); | |
1343 emit_byte((offs - short_size) & 0xFF); | |
1344 } else { | |
1345 // 0000 1111 1000 tttn #32-bit disp | |
1346 assert(is_simm32(offs - long_size), | |
1347 "must be 32bit offset (call4)"); | |
1348 emit_byte(0x0F); | |
1349 emit_byte(0x80 | cc); | |
1350 emit_long(offs - long_size); | |
1351 } | |
1352 } else { | |
1353 // Note: could eliminate cond. jumps to this jump if condition | |
1354 // is the same however, seems to be rather unlikely case. | |
1355 // Note: use jccb() if label to be bound is very close to get | |
1356 // an 8-bit displacement | |
1357 L.add_patch_at(code(), locator()); | |
1358 emit_byte(0x0F); | |
1359 emit_byte(0x80 | cc); | |
1360 emit_long(0); | |
1361 } | |
1362 } | |
1363 | |
1364 void Assembler::jccb(Condition cc, Label& L) { | |
1365 if (L.is_bound()) { | |
1366 const int short_size = 2; | |
1367 address entry = target(L); | |
1368 assert(is8bit((intptr_t)entry - ((intptr_t)_code_pos + short_size)), | |
1369 "Dispacement too large for a short jmp"); | |
1370 intptr_t offs = (intptr_t)entry - (intptr_t)_code_pos; | |
1371 // 0111 tttn #8-bit disp | |
1372 emit_byte(0x70 | cc); | |
1373 emit_byte((offs - short_size) & 0xFF); | |
1374 } else { | |
1375 InstructionMark im(this); | |
1376 L.add_patch_at(code(), locator()); | |
1377 emit_byte(0x70 | cc); | |
1378 emit_byte(0); | |
1379 } | |
1380 } | |
1381 | |
1382 void Assembler::jmp(Address adr) { | |
1383 InstructionMark im(this); | |
1384 prefix(adr); | |
1385 emit_byte(0xFF); | |
1386 emit_operand(rsp, adr); | |
1387 } | |
1388 | |
1389 void Assembler::jmp(Label& L, relocInfo::relocType rtype) { | |
1390 if (L.is_bound()) { | |
1391 address entry = target(L); | |
1392 assert(entry != NULL, "jmp most probably wrong"); | |
1393 InstructionMark im(this); | |
1394 const int short_size = 2; | |
1395 const int long_size = 5; | |
1396 intptr_t offs = entry - _code_pos; | |
1397 if (rtype == relocInfo::none && is8bit(offs - short_size)) { | |
1398 emit_byte(0xEB); | |
1399 emit_byte((offs - short_size) & 0xFF); | |
1400 } else { | |
1401 emit_byte(0xE9); | |
1402 emit_long(offs - long_size); | |
1403 } | |
1404 } else { | |
1405 // By default, forward jumps are always 32-bit displacements, since | |
1406 // we can't yet know where the label will be bound. If you're sure that | |
1407 // the forward jump will not run beyond 256 bytes, use jmpb to | |
1408 // force an 8-bit displacement. | |
1409 InstructionMark im(this); | |
1410 relocate(rtype); | |
1411 L.add_patch_at(code(), locator()); | |
1412 emit_byte(0xE9); | |
1413 emit_long(0); | |
1414 } | |
1415 } | |
1416 | |
1417 void Assembler::jmp(Register entry) { | |
1418 int encode = prefix_and_encode(entry->encoding()); | |
1419 emit_byte(0xFF); | |
1420 emit_byte(0xE0 | encode); | |
1421 } | |
1422 | |
1423 void Assembler::jmp_literal(address dest, RelocationHolder const& rspec) { | |
1424 InstructionMark im(this); | |
1425 emit_byte(0xE9); | |
1426 assert(dest != NULL, "must have a target"); | |
1427 intptr_t disp = dest - (_code_pos + sizeof(int32_t)); | |
1428 assert(is_simm32(disp), "must be 32bit offset (jmp)"); | |
1429 emit_data(disp, rspec.reloc(), call32_operand); | |
1430 } | |
1431 | |
1432 void Assembler::jmpb(Label& L) { | |
1433 if (L.is_bound()) { | |
1434 const int short_size = 2; | |
1435 address entry = target(L); | |
1436 assert(is8bit((entry - _code_pos) + short_size), | |
1437 "Dispacement too large for a short jmp"); | |
1438 assert(entry != NULL, "jmp most probably wrong"); | |
1439 intptr_t offs = entry - _code_pos; | |
1440 emit_byte(0xEB); | |
1441 emit_byte((offs - short_size) & 0xFF); | |
1442 } else { | |
1443 InstructionMark im(this); | |
1444 L.add_patch_at(code(), locator()); | |
1445 emit_byte(0xEB); | |
1446 emit_byte(0); | |
1447 } | |
1448 } | |
1449 | |
1450 void Assembler::ldmxcsr( Address src) { | |
1451 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1452 InstructionMark im(this); | |
1453 prefix(src); | |
1454 emit_byte(0x0F); | |
1455 emit_byte(0xAE); | |
1456 emit_operand(as_Register(2), src); | |
1457 } | |
1458 | |
1459 void Assembler::leal(Register dst, Address src) { | |
1460 InstructionMark im(this); | |
1461 #ifdef _LP64 | |
1462 emit_byte(0x67); // addr32 | |
1463 prefix(src, dst); | |
1464 #endif // LP64 | |
1465 emit_byte(0x8D); | |
1466 emit_operand(dst, src); | |
1467 } | |
1468 | |
1469 void Assembler::lock() { | |
1470 if (Atomics & 1) { | |
1471 // Emit either nothing, a NOP, or a NOP: prefix | |
1472 emit_byte(0x90) ; | |
1473 } else { | |
1474 emit_byte(0xF0); | |
1475 } | |
1476 } | |
1477 | |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1478 void Assembler::lzcntl(Register dst, Register src) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1479 assert(VM_Version::supports_lzcnt(), "encoding is treated as BSR"); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1480 emit_byte(0xF3); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1481 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1482 emit_byte(0x0F); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1483 emit_byte(0xBD); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1484 emit_byte(0xC0 | encode); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1485 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
1486 |
671
d0994e5bebce
6822204: volatile fences should prefer lock:addl to actual mfence instructions
never
parents:
665
diff
changeset
|
1487 // Emit mfence instruction |
304 | 1488 void Assembler::mfence() { |
671
d0994e5bebce
6822204: volatile fences should prefer lock:addl to actual mfence instructions
never
parents:
665
diff
changeset
|
1489 NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");) |
d0994e5bebce
6822204: volatile fences should prefer lock:addl to actual mfence instructions
never
parents:
665
diff
changeset
|
1490 emit_byte( 0x0F ); |
d0994e5bebce
6822204: volatile fences should prefer lock:addl to actual mfence instructions
never
parents:
665
diff
changeset
|
1491 emit_byte( 0xAE ); |
d0994e5bebce
6822204: volatile fences should prefer lock:addl to actual mfence instructions
never
parents:
665
diff
changeset
|
1492 emit_byte( 0xF0 ); |
304 | 1493 } |
1494 | |
1495 void Assembler::mov(Register dst, Register src) { | |
1496 LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); | |
1497 } | |
1498 | |
1499 void Assembler::movapd(XMMRegister dst, XMMRegister src) { | |
1500 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1501 int dstenc = dst->encoding(); | |
1502 int srcenc = src->encoding(); | |
1503 emit_byte(0x66); | |
1504 if (dstenc < 8) { | |
1505 if (srcenc >= 8) { | |
1506 prefix(REX_B); | |
1507 srcenc -= 8; | |
1508 } | |
1509 } else { | |
1510 if (srcenc < 8) { | |
1511 prefix(REX_R); | |
1512 } else { | |
1513 prefix(REX_RB); | |
1514 srcenc -= 8; | |
1515 } | |
1516 dstenc -= 8; | |
1517 } | |
1518 emit_byte(0x0F); | |
1519 emit_byte(0x28); | |
1520 emit_byte(0xC0 | dstenc << 3 | srcenc); | |
1521 } | |
1522 | |
1523 void Assembler::movaps(XMMRegister dst, XMMRegister src) { | |
1524 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1525 int dstenc = dst->encoding(); | |
1526 int srcenc = src->encoding(); | |
1527 if (dstenc < 8) { | |
1528 if (srcenc >= 8) { | |
1529 prefix(REX_B); | |
1530 srcenc -= 8; | |
1531 } | |
1532 } else { | |
1533 if (srcenc < 8) { | |
1534 prefix(REX_R); | |
1535 } else { | |
1536 prefix(REX_RB); | |
1537 srcenc -= 8; | |
1538 } | |
1539 dstenc -= 8; | |
1540 } | |
1541 emit_byte(0x0F); | |
1542 emit_byte(0x28); | |
1543 emit_byte(0xC0 | dstenc << 3 | srcenc); | |
1544 } | |
1545 | |
1546 void Assembler::movb(Register dst, Address src) { | |
1547 NOT_LP64(assert(dst->has_byte_register(), "must have byte register")); | |
1548 InstructionMark im(this); | |
1549 prefix(src, dst, true); | |
1550 emit_byte(0x8A); | |
1551 emit_operand(dst, src); | |
1552 } | |
1553 | |
1554 | |
1555 void Assembler::movb(Address dst, int imm8) { | |
1556 InstructionMark im(this); | |
1557 prefix(dst); | |
1558 emit_byte(0xC6); | |
1559 emit_operand(rax, dst, 1); | |
1560 emit_byte(imm8); | |
1561 } | |
1562 | |
1563 | |
1564 void Assembler::movb(Address dst, Register src) { | |
1565 assert(src->has_byte_register(), "must have byte register"); | |
1566 InstructionMark im(this); | |
1567 prefix(dst, src, true); | |
1568 emit_byte(0x88); | |
1569 emit_operand(src, dst); | |
1570 } | |
1571 | |
1572 void Assembler::movdl(XMMRegister dst, Register src) { | |
1573 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1574 emit_byte(0x66); | |
1575 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1576 emit_byte(0x0F); | |
1577 emit_byte(0x6E); | |
1578 emit_byte(0xC0 | encode); | |
1579 } | |
1580 | |
1581 void Assembler::movdl(Register dst, XMMRegister src) { | |
1582 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1583 emit_byte(0x66); | |
1584 // swap src/dst to get correct prefix | |
1585 int encode = prefix_and_encode(src->encoding(), dst->encoding()); | |
1586 emit_byte(0x0F); | |
1587 emit_byte(0x7E); | |
1588 emit_byte(0xC0 | encode); | |
1589 } | |
1590 | |
1591 void Assembler::movdqa(XMMRegister dst, Address src) { | |
1592 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1593 InstructionMark im(this); | |
1594 emit_byte(0x66); | |
1595 prefix(src, dst); | |
1596 emit_byte(0x0F); | |
1597 emit_byte(0x6F); | |
1598 emit_operand(dst, src); | |
1599 } | |
1600 | |
1601 void Assembler::movdqa(XMMRegister dst, XMMRegister src) { | |
1602 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1603 emit_byte(0x66); | |
1604 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
1605 emit_byte(0x0F); | |
1606 emit_byte(0x6F); | |
1607 emit_byte(0xC0 | encode); | |
1608 } | |
1609 | |
1610 void Assembler::movdqa(Address dst, XMMRegister src) { | |
1611 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1612 InstructionMark im(this); | |
1613 emit_byte(0x66); | |
1614 prefix(dst, src); | |
1615 emit_byte(0x0F); | |
1616 emit_byte(0x7F); | |
1617 emit_operand(src, dst); | |
1618 } | |
1619 | |
405 | 1620 void Assembler::movdqu(XMMRegister dst, Address src) { |
1621 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1622 InstructionMark im(this); | |
1623 emit_byte(0xF3); | |
1624 prefix(src, dst); | |
1625 emit_byte(0x0F); | |
1626 emit_byte(0x6F); | |
1627 emit_operand(dst, src); | |
1628 } | |
1629 | |
1630 void Assembler::movdqu(XMMRegister dst, XMMRegister src) { | |
1631 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1632 emit_byte(0xF3); | |
1633 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
1634 emit_byte(0x0F); | |
1635 emit_byte(0x6F); | |
1636 emit_byte(0xC0 | encode); | |
1637 } | |
1638 | |
1639 void Assembler::movdqu(Address dst, XMMRegister src) { | |
1640 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1641 InstructionMark im(this); | |
1642 emit_byte(0xF3); | |
1643 prefix(dst, src); | |
1644 emit_byte(0x0F); | |
1645 emit_byte(0x7F); | |
1646 emit_operand(src, dst); | |
1647 } | |
1648 | |
304 | 1649 // Uses zero extension on 64bit |
1650 | |
1651 void Assembler::movl(Register dst, int32_t imm32) { | |
1652 int encode = prefix_and_encode(dst->encoding()); | |
1653 emit_byte(0xB8 | encode); | |
1654 emit_long(imm32); | |
1655 } | |
1656 | |
1657 void Assembler::movl(Register dst, Register src) { | |
1658 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1659 emit_byte(0x8B); | |
1660 emit_byte(0xC0 | encode); | |
1661 } | |
1662 | |
1663 void Assembler::movl(Register dst, Address src) { | |
1664 InstructionMark im(this); | |
1665 prefix(src, dst); | |
1666 emit_byte(0x8B); | |
1667 emit_operand(dst, src); | |
1668 } | |
1669 | |
1670 void Assembler::movl(Address dst, int32_t imm32) { | |
1671 InstructionMark im(this); | |
1672 prefix(dst); | |
1673 emit_byte(0xC7); | |
1674 emit_operand(rax, dst, 4); | |
1675 emit_long(imm32); | |
1676 } | |
1677 | |
1678 void Assembler::movl(Address dst, Register src) { | |
1679 InstructionMark im(this); | |
1680 prefix(dst, src); | |
1681 emit_byte(0x89); | |
1682 emit_operand(src, dst); | |
1683 } | |
1684 | |
1685 // New cpus require to use movsd and movss to avoid partial register stall | |
1686 // when loading from memory. But for old Opteron use movlpd instead of movsd. | |
1687 // The selection is done in MacroAssembler::movdbl() and movflt(). | |
1688 void Assembler::movlpd(XMMRegister dst, Address src) { | |
1689 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1690 InstructionMark im(this); | |
1691 emit_byte(0x66); | |
1692 prefix(src, dst); | |
1693 emit_byte(0x0F); | |
1694 emit_byte(0x12); | |
1695 emit_operand(dst, src); | |
1696 } | |
1697 | |
1698 void Assembler::movq( MMXRegister dst, Address src ) { | |
1699 assert( VM_Version::supports_mmx(), "" ); | |
1700 emit_byte(0x0F); | |
1701 emit_byte(0x6F); | |
1702 emit_operand(dst, src); | |
1703 } | |
1704 | |
1705 void Assembler::movq( Address dst, MMXRegister src ) { | |
1706 assert( VM_Version::supports_mmx(), "" ); | |
1707 emit_byte(0x0F); | |
1708 emit_byte(0x7F); | |
1709 // workaround gcc (3.2.1-7a) bug | |
1710 // In that version of gcc with only an emit_operand(MMX, Address) | |
1711 // gcc will tail jump and try and reverse the parameters completely | |
1712 // obliterating dst in the process. By having a version available | |
1713 // that doesn't need to swap the args at the tail jump the bug is | |
1714 // avoided. | |
1715 emit_operand(dst, src); | |
1716 } | |
1717 | |
1718 void Assembler::movq(XMMRegister dst, Address src) { | |
1719 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1720 InstructionMark im(this); | |
1721 emit_byte(0xF3); | |
1722 prefix(src, dst); | |
1723 emit_byte(0x0F); | |
1724 emit_byte(0x7E); | |
1725 emit_operand(dst, src); | |
1726 } | |
1727 | |
1728 void Assembler::movq(Address dst, XMMRegister src) { | |
1729 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1730 InstructionMark im(this); | |
1731 emit_byte(0x66); | |
1732 prefix(dst, src); | |
1733 emit_byte(0x0F); | |
1734 emit_byte(0xD6); | |
1735 emit_operand(src, dst); | |
1736 } | |
1737 | |
1738 void Assembler::movsbl(Register dst, Address src) { // movsxb | |
1739 InstructionMark im(this); | |
1740 prefix(src, dst); | |
1741 emit_byte(0x0F); | |
1742 emit_byte(0xBE); | |
1743 emit_operand(dst, src); | |
1744 } | |
1745 | |
1746 void Assembler::movsbl(Register dst, Register src) { // movsxb | |
1747 NOT_LP64(assert(src->has_byte_register(), "must have byte register")); | |
1748 int encode = prefix_and_encode(dst->encoding(), src->encoding(), true); | |
1749 emit_byte(0x0F); | |
1750 emit_byte(0xBE); | |
1751 emit_byte(0xC0 | encode); | |
1752 } | |
1753 | |
1754 void Assembler::movsd(XMMRegister dst, XMMRegister src) { | |
1755 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1756 emit_byte(0xF2); | |
1757 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1758 emit_byte(0x0F); | |
1759 emit_byte(0x10); | |
1760 emit_byte(0xC0 | encode); | |
1761 } | |
1762 | |
1763 void Assembler::movsd(XMMRegister dst, Address src) { | |
1764 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1765 InstructionMark im(this); | |
1766 emit_byte(0xF2); | |
1767 prefix(src, dst); | |
1768 emit_byte(0x0F); | |
1769 emit_byte(0x10); | |
1770 emit_operand(dst, src); | |
1771 } | |
1772 | |
1773 void Assembler::movsd(Address dst, XMMRegister src) { | |
1774 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1775 InstructionMark im(this); | |
1776 emit_byte(0xF2); | |
1777 prefix(dst, src); | |
1778 emit_byte(0x0F); | |
1779 emit_byte(0x11); | |
1780 emit_operand(src, dst); | |
1781 } | |
1782 | |
1783 void Assembler::movss(XMMRegister dst, XMMRegister src) { | |
1784 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1785 emit_byte(0xF3); | |
1786 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1787 emit_byte(0x0F); | |
1788 emit_byte(0x10); | |
1789 emit_byte(0xC0 | encode); | |
1790 } | |
1791 | |
1792 void Assembler::movss(XMMRegister dst, Address src) { | |
1793 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1794 InstructionMark im(this); | |
1795 emit_byte(0xF3); | |
1796 prefix(src, dst); | |
1797 emit_byte(0x0F); | |
1798 emit_byte(0x10); | |
1799 emit_operand(dst, src); | |
1800 } | |
1801 | |
1802 void Assembler::movss(Address dst, XMMRegister src) { | |
1803 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1804 InstructionMark im(this); | |
1805 emit_byte(0xF3); | |
1806 prefix(dst, src); | |
1807 emit_byte(0x0F); | |
1808 emit_byte(0x11); | |
1809 emit_operand(src, dst); | |
1810 } | |
1811 | |
1812 void Assembler::movswl(Register dst, Address src) { // movsxw | |
1813 InstructionMark im(this); | |
1814 prefix(src, dst); | |
1815 emit_byte(0x0F); | |
1816 emit_byte(0xBF); | |
1817 emit_operand(dst, src); | |
1818 } | |
1819 | |
1820 void Assembler::movswl(Register dst, Register src) { // movsxw | |
1821 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1822 emit_byte(0x0F); | |
1823 emit_byte(0xBF); | |
1824 emit_byte(0xC0 | encode); | |
1825 } | |
1826 | |
1827 void Assembler::movw(Address dst, int imm16) { | |
1828 InstructionMark im(this); | |
1829 | |
1830 emit_byte(0x66); // switch to 16-bit mode | |
1831 prefix(dst); | |
1832 emit_byte(0xC7); | |
1833 emit_operand(rax, dst, 2); | |
1834 emit_word(imm16); | |
1835 } | |
1836 | |
1837 void Assembler::movw(Register dst, Address src) { | |
1838 InstructionMark im(this); | |
1839 emit_byte(0x66); | |
1840 prefix(src, dst); | |
1841 emit_byte(0x8B); | |
1842 emit_operand(dst, src); | |
1843 } | |
1844 | |
1845 void Assembler::movw(Address dst, Register src) { | |
1846 InstructionMark im(this); | |
1847 emit_byte(0x66); | |
1848 prefix(dst, src); | |
1849 emit_byte(0x89); | |
1850 emit_operand(src, dst); | |
1851 } | |
1852 | |
1853 void Assembler::movzbl(Register dst, Address src) { // movzxb | |
1854 InstructionMark im(this); | |
1855 prefix(src, dst); | |
1856 emit_byte(0x0F); | |
1857 emit_byte(0xB6); | |
1858 emit_operand(dst, src); | |
1859 } | |
1860 | |
1861 void Assembler::movzbl(Register dst, Register src) { // movzxb | |
1862 NOT_LP64(assert(src->has_byte_register(), "must have byte register")); | |
1863 int encode = prefix_and_encode(dst->encoding(), src->encoding(), true); | |
1864 emit_byte(0x0F); | |
1865 emit_byte(0xB6); | |
1866 emit_byte(0xC0 | encode); | |
1867 } | |
1868 | |
1869 void Assembler::movzwl(Register dst, Address src) { // movzxw | |
1870 InstructionMark im(this); | |
1871 prefix(src, dst); | |
1872 emit_byte(0x0F); | |
1873 emit_byte(0xB7); | |
1874 emit_operand(dst, src); | |
1875 } | |
1876 | |
1877 void Assembler::movzwl(Register dst, Register src) { // movzxw | |
1878 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1879 emit_byte(0x0F); | |
1880 emit_byte(0xB7); | |
1881 emit_byte(0xC0 | encode); | |
1882 } | |
1883 | |
1884 void Assembler::mull(Address src) { | |
1885 InstructionMark im(this); | |
1886 prefix(src); | |
1887 emit_byte(0xF7); | |
1888 emit_operand(rsp, src); | |
1889 } | |
1890 | |
1891 void Assembler::mull(Register src) { | |
1892 int encode = prefix_and_encode(src->encoding()); | |
1893 emit_byte(0xF7); | |
1894 emit_byte(0xE0 | encode); | |
1895 } | |
1896 | |
1897 void Assembler::mulsd(XMMRegister dst, Address src) { | |
1898 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1899 InstructionMark im(this); | |
1900 emit_byte(0xF2); | |
1901 prefix(src, dst); | |
1902 emit_byte(0x0F); | |
1903 emit_byte(0x59); | |
1904 emit_operand(dst, src); | |
1905 } | |
1906 | |
1907 void Assembler::mulsd(XMMRegister dst, XMMRegister src) { | |
1908 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
1909 emit_byte(0xF2); | |
1910 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1911 emit_byte(0x0F); | |
1912 emit_byte(0x59); | |
1913 emit_byte(0xC0 | encode); | |
1914 } | |
1915 | |
1916 void Assembler::mulss(XMMRegister dst, Address src) { | |
1917 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1918 InstructionMark im(this); | |
1919 emit_byte(0xF3); | |
1920 prefix(src, dst); | |
1921 emit_byte(0x0F); | |
1922 emit_byte(0x59); | |
1923 emit_operand(dst, src); | |
1924 } | |
1925 | |
1926 void Assembler::mulss(XMMRegister dst, XMMRegister src) { | |
1927 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
1928 emit_byte(0xF3); | |
1929 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
1930 emit_byte(0x0F); | |
1931 emit_byte(0x59); | |
1932 emit_byte(0xC0 | encode); | |
1933 } | |
1934 | |
1935 void Assembler::negl(Register dst) { | |
1936 int encode = prefix_and_encode(dst->encoding()); | |
1937 emit_byte(0xF7); | |
1938 emit_byte(0xD8 | encode); | |
1939 } | |
1940 | |
0 | 1941 void Assembler::nop(int i) { |
304 | 1942 #ifdef ASSERT |
0 | 1943 assert(i > 0, " "); |
304 | 1944 // The fancy nops aren't currently recognized by debuggers making it a |
1945 // pain to disassemble code while debugging. If asserts are on clearly | |
1946 // speed is not an issue so simply use the single byte traditional nop | |
1947 // to do alignment. | |
1948 | |
1949 for (; i > 0 ; i--) emit_byte(0x90); | |
1950 return; | |
1951 | |
1952 #endif // ASSERT | |
1953 | |
0 | 1954 if (UseAddressNop && VM_Version::is_intel()) { |
1955 // | |
1956 // Using multi-bytes nops "0x0F 0x1F [address]" for Intel | |
1957 // 1: 0x90 | |
1958 // 2: 0x66 0x90 | |
1959 // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding) | |
1960 // 4: 0x0F 0x1F 0x40 0x00 | |
1961 // 5: 0x0F 0x1F 0x44 0x00 0x00 | |
1962 // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00 | |
1963 // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 | |
1964 // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
1965 // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
1966 // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
1967 // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
1968 | |
1969 // The rest coding is Intel specific - don't use consecutive address nops | |
1970 | |
1971 // 12: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90 | |
1972 // 13: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90 | |
1973 // 14: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90 | |
1974 // 15: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90 | |
1975 | |
1976 while(i >= 15) { | |
1977 // For Intel don't generate consecutive addess nops (mix with regular nops) | |
1978 i -= 15; | |
1979 emit_byte(0x66); // size prefix | |
1980 emit_byte(0x66); // size prefix | |
1981 emit_byte(0x66); // size prefix | |
1982 addr_nop_8(); | |
1983 emit_byte(0x66); // size prefix | |
1984 emit_byte(0x66); // size prefix | |
1985 emit_byte(0x66); // size prefix | |
1986 emit_byte(0x90); // nop | |
1987 } | |
1988 switch (i) { | |
1989 case 14: | |
1990 emit_byte(0x66); // size prefix | |
1991 case 13: | |
1992 emit_byte(0x66); // size prefix | |
1993 case 12: | |
1994 addr_nop_8(); | |
1995 emit_byte(0x66); // size prefix | |
1996 emit_byte(0x66); // size prefix | |
1997 emit_byte(0x66); // size prefix | |
1998 emit_byte(0x90); // nop | |
1999 break; | |
2000 case 11: | |
2001 emit_byte(0x66); // size prefix | |
2002 case 10: | |
2003 emit_byte(0x66); // size prefix | |
2004 case 9: | |
2005 emit_byte(0x66); // size prefix | |
2006 case 8: | |
2007 addr_nop_8(); | |
2008 break; | |
2009 case 7: | |
2010 addr_nop_7(); | |
2011 break; | |
2012 case 6: | |
2013 emit_byte(0x66); // size prefix | |
2014 case 5: | |
2015 addr_nop_5(); | |
2016 break; | |
2017 case 4: | |
2018 addr_nop_4(); | |
2019 break; | |
2020 case 3: | |
2021 // Don't use "0x0F 0x1F 0x00" - need patching safe padding | |
2022 emit_byte(0x66); // size prefix | |
2023 case 2: | |
2024 emit_byte(0x66); // size prefix | |
2025 case 1: | |
2026 emit_byte(0x90); // nop | |
2027 break; | |
2028 default: | |
2029 assert(i == 0, " "); | |
2030 } | |
2031 return; | |
2032 } | |
2033 if (UseAddressNop && VM_Version::is_amd()) { | |
2034 // | |
2035 // Using multi-bytes nops "0x0F 0x1F [address]" for AMD. | |
2036 // 1: 0x90 | |
2037 // 2: 0x66 0x90 | |
2038 // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding) | |
2039 // 4: 0x0F 0x1F 0x40 0x00 | |
2040 // 5: 0x0F 0x1F 0x44 0x00 0x00 | |
2041 // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00 | |
2042 // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 | |
2043 // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
2044 // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
2045 // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
2046 // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
2047 | |
2048 // The rest coding is AMD specific - use consecutive address nops | |
2049 | |
2050 // 12: 0x66 0x0F 0x1F 0x44 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00 | |
2051 // 13: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00 | |
2052 // 14: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 | |
2053 // 15: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 | |
2054 // 16: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 | |
2055 // Size prefixes (0x66) are added for larger sizes | |
2056 | |
2057 while(i >= 22) { | |
2058 i -= 11; | |
2059 emit_byte(0x66); // size prefix | |
2060 emit_byte(0x66); // size prefix | |
2061 emit_byte(0x66); // size prefix | |
2062 addr_nop_8(); | |
2063 } | |
2064 // Generate first nop for size between 21-12 | |
2065 switch (i) { | |
2066 case 21: | |
2067 i -= 1; | |
2068 emit_byte(0x66); // size prefix | |
2069 case 20: | |
2070 case 19: | |
2071 i -= 1; | |
2072 emit_byte(0x66); // size prefix | |
2073 case 18: | |
2074 case 17: | |
2075 i -= 1; | |
2076 emit_byte(0x66); // size prefix | |
2077 case 16: | |
2078 case 15: | |
2079 i -= 8; | |
2080 addr_nop_8(); | |
2081 break; | |
2082 case 14: | |
2083 case 13: | |
2084 i -= 7; | |
2085 addr_nop_7(); | |
2086 break; | |
2087 case 12: | |
2088 i -= 6; | |
2089 emit_byte(0x66); // size prefix | |
2090 addr_nop_5(); | |
2091 break; | |
2092 default: | |
2093 assert(i < 12, " "); | |
2094 } | |
2095 | |
2096 // Generate second nop for size between 11-1 | |
2097 switch (i) { | |
2098 case 11: | |
2099 emit_byte(0x66); // size prefix | |
2100 case 10: | |
2101 emit_byte(0x66); // size prefix | |
2102 case 9: | |
2103 emit_byte(0x66); // size prefix | |
2104 case 8: | |
2105 addr_nop_8(); | |
2106 break; | |
2107 case 7: | |
2108 addr_nop_7(); | |
2109 break; | |
2110 case 6: | |
2111 emit_byte(0x66); // size prefix | |
2112 case 5: | |
2113 addr_nop_5(); | |
2114 break; | |
2115 case 4: | |
2116 addr_nop_4(); | |
2117 break; | |
2118 case 3: | |
2119 // Don't use "0x0F 0x1F 0x00" - need patching safe padding | |
2120 emit_byte(0x66); // size prefix | |
2121 case 2: | |
2122 emit_byte(0x66); // size prefix | |
2123 case 1: | |
2124 emit_byte(0x90); // nop | |
2125 break; | |
2126 default: | |
2127 assert(i == 0, " "); | |
2128 } | |
2129 return; | |
2130 } | |
2131 | |
2132 // Using nops with size prefixes "0x66 0x90". | |
2133 // From AMD Optimization Guide: | |
2134 // 1: 0x90 | |
2135 // 2: 0x66 0x90 | |
2136 // 3: 0x66 0x66 0x90 | |
2137 // 4: 0x66 0x66 0x66 0x90 | |
2138 // 5: 0x66 0x66 0x90 0x66 0x90 | |
2139 // 6: 0x66 0x66 0x90 0x66 0x66 0x90 | |
2140 // 7: 0x66 0x66 0x66 0x90 0x66 0x66 0x90 | |
2141 // 8: 0x66 0x66 0x66 0x90 0x66 0x66 0x66 0x90 | |
2142 // 9: 0x66 0x66 0x90 0x66 0x66 0x90 0x66 0x66 0x90 | |
2143 // 10: 0x66 0x66 0x66 0x90 0x66 0x66 0x90 0x66 0x66 0x90 | |
2144 // | |
2145 while(i > 12) { | |
2146 i -= 4; | |
2147 emit_byte(0x66); // size prefix | |
2148 emit_byte(0x66); | |
2149 emit_byte(0x66); | |
2150 emit_byte(0x90); // nop | |
2151 } | |
2152 // 1 - 12 nops | |
2153 if(i > 8) { | |
2154 if(i > 9) { | |
2155 i -= 1; | |
2156 emit_byte(0x66); | |
2157 } | |
2158 i -= 3; | |
2159 emit_byte(0x66); | |
2160 emit_byte(0x66); | |
2161 emit_byte(0x90); | |
2162 } | |
2163 // 1 - 8 nops | |
2164 if(i > 4) { | |
2165 if(i > 6) { | |
2166 i -= 1; | |
2167 emit_byte(0x66); | |
2168 } | |
2169 i -= 3; | |
2170 emit_byte(0x66); | |
2171 emit_byte(0x66); | |
2172 emit_byte(0x90); | |
2173 } | |
2174 switch (i) { | |
2175 case 4: | |
2176 emit_byte(0x66); | |
2177 case 3: | |
2178 emit_byte(0x66); | |
2179 case 2: | |
2180 emit_byte(0x66); | |
2181 case 1: | |
2182 emit_byte(0x90); | |
2183 break; | |
2184 default: | |
2185 assert(i == 0, " "); | |
2186 } | |
2187 } | |
2188 | |
304 | 2189 void Assembler::notl(Register dst) { |
2190 int encode = prefix_and_encode(dst->encoding()); | |
2191 emit_byte(0xF7); | |
2192 emit_byte(0xD0 | encode ); | |
2193 } | |
2194 | |
2195 void Assembler::orl(Address dst, int32_t imm32) { | |
2196 InstructionMark im(this); | |
2197 prefix(dst); | |
2198 emit_byte(0x81); | |
2199 emit_operand(rcx, dst, 4); | |
2200 emit_long(imm32); | |
2201 } | |
2202 | |
2203 void Assembler::orl(Register dst, int32_t imm32) { | |
2204 prefix(dst); | |
2205 emit_arith(0x81, 0xC8, dst, imm32); | |
2206 } | |
2207 | |
2208 | |
2209 void Assembler::orl(Register dst, Address src) { | |
2210 InstructionMark im(this); | |
2211 prefix(src, dst); | |
2212 emit_byte(0x0B); | |
2213 emit_operand(dst, src); | |
2214 } | |
2215 | |
2216 | |
2217 void Assembler::orl(Register dst, Register src) { | |
2218 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
2219 emit_arith(0x0B, 0xC0, dst, src); | |
2220 } | |
2221 | |
681 | 2222 void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { |
2223 assert(VM_Version::supports_sse4_2(), ""); | |
2224 | |
2225 InstructionMark im(this); | |
2226 emit_byte(0x66); | |
2227 prefix(src, dst); | |
2228 emit_byte(0x0F); | |
2229 emit_byte(0x3A); | |
2230 emit_byte(0x61); | |
2231 emit_operand(dst, src); | |
2232 emit_byte(imm8); | |
2233 } | |
2234 | |
2235 void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) { | |
2236 assert(VM_Version::supports_sse4_2(), ""); | |
2237 | |
2238 emit_byte(0x66); | |
2239 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
2240 emit_byte(0x0F); | |
2241 emit_byte(0x3A); | |
2242 emit_byte(0x61); | |
2243 emit_byte(0xC0 | encode); | |
2244 emit_byte(imm8); | |
2245 } | |
2246 | |
304 | 2247 // generic |
2248 void Assembler::pop(Register dst) { | |
2249 int encode = prefix_and_encode(dst->encoding()); | |
2250 emit_byte(0x58 | encode); | |
2251 } | |
2252 | |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2253 void Assembler::popcntl(Register dst, Address src) { |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2254 assert(VM_Version::supports_popcnt(), "must support"); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2255 InstructionMark im(this); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2256 emit_byte(0xF3); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2257 prefix(src, dst); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2258 emit_byte(0x0F); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2259 emit_byte(0xB8); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2260 emit_operand(dst, src); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2261 } |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2262 |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2263 void Assembler::popcntl(Register dst, Register src) { |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2264 assert(VM_Version::supports_popcnt(), "must support"); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2265 emit_byte(0xF3); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2266 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2267 emit_byte(0x0F); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2268 emit_byte(0xB8); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2269 emit_byte(0xC0 | encode); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2270 } |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
2271 |
304 | 2272 void Assembler::popf() { |
2273 emit_byte(0x9D); | |
2274 } | |
2275 | |
1060 | 2276 #ifndef _LP64 // no 32bit push/pop on amd64 |
304 | 2277 void Assembler::popl(Address dst) { |
2278 // NOTE: this will adjust stack by 8byte on 64bits | |
2279 InstructionMark im(this); | |
2280 prefix(dst); | |
2281 emit_byte(0x8F); | |
2282 emit_operand(rax, dst); | |
2283 } | |
1060 | 2284 #endif |
304 | 2285 |
2286 void Assembler::prefetch_prefix(Address src) { | |
2287 prefix(src); | |
2288 emit_byte(0x0F); | |
2289 } | |
2290 | |
2291 void Assembler::prefetchnta(Address src) { | |
2292 NOT_LP64(assert(VM_Version::supports_sse2(), "must support")); | |
2293 InstructionMark im(this); | |
2294 prefetch_prefix(src); | |
2295 emit_byte(0x18); | |
2296 emit_operand(rax, src); // 0, src | |
2297 } | |
2298 | |
2299 void Assembler::prefetchr(Address src) { | |
2300 NOT_LP64(assert(VM_Version::supports_3dnow(), "must support")); | |
2301 InstructionMark im(this); | |
2302 prefetch_prefix(src); | |
2303 emit_byte(0x0D); | |
2304 emit_operand(rax, src); // 0, src | |
2305 } | |
2306 | |
2307 void Assembler::prefetcht0(Address src) { | |
2308 NOT_LP64(assert(VM_Version::supports_sse(), "must support")); | |
2309 InstructionMark im(this); | |
2310 prefetch_prefix(src); | |
2311 emit_byte(0x18); | |
2312 emit_operand(rcx, src); // 1, src | |
2313 } | |
2314 | |
2315 void Assembler::prefetcht1(Address src) { | |
2316 NOT_LP64(assert(VM_Version::supports_sse(), "must support")); | |
2317 InstructionMark im(this); | |
2318 prefetch_prefix(src); | |
2319 emit_byte(0x18); | |
2320 emit_operand(rdx, src); // 2, src | |
2321 } | |
2322 | |
2323 void Assembler::prefetcht2(Address src) { | |
2324 NOT_LP64(assert(VM_Version::supports_sse(), "must support")); | |
2325 InstructionMark im(this); | |
2326 prefetch_prefix(src); | |
2327 emit_byte(0x18); | |
2328 emit_operand(rbx, src); // 3, src | |
2329 } | |
2330 | |
2331 void Assembler::prefetchw(Address src) { | |
2332 NOT_LP64(assert(VM_Version::supports_3dnow(), "must support")); | |
2333 InstructionMark im(this); | |
2334 prefetch_prefix(src); | |
2335 emit_byte(0x0D); | |
2336 emit_operand(rcx, src); // 1, src | |
2337 } | |
2338 | |
2339 void Assembler::prefix(Prefix p) { | |
2340 a_byte(p); | |
2341 } | |
2342 | |
2343 void Assembler::pshufd(XMMRegister dst, XMMRegister src, int mode) { | |
2344 assert(isByte(mode), "invalid value"); | |
2345 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2346 | |
2347 emit_byte(0x66); | |
2348 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2349 emit_byte(0x0F); | |
2350 emit_byte(0x70); | |
2351 emit_byte(0xC0 | encode); | |
2352 emit_byte(mode & 0xFF); | |
2353 | |
2354 } | |
2355 | |
2356 void Assembler::pshufd(XMMRegister dst, Address src, int mode) { | |
2357 assert(isByte(mode), "invalid value"); | |
2358 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2359 | |
2360 InstructionMark im(this); | |
2361 emit_byte(0x66); | |
2362 prefix(src, dst); | |
2363 emit_byte(0x0F); | |
2364 emit_byte(0x70); | |
2365 emit_operand(dst, src); | |
2366 emit_byte(mode & 0xFF); | |
2367 } | |
2368 | |
2369 void Assembler::pshuflw(XMMRegister dst, XMMRegister src, int mode) { | |
2370 assert(isByte(mode), "invalid value"); | |
2371 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2372 | |
2373 emit_byte(0xF2); | |
2374 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2375 emit_byte(0x0F); | |
2376 emit_byte(0x70); | |
2377 emit_byte(0xC0 | encode); | |
2378 emit_byte(mode & 0xFF); | |
2379 } | |
2380 | |
2381 void Assembler::pshuflw(XMMRegister dst, Address src, int mode) { | |
2382 assert(isByte(mode), "invalid value"); | |
2383 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2384 | |
2385 InstructionMark im(this); | |
2386 emit_byte(0xF2); | |
2387 prefix(src, dst); // QQ new | |
2388 emit_byte(0x0F); | |
2389 emit_byte(0x70); | |
2390 emit_operand(dst, src); | |
2391 emit_byte(mode & 0xFF); | |
2392 } | |
2393 | |
2394 void Assembler::psrlq(XMMRegister dst, int shift) { | |
2395 // HMM Table D-1 says sse2 or mmx | |
2396 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2397 | |
2398 int encode = prefixq_and_encode(xmm2->encoding(), dst->encoding()); | |
2399 emit_byte(0x66); | |
2400 emit_byte(0x0F); | |
2401 emit_byte(0x73); | |
2402 emit_byte(0xC0 | encode); | |
2403 emit_byte(shift); | |
2404 } | |
2405 | |
681 | 2406 void Assembler::ptest(XMMRegister dst, Address src) { |
2407 assert(VM_Version::supports_sse4_1(), ""); | |
2408 | |
2409 InstructionMark im(this); | |
2410 emit_byte(0x66); | |
2411 prefix(src, dst); | |
2412 emit_byte(0x0F); | |
2413 emit_byte(0x38); | |
2414 emit_byte(0x17); | |
2415 emit_operand(dst, src); | |
2416 } | |
2417 | |
2418 void Assembler::ptest(XMMRegister dst, XMMRegister src) { | |
2419 assert(VM_Version::supports_sse4_1(), ""); | |
2420 | |
2421 emit_byte(0x66); | |
2422 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
2423 emit_byte(0x0F); | |
2424 emit_byte(0x38); | |
2425 emit_byte(0x17); | |
2426 emit_byte(0xC0 | encode); | |
2427 } | |
2428 | |
304 | 2429 void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) { |
2430 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2431 emit_byte(0x66); | |
2432 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2433 emit_byte(0x0F); | |
2434 emit_byte(0x60); | |
2435 emit_byte(0xC0 | encode); | |
2436 } | |
2437 | |
2438 void Assembler::push(int32_t imm32) { | |
2439 // in 64bits we push 64bits onto the stack but only | |
2440 // take a 32bit immediate | |
2441 emit_byte(0x68); | |
2442 emit_long(imm32); | |
2443 } | |
2444 | |
2445 void Assembler::push(Register src) { | |
2446 int encode = prefix_and_encode(src->encoding()); | |
2447 | |
2448 emit_byte(0x50 | encode); | |
2449 } | |
2450 | |
2451 void Assembler::pushf() { | |
2452 emit_byte(0x9C); | |
2453 } | |
2454 | |
1060 | 2455 #ifndef _LP64 // no 32bit push/pop on amd64 |
304 | 2456 void Assembler::pushl(Address src) { |
2457 // Note this will push 64bit on 64bit | |
2458 InstructionMark im(this); | |
2459 prefix(src); | |
2460 emit_byte(0xFF); | |
2461 emit_operand(rsi, src); | |
2462 } | |
1060 | 2463 #endif |
304 | 2464 |
2465 void Assembler::pxor(XMMRegister dst, Address src) { | |
2466 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2467 InstructionMark im(this); | |
2468 emit_byte(0x66); | |
2469 prefix(src, dst); | |
2470 emit_byte(0x0F); | |
2471 emit_byte(0xEF); | |
2472 emit_operand(dst, src); | |
2473 } | |
2474 | |
2475 void Assembler::pxor(XMMRegister dst, XMMRegister src) { | |
2476 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2477 InstructionMark im(this); | |
2478 emit_byte(0x66); | |
2479 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2480 emit_byte(0x0F); | |
2481 emit_byte(0xEF); | |
2482 emit_byte(0xC0 | encode); | |
2483 } | |
2484 | |
2485 void Assembler::rcll(Register dst, int imm8) { | |
2486 assert(isShiftCount(imm8), "illegal shift count"); | |
2487 int encode = prefix_and_encode(dst->encoding()); | |
2488 if (imm8 == 1) { | |
2489 emit_byte(0xD1); | |
2490 emit_byte(0xD0 | encode); | |
2491 } else { | |
2492 emit_byte(0xC1); | |
2493 emit_byte(0xD0 | encode); | |
2494 emit_byte(imm8); | |
2495 } | |
2496 } | |
2497 | |
2498 // copies data from [esi] to [edi] using rcx pointer sized words | |
2499 // generic | |
2500 void Assembler::rep_mov() { | |
2501 emit_byte(0xF3); | |
2502 // MOVSQ | |
2503 LP64_ONLY(prefix(REX_W)); | |
2504 emit_byte(0xA5); | |
2505 } | |
2506 | |
2507 // sets rcx pointer sized words with rax, value at [edi] | |
2508 // generic | |
2509 void Assembler::rep_set() { // rep_set | |
2510 emit_byte(0xF3); | |
2511 // STOSQ | |
2512 LP64_ONLY(prefix(REX_W)); | |
2513 emit_byte(0xAB); | |
2514 } | |
2515 | |
2516 // scans rcx pointer sized words at [edi] for occurance of rax, | |
2517 // generic | |
2518 void Assembler::repne_scan() { // repne_scan | |
2519 emit_byte(0xF2); | |
2520 // SCASQ | |
2521 LP64_ONLY(prefix(REX_W)); | |
2522 emit_byte(0xAF); | |
2523 } | |
2524 | |
2525 #ifdef _LP64 | |
2526 // scans rcx 4 byte words at [edi] for occurance of rax, | |
2527 // generic | |
2528 void Assembler::repne_scanl() { // repne_scan | |
2529 emit_byte(0xF2); | |
2530 // SCASL | |
2531 emit_byte(0xAF); | |
2532 } | |
2533 #endif | |
2534 | |
0 | 2535 void Assembler::ret(int imm16) { |
2536 if (imm16 == 0) { | |
2537 emit_byte(0xC3); | |
2538 } else { | |
2539 emit_byte(0xC2); | |
2540 emit_word(imm16); | |
2541 } | |
2542 } | |
2543 | |
304 | 2544 void Assembler::sahf() { |
2545 #ifdef _LP64 | |
2546 // Not supported in 64bit mode | |
2547 ShouldNotReachHere(); | |
2548 #endif | |
2549 emit_byte(0x9E); | |
2550 } | |
2551 | |
2552 void Assembler::sarl(Register dst, int imm8) { | |
2553 int encode = prefix_and_encode(dst->encoding()); | |
2554 assert(isShiftCount(imm8), "illegal shift count"); | |
2555 if (imm8 == 1) { | |
2556 emit_byte(0xD1); | |
2557 emit_byte(0xF8 | encode); | |
2558 } else { | |
2559 emit_byte(0xC1); | |
2560 emit_byte(0xF8 | encode); | |
2561 emit_byte(imm8); | |
2562 } | |
2563 } | |
2564 | |
2565 void Assembler::sarl(Register dst) { | |
2566 int encode = prefix_and_encode(dst->encoding()); | |
2567 emit_byte(0xD3); | |
2568 emit_byte(0xF8 | encode); | |
2569 } | |
2570 | |
2571 void Assembler::sbbl(Address dst, int32_t imm32) { | |
2572 InstructionMark im(this); | |
2573 prefix(dst); | |
2574 emit_arith_operand(0x81, rbx, dst, imm32); | |
2575 } | |
2576 | |
2577 void Assembler::sbbl(Register dst, int32_t imm32) { | |
2578 prefix(dst); | |
2579 emit_arith(0x81, 0xD8, dst, imm32); | |
2580 } | |
2581 | |
2582 | |
2583 void Assembler::sbbl(Register dst, Address src) { | |
2584 InstructionMark im(this); | |
2585 prefix(src, dst); | |
2586 emit_byte(0x1B); | |
2587 emit_operand(dst, src); | |
2588 } | |
2589 | |
2590 void Assembler::sbbl(Register dst, Register src) { | |
2591 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
2592 emit_arith(0x1B, 0xC0, dst, src); | |
2593 } | |
2594 | |
2595 void Assembler::setb(Condition cc, Register dst) { | |
2596 assert(0 <= cc && cc < 16, "illegal cc"); | |
2597 int encode = prefix_and_encode(dst->encoding(), true); | |
0 | 2598 emit_byte(0x0F); |
304 | 2599 emit_byte(0x90 | cc); |
2600 emit_byte(0xC0 | encode); | |
2601 } | |
2602 | |
2603 void Assembler::shll(Register dst, int imm8) { | |
2604 assert(isShiftCount(imm8), "illegal shift count"); | |
2605 int encode = prefix_and_encode(dst->encoding()); | |
2606 if (imm8 == 1 ) { | |
2607 emit_byte(0xD1); | |
2608 emit_byte(0xE0 | encode); | |
2609 } else { | |
2610 emit_byte(0xC1); | |
2611 emit_byte(0xE0 | encode); | |
2612 emit_byte(imm8); | |
2613 } | |
2614 } | |
2615 | |
2616 void Assembler::shll(Register dst) { | |
2617 int encode = prefix_and_encode(dst->encoding()); | |
2618 emit_byte(0xD3); | |
2619 emit_byte(0xE0 | encode); | |
2620 } | |
2621 | |
2622 void Assembler::shrl(Register dst, int imm8) { | |
2623 assert(isShiftCount(imm8), "illegal shift count"); | |
2624 int encode = prefix_and_encode(dst->encoding()); | |
2625 emit_byte(0xC1); | |
2626 emit_byte(0xE8 | encode); | |
2627 emit_byte(imm8); | |
2628 } | |
2629 | |
2630 void Assembler::shrl(Register dst) { | |
2631 int encode = prefix_and_encode(dst->encoding()); | |
2632 emit_byte(0xD3); | |
2633 emit_byte(0xE8 | encode); | |
2634 } | |
0 | 2635 |
2636 // copies a single word from [esi] to [edi] | |
2637 void Assembler::smovl() { | |
2638 emit_byte(0xA5); | |
2639 } | |
2640 | |
304 | 2641 void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { |
2642 // HMM Table D-1 says sse2 | |
2643 // NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2644 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2645 emit_byte(0xF2); | |
2646 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2647 emit_byte(0x0F); | |
2648 emit_byte(0x51); | |
2649 emit_byte(0xC0 | encode); | |
2650 } | |
2651 | |
2652 void Assembler::stmxcsr( Address dst) { | |
2653 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2654 InstructionMark im(this); | |
2655 prefix(dst); | |
2656 emit_byte(0x0F); | |
2657 emit_byte(0xAE); | |
2658 emit_operand(as_Register(3), dst); | |
2659 } | |
2660 | |
2661 void Assembler::subl(Address dst, int32_t imm32) { | |
2662 InstructionMark im(this); | |
2663 prefix(dst); | |
2664 if (is8bit(imm32)) { | |
2665 emit_byte(0x83); | |
2666 emit_operand(rbp, dst, 1); | |
2667 emit_byte(imm32 & 0xFF); | |
2668 } else { | |
2669 emit_byte(0x81); | |
2670 emit_operand(rbp, dst, 4); | |
2671 emit_long(imm32); | |
2672 } | |
2673 } | |
2674 | |
2675 void Assembler::subl(Register dst, int32_t imm32) { | |
2676 prefix(dst); | |
2677 emit_arith(0x81, 0xE8, dst, imm32); | |
2678 } | |
2679 | |
2680 void Assembler::subl(Address dst, Register src) { | |
2681 InstructionMark im(this); | |
2682 prefix(dst, src); | |
2683 emit_byte(0x29); | |
2684 emit_operand(src, dst); | |
2685 } | |
2686 | |
2687 void Assembler::subl(Register dst, Address src) { | |
2688 InstructionMark im(this); | |
2689 prefix(src, dst); | |
2690 emit_byte(0x2B); | |
2691 emit_operand(dst, src); | |
2692 } | |
2693 | |
2694 void Assembler::subl(Register dst, Register src) { | |
2695 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
2696 emit_arith(0x2B, 0xC0, dst, src); | |
2697 } | |
2698 | |
2699 void Assembler::subsd(XMMRegister dst, XMMRegister src) { | |
2700 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2701 emit_byte(0xF2); | |
2702 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2703 emit_byte(0x0F); | |
2704 emit_byte(0x5C); | |
2705 emit_byte(0xC0 | encode); | |
2706 } | |
2707 | |
2708 void Assembler::subsd(XMMRegister dst, Address src) { | |
2709 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2710 InstructionMark im(this); | |
2711 emit_byte(0xF2); | |
2712 prefix(src, dst); | |
2713 emit_byte(0x0F); | |
2714 emit_byte(0x5C); | |
2715 emit_operand(dst, src); | |
2716 } | |
2717 | |
2718 void Assembler::subss(XMMRegister dst, XMMRegister src) { | |
2719 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
0 | 2720 emit_byte(0xF3); |
304 | 2721 int encode = prefix_and_encode(dst->encoding(), src->encoding()); |
2722 emit_byte(0x0F); | |
2723 emit_byte(0x5C); | |
2724 emit_byte(0xC0 | encode); | |
2725 } | |
2726 | |
2727 void Assembler::subss(XMMRegister dst, Address src) { | |
2728 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2729 InstructionMark im(this); | |
2730 emit_byte(0xF3); | |
2731 prefix(src, dst); | |
2732 emit_byte(0x0F); | |
2733 emit_byte(0x5C); | |
2734 emit_operand(dst, src); | |
2735 } | |
2736 | |
2737 void Assembler::testb(Register dst, int imm8) { | |
2738 NOT_LP64(assert(dst->has_byte_register(), "must have byte register")); | |
2739 (void) prefix_and_encode(dst->encoding(), true); | |
2740 emit_arith_b(0xF6, 0xC0, dst, imm8); | |
2741 } | |
2742 | |
2743 void Assembler::testl(Register dst, int32_t imm32) { | |
2744 // not using emit_arith because test | |
2745 // doesn't support sign-extension of | |
2746 // 8bit operands | |
2747 int encode = dst->encoding(); | |
2748 if (encode == 0) { | |
2749 emit_byte(0xA9); | |
2750 } else { | |
2751 encode = prefix_and_encode(encode); | |
2752 emit_byte(0xF7); | |
2753 emit_byte(0xC0 | encode); | |
2754 } | |
2755 emit_long(imm32); | |
2756 } | |
2757 | |
2758 void Assembler::testl(Register dst, Register src) { | |
2759 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
2760 emit_arith(0x85, 0xC0, dst, src); | |
2761 } | |
2762 | |
2763 void Assembler::testl(Register dst, Address src) { | |
2764 InstructionMark im(this); | |
2765 prefix(src, dst); | |
2766 emit_byte(0x85); | |
2767 emit_operand(dst, src); | |
2768 } | |
2769 | |
2770 void Assembler::ucomisd(XMMRegister dst, Address src) { | |
2771 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2772 emit_byte(0x66); | |
2773 ucomiss(dst, src); | |
2774 } | |
2775 | |
2776 void Assembler::ucomisd(XMMRegister dst, XMMRegister src) { | |
2777 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2778 emit_byte(0x66); | |
2779 ucomiss(dst, src); | |
2780 } | |
2781 | |
2782 void Assembler::ucomiss(XMMRegister dst, Address src) { | |
2783 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2784 | |
2785 InstructionMark im(this); | |
2786 prefix(src, dst); | |
2787 emit_byte(0x0F); | |
2788 emit_byte(0x2E); | |
2789 emit_operand(dst, src); | |
2790 } | |
2791 | |
2792 void Assembler::ucomiss(XMMRegister dst, XMMRegister src) { | |
2793 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2794 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2795 emit_byte(0x0F); | |
2796 emit_byte(0x2E); | |
2797 emit_byte(0xC0 | encode); | |
2798 } | |
2799 | |
2800 | |
2801 void Assembler::xaddl(Address dst, Register src) { | |
2802 InstructionMark im(this); | |
2803 prefix(dst, src); | |
0 | 2804 emit_byte(0x0F); |
304 | 2805 emit_byte(0xC1); |
2806 emit_operand(src, dst); | |
2807 } | |
2808 | |
2809 void Assembler::xchgl(Register dst, Address src) { // xchg | |
2810 InstructionMark im(this); | |
2811 prefix(src, dst); | |
2812 emit_byte(0x87); | |
2813 emit_operand(dst, src); | |
2814 } | |
2815 | |
2816 void Assembler::xchgl(Register dst, Register src) { | |
2817 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2818 emit_byte(0x87); | |
2819 emit_byte(0xc0 | encode); | |
2820 } | |
2821 | |
2822 void Assembler::xorl(Register dst, int32_t imm32) { | |
2823 prefix(dst); | |
2824 emit_arith(0x81, 0xF0, dst, imm32); | |
2825 } | |
2826 | |
2827 void Assembler::xorl(Register dst, Address src) { | |
2828 InstructionMark im(this); | |
2829 prefix(src, dst); | |
2830 emit_byte(0x33); | |
2831 emit_operand(dst, src); | |
2832 } | |
2833 | |
2834 void Assembler::xorl(Register dst, Register src) { | |
2835 (void) prefix_and_encode(dst->encoding(), src->encoding()); | |
2836 emit_arith(0x33, 0xC0, dst, src); | |
2837 } | |
2838 | |
2839 void Assembler::xorpd(XMMRegister dst, XMMRegister src) { | |
2840 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2841 emit_byte(0x66); | |
2842 xorps(dst, src); | |
2843 } | |
2844 | |
2845 void Assembler::xorpd(XMMRegister dst, Address src) { | |
2846 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
2847 InstructionMark im(this); | |
2848 emit_byte(0x66); | |
2849 prefix(src, dst); | |
2850 emit_byte(0x0F); | |
2851 emit_byte(0x57); | |
2852 emit_operand(dst, src); | |
2853 } | |
2854 | |
2855 | |
2856 void Assembler::xorps(XMMRegister dst, XMMRegister src) { | |
2857 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2858 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2859 emit_byte(0x0F); | |
2860 emit_byte(0x57); | |
2861 emit_byte(0xC0 | encode); | |
2862 } | |
2863 | |
2864 void Assembler::xorps(XMMRegister dst, Address src) { | |
2865 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
2866 InstructionMark im(this); | |
2867 prefix(src, dst); | |
2868 emit_byte(0x0F); | |
2869 emit_byte(0x57); | |
2870 emit_operand(dst, src); | |
2871 } | |
2872 | |
2873 #ifndef _LP64 | |
2874 // 32bit only pieces of the assembler | |
2875 | |
2876 void Assembler::cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec) { | |
2877 // NO PREFIX AS NEVER 64BIT | |
2878 InstructionMark im(this); | |
2879 emit_byte(0x81); | |
2880 emit_byte(0xF8 | src1->encoding()); | |
2881 emit_data(imm32, rspec, 0); | |
2882 } | |
2883 | |
2884 void Assembler::cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec) { | |
2885 // NO PREFIX AS NEVER 64BIT (not even 32bit versions of 64bit regs | |
2886 InstructionMark im(this); | |
2887 emit_byte(0x81); | |
2888 emit_operand(rdi, src1); | |
2889 emit_data(imm32, rspec, 0); | |
2890 } | |
2891 | |
2892 // The 64-bit (32bit platform) cmpxchg compares the value at adr with the contents of rdx:rax, | |
2893 // and stores rcx:rbx into adr if so; otherwise, the value at adr is loaded | |
2894 // into rdx:rax. The ZF is set if the compared values were equal, and cleared otherwise. | |
2895 void Assembler::cmpxchg8(Address adr) { | |
2896 InstructionMark im(this); | |
2897 emit_byte(0x0F); | |
2898 emit_byte(0xc7); | |
2899 emit_operand(rcx, adr); | |
2900 } | |
2901 | |
2902 void Assembler::decl(Register dst) { | |
2903 // Don't use it directly. Use MacroAssembler::decrementl() instead. | |
2904 emit_byte(0x48 | dst->encoding()); | |
2905 } | |
2906 | |
2907 #endif // _LP64 | |
2908 | |
2909 // 64bit typically doesn't use the x87 but needs to for the trig funcs | |
2910 | |
2911 void Assembler::fabs() { | |
2912 emit_byte(0xD9); | |
2913 emit_byte(0xE1); | |
2914 } | |
2915 | |
2916 void Assembler::fadd(int i) { | |
2917 emit_farith(0xD8, 0xC0, i); | |
2918 } | |
2919 | |
2920 void Assembler::fadd_d(Address src) { | |
2921 InstructionMark im(this); | |
2922 emit_byte(0xDC); | |
2923 emit_operand32(rax, src); | |
2924 } | |
2925 | |
2926 void Assembler::fadd_s(Address src) { | |
2927 InstructionMark im(this); | |
2928 emit_byte(0xD8); | |
2929 emit_operand32(rax, src); | |
2930 } | |
2931 | |
2932 void Assembler::fadda(int i) { | |
2933 emit_farith(0xDC, 0xC0, i); | |
2934 } | |
2935 | |
2936 void Assembler::faddp(int i) { | |
2937 emit_farith(0xDE, 0xC0, i); | |
2938 } | |
2939 | |
2940 void Assembler::fchs() { | |
2941 emit_byte(0xD9); | |
2942 emit_byte(0xE0); | |
2943 } | |
2944 | |
2945 void Assembler::fcom(int i) { | |
2946 emit_farith(0xD8, 0xD0, i); | |
2947 } | |
2948 | |
2949 void Assembler::fcomp(int i) { | |
2950 emit_farith(0xD8, 0xD8, i); | |
2951 } | |
2952 | |
2953 void Assembler::fcomp_d(Address src) { | |
2954 InstructionMark im(this); | |
2955 emit_byte(0xDC); | |
2956 emit_operand32(rbx, src); | |
2957 } | |
2958 | |
2959 void Assembler::fcomp_s(Address src) { | |
2960 InstructionMark im(this); | |
2961 emit_byte(0xD8); | |
2962 emit_operand32(rbx, src); | |
2963 } | |
2964 | |
2965 void Assembler::fcompp() { | |
2966 emit_byte(0xDE); | |
2967 emit_byte(0xD9); | |
2968 } | |
2969 | |
2970 void Assembler::fcos() { | |
2971 emit_byte(0xD9); | |
0 | 2972 emit_byte(0xFF); |
304 | 2973 } |
2974 | |
2975 void Assembler::fdecstp() { | |
2976 emit_byte(0xD9); | |
2977 emit_byte(0xF6); | |
2978 } | |
2979 | |
2980 void Assembler::fdiv(int i) { | |
2981 emit_farith(0xD8, 0xF0, i); | |
2982 } | |
2983 | |
2984 void Assembler::fdiv_d(Address src) { | |
2985 InstructionMark im(this); | |
2986 emit_byte(0xDC); | |
2987 emit_operand32(rsi, src); | |
2988 } | |
2989 | |
2990 void Assembler::fdiv_s(Address src) { | |
2991 InstructionMark im(this); | |
2992 emit_byte(0xD8); | |
2993 emit_operand32(rsi, src); | |
2994 } | |
2995 | |
2996 void Assembler::fdiva(int i) { | |
2997 emit_farith(0xDC, 0xF8, i); | |
2998 } | |
2999 | |
3000 // Note: The Intel manual (Pentium Processor User's Manual, Vol.3, 1994) | |
3001 // is erroneous for some of the floating-point instructions below. | |
3002 | |
3003 void Assembler::fdivp(int i) { | |
3004 emit_farith(0xDE, 0xF8, i); // ST(0) <- ST(0) / ST(1) and pop (Intel manual wrong) | |
3005 } | |
3006 | |
3007 void Assembler::fdivr(int i) { | |
3008 emit_farith(0xD8, 0xF8, i); | |
3009 } | |
3010 | |
3011 void Assembler::fdivr_d(Address src) { | |
3012 InstructionMark im(this); | |
3013 emit_byte(0xDC); | |
3014 emit_operand32(rdi, src); | |
3015 } | |
3016 | |
3017 void Assembler::fdivr_s(Address src) { | |
3018 InstructionMark im(this); | |
3019 emit_byte(0xD8); | |
3020 emit_operand32(rdi, src); | |
3021 } | |
3022 | |
3023 void Assembler::fdivra(int i) { | |
3024 emit_farith(0xDC, 0xF0, i); | |
3025 } | |
3026 | |
3027 void Assembler::fdivrp(int i) { | |
3028 emit_farith(0xDE, 0xF0, i); // ST(0) <- ST(1) / ST(0) and pop (Intel manual wrong) | |
3029 } | |
3030 | |
3031 void Assembler::ffree(int i) { | |
3032 emit_farith(0xDD, 0xC0, i); | |
3033 } | |
3034 | |
3035 void Assembler::fild_d(Address adr) { | |
3036 InstructionMark im(this); | |
3037 emit_byte(0xDF); | |
3038 emit_operand32(rbp, adr); | |
3039 } | |
3040 | |
3041 void Assembler::fild_s(Address adr) { | |
3042 InstructionMark im(this); | |
3043 emit_byte(0xDB); | |
3044 emit_operand32(rax, adr); | |
3045 } | |
3046 | |
3047 void Assembler::fincstp() { | |
3048 emit_byte(0xD9); | |
3049 emit_byte(0xF7); | |
3050 } | |
3051 | |
3052 void Assembler::finit() { | |
3053 emit_byte(0x9B); | |
3054 emit_byte(0xDB); | |
3055 emit_byte(0xE3); | |
3056 } | |
3057 | |
3058 void Assembler::fist_s(Address adr) { | |
3059 InstructionMark im(this); | |
3060 emit_byte(0xDB); | |
3061 emit_operand32(rdx, adr); | |
3062 } | |
3063 | |
3064 void Assembler::fistp_d(Address adr) { | |
3065 InstructionMark im(this); | |
3066 emit_byte(0xDF); | |
3067 emit_operand32(rdi, adr); | |
3068 } | |
3069 | |
3070 void Assembler::fistp_s(Address adr) { | |
3071 InstructionMark im(this); | |
3072 emit_byte(0xDB); | |
3073 emit_operand32(rbx, adr); | |
3074 } | |
0 | 3075 |
3076 void Assembler::fld1() { | |
3077 emit_byte(0xD9); | |
3078 emit_byte(0xE8); | |
3079 } | |
3080 | |
304 | 3081 void Assembler::fld_d(Address adr) { |
3082 InstructionMark im(this); | |
3083 emit_byte(0xDD); | |
3084 emit_operand32(rax, adr); | |
3085 } | |
0 | 3086 |
3087 void Assembler::fld_s(Address adr) { | |
3088 InstructionMark im(this); | |
3089 emit_byte(0xD9); | |
304 | 3090 emit_operand32(rax, adr); |
3091 } | |
3092 | |
3093 | |
3094 void Assembler::fld_s(int index) { | |
0 | 3095 emit_farith(0xD9, 0xC0, index); |
3096 } | |
3097 | |
3098 void Assembler::fld_x(Address adr) { | |
3099 InstructionMark im(this); | |
3100 emit_byte(0xDB); | |
304 | 3101 emit_operand32(rbp, adr); |
3102 } | |
3103 | |
3104 void Assembler::fldcw(Address src) { | |
3105 InstructionMark im(this); | |
3106 emit_byte(0xd9); | |
3107 emit_operand32(rbp, src); | |
3108 } | |
3109 | |
3110 void Assembler::fldenv(Address src) { | |
0 | 3111 InstructionMark im(this); |
3112 emit_byte(0xD9); | |
304 | 3113 emit_operand32(rsp, src); |
3114 } | |
3115 | |
3116 void Assembler::fldlg2() { | |
0 | 3117 emit_byte(0xD9); |
304 | 3118 emit_byte(0xEC); |
3119 } | |
0 | 3120 |
3121 void Assembler::fldln2() { | |
3122 emit_byte(0xD9); | |
3123 emit_byte(0xED); | |
3124 } | |
3125 | |
304 | 3126 void Assembler::fldz() { |
0 | 3127 emit_byte(0xD9); |
304 | 3128 emit_byte(0xEE); |
3129 } | |
0 | 3130 |
3131 void Assembler::flog() { | |
3132 fldln2(); | |
3133 fxch(); | |
3134 fyl2x(); | |
3135 } | |
3136 | |
3137 void Assembler::flog10() { | |
3138 fldlg2(); | |
3139 fxch(); | |
3140 fyl2x(); | |
3141 } | |
3142 | |
304 | 3143 void Assembler::fmul(int i) { |
3144 emit_farith(0xD8, 0xC8, i); | |
3145 } | |
3146 | |
3147 void Assembler::fmul_d(Address src) { | |
3148 InstructionMark im(this); | |
3149 emit_byte(0xDC); | |
3150 emit_operand32(rcx, src); | |
3151 } | |
3152 | |
3153 void Assembler::fmul_s(Address src) { | |
3154 InstructionMark im(this); | |
3155 emit_byte(0xD8); | |
3156 emit_operand32(rcx, src); | |
3157 } | |
3158 | |
3159 void Assembler::fmula(int i) { | |
3160 emit_farith(0xDC, 0xC8, i); | |
3161 } | |
3162 | |
3163 void Assembler::fmulp(int i) { | |
3164 emit_farith(0xDE, 0xC8, i); | |
3165 } | |
3166 | |
3167 void Assembler::fnsave(Address dst) { | |
3168 InstructionMark im(this); | |
3169 emit_byte(0xDD); | |
3170 emit_operand32(rsi, dst); | |
3171 } | |
3172 | |
3173 void Assembler::fnstcw(Address src) { | |
3174 InstructionMark im(this); | |
3175 emit_byte(0x9B); | |
3176 emit_byte(0xD9); | |
3177 emit_operand32(rdi, src); | |
3178 } | |
3179 | |
3180 void Assembler::fnstsw_ax() { | |
3181 emit_byte(0xdF); | |
3182 emit_byte(0xE0); | |
3183 } | |
3184 | |
3185 void Assembler::fprem() { | |
3186 emit_byte(0xD9); | |
3187 emit_byte(0xF8); | |
3188 } | |
3189 | |
3190 void Assembler::fprem1() { | |
3191 emit_byte(0xD9); | |
3192 emit_byte(0xF5); | |
3193 } | |
3194 | |
3195 void Assembler::frstor(Address src) { | |
3196 InstructionMark im(this); | |
3197 emit_byte(0xDD); | |
3198 emit_operand32(rsp, src); | |
3199 } | |
0 | 3200 |
3201 void Assembler::fsin() { | |
3202 emit_byte(0xD9); | |
3203 emit_byte(0xFE); | |
3204 } | |
3205 | |
304 | 3206 void Assembler::fsqrt() { |
3207 emit_byte(0xD9); | |
3208 emit_byte(0xFA); | |
3209 } | |
3210 | |
3211 void Assembler::fst_d(Address adr) { | |
3212 InstructionMark im(this); | |
3213 emit_byte(0xDD); | |
3214 emit_operand32(rdx, adr); | |
3215 } | |
3216 | |
3217 void Assembler::fst_s(Address adr) { | |
3218 InstructionMark im(this); | |
3219 emit_byte(0xD9); | |
3220 emit_operand32(rdx, adr); | |
3221 } | |
3222 | |
3223 void Assembler::fstp_d(Address adr) { | |
3224 InstructionMark im(this); | |
3225 emit_byte(0xDD); | |
3226 emit_operand32(rbx, adr); | |
3227 } | |
3228 | |
3229 void Assembler::fstp_d(int index) { | |
3230 emit_farith(0xDD, 0xD8, index); | |
3231 } | |
3232 | |
3233 void Assembler::fstp_s(Address adr) { | |
3234 InstructionMark im(this); | |
0 | 3235 emit_byte(0xD9); |
304 | 3236 emit_operand32(rbx, adr); |
3237 } | |
3238 | |
3239 void Assembler::fstp_x(Address adr) { | |
3240 InstructionMark im(this); | |
3241 emit_byte(0xDB); | |
3242 emit_operand32(rdi, adr); | |
3243 } | |
3244 | |
3245 void Assembler::fsub(int i) { | |
3246 emit_farith(0xD8, 0xE0, i); | |
3247 } | |
3248 | |
3249 void Assembler::fsub_d(Address src) { | |
3250 InstructionMark im(this); | |
3251 emit_byte(0xDC); | |
3252 emit_operand32(rsp, src); | |
3253 } | |
3254 | |
3255 void Assembler::fsub_s(Address src) { | |
3256 InstructionMark im(this); | |
3257 emit_byte(0xD8); | |
3258 emit_operand32(rsp, src); | |
3259 } | |
3260 | |
3261 void Assembler::fsuba(int i) { | |
3262 emit_farith(0xDC, 0xE8, i); | |
3263 } | |
3264 | |
3265 void Assembler::fsubp(int i) { | |
3266 emit_farith(0xDE, 0xE8, i); // ST(0) <- ST(0) - ST(1) and pop (Intel manual wrong) | |
3267 } | |
3268 | |
3269 void Assembler::fsubr(int i) { | |
3270 emit_farith(0xD8, 0xE8, i); | |
3271 } | |
3272 | |
3273 void Assembler::fsubr_d(Address src) { | |
3274 InstructionMark im(this); | |
3275 emit_byte(0xDC); | |
3276 emit_operand32(rbp, src); | |
3277 } | |
3278 | |
3279 void Assembler::fsubr_s(Address src) { | |
3280 InstructionMark im(this); | |
3281 emit_byte(0xD8); | |
3282 emit_operand32(rbp, src); | |
3283 } | |
3284 | |
3285 void Assembler::fsubra(int i) { | |
3286 emit_farith(0xDC, 0xE0, i); | |
3287 } | |
3288 | |
3289 void Assembler::fsubrp(int i) { | |
3290 emit_farith(0xDE, 0xE0, i); // ST(0) <- ST(1) - ST(0) and pop (Intel manual wrong) | |
0 | 3291 } |
3292 | |
3293 void Assembler::ftan() { | |
3294 emit_byte(0xD9); | |
3295 emit_byte(0xF2); | |
3296 emit_byte(0xDD); | |
3297 emit_byte(0xD8); | |
3298 } | |
3299 | |
304 | 3300 void Assembler::ftst() { |
0 | 3301 emit_byte(0xD9); |
304 | 3302 emit_byte(0xE4); |
3303 } | |
0 | 3304 |
3305 void Assembler::fucomi(int i) { | |
3306 // make sure the instruction is supported (introduced for P6, together with cmov) | |
3307 guarantee(VM_Version::supports_cmov(), "illegal instruction"); | |
3308 emit_farith(0xDB, 0xE8, i); | |
3309 } | |
3310 | |
3311 void Assembler::fucomip(int i) { | |
3312 // make sure the instruction is supported (introduced for P6, together with cmov) | |
3313 guarantee(VM_Version::supports_cmov(), "illegal instruction"); | |
3314 emit_farith(0xDF, 0xE8, i); | |
3315 } | |
3316 | |
3317 void Assembler::fwait() { | |
3318 emit_byte(0x9B); | |
3319 } | |
3320 | |
304 | 3321 void Assembler::fxch(int i) { |
3322 emit_farith(0xD9, 0xC8, i); | |
3323 } | |
3324 | |
3325 void Assembler::fyl2x() { | |
0 | 3326 emit_byte(0xD9); |
304 | 3327 emit_byte(0xF1); |
3328 } | |
3329 | |
3330 | |
3331 #ifndef _LP64 | |
3332 | |
3333 void Assembler::incl(Register dst) { | |
3334 // Don't use it directly. Use MacroAssembler::incrementl() instead. | |
3335 emit_byte(0x40 | dst->encoding()); | |
3336 } | |
3337 | |
3338 void Assembler::lea(Register dst, Address src) { | |
3339 leal(dst, src); | |
3340 } | |
3341 | |
3342 void Assembler::mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec) { | |
3343 InstructionMark im(this); | |
3344 emit_byte(0xC7); | |
3345 emit_operand(rax, dst); | |
3346 emit_data((int)imm32, rspec, 0); | |
3347 } | |
3348 | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3349 void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3350 InstructionMark im(this); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3351 int encode = prefix_and_encode(dst->encoding()); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3352 emit_byte(0xB8 | encode); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3353 emit_data((int)imm32, rspec, 0); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3354 } |
304 | 3355 |
3356 void Assembler::popa() { // 32bit | |
3357 emit_byte(0x61); | |
3358 } | |
3359 | |
3360 void Assembler::push_literal32(int32_t imm32, RelocationHolder const& rspec) { | |
3361 InstructionMark im(this); | |
3362 emit_byte(0x68); | |
3363 emit_data(imm32, rspec, 0); | |
3364 } | |
3365 | |
3366 void Assembler::pusha() { // 32bit | |
3367 emit_byte(0x60); | |
3368 } | |
3369 | |
3370 void Assembler::set_byte_if_not_zero(Register dst) { | |
0 | 3371 emit_byte(0x0F); |
304 | 3372 emit_byte(0x95); |
3373 emit_byte(0xE0 | dst->encoding()); | |
3374 } | |
3375 | |
3376 void Assembler::shldl(Register dst, Register src) { | |
0 | 3377 emit_byte(0x0F); |
304 | 3378 emit_byte(0xA5); |
3379 emit_byte(0xC0 | src->encoding() << 3 | dst->encoding()); | |
3380 } | |
3381 | |
3382 void Assembler::shrdl(Register dst, Register src) { | |
0 | 3383 emit_byte(0x0F); |
304 | 3384 emit_byte(0xAD); |
3385 emit_byte(0xC0 | src->encoding() << 3 | dst->encoding()); | |
3386 } | |
3387 | |
3388 #else // LP64 | |
3389 | |
1369 | 3390 void Assembler::set_byte_if_not_zero(Register dst) { |
3391 int enc = prefix_and_encode(dst->encoding(), true); | |
3392 emit_byte(0x0F); | |
3393 emit_byte(0x95); | |
3394 emit_byte(0xE0 | enc); | |
3395 } | |
3396 | |
304 | 3397 // 64bit only pieces of the assembler |
3398 // This should only be used by 64bit instructions that can use rip-relative | |
3399 // it cannot be used by instructions that want an immediate value. | |
3400 | |
3401 bool Assembler::reachable(AddressLiteral adr) { | |
3402 int64_t disp; | |
3403 // None will force a 64bit literal to the code stream. Likely a placeholder | |
3404 // for something that will be patched later and we need to certain it will | |
3405 // always be reachable. | |
3406 if (adr.reloc() == relocInfo::none) { | |
3407 return false; | |
3408 } | |
3409 if (adr.reloc() == relocInfo::internal_word_type) { | |
3410 // This should be rip relative and easily reachable. | |
3411 return true; | |
3412 } | |
3413 if (adr.reloc() == relocInfo::virtual_call_type || | |
3414 adr.reloc() == relocInfo::opt_virtual_call_type || | |
3415 adr.reloc() == relocInfo::static_call_type || | |
3416 adr.reloc() == relocInfo::static_stub_type ) { | |
3417 // This should be rip relative within the code cache and easily | |
3418 // reachable until we get huge code caches. (At which point | |
3419 // ic code is going to have issues). | |
3420 return true; | |
3421 } | |
3422 if (adr.reloc() != relocInfo::external_word_type && | |
3423 adr.reloc() != relocInfo::poll_return_type && // these are really external_word but need special | |
3424 adr.reloc() != relocInfo::poll_type && // relocs to identify them | |
3425 adr.reloc() != relocInfo::runtime_call_type ) { | |
3426 return false; | |
3427 } | |
3428 | |
3429 // Stress the correction code | |
3430 if (ForceUnreachable) { | |
3431 // Must be runtimecall reloc, see if it is in the codecache | |
3432 // Flipping stuff in the codecache to be unreachable causes issues | |
3433 // with things like inline caches where the additional instructions | |
3434 // are not handled. | |
3435 if (CodeCache::find_blob(adr._target) == NULL) { | |
3436 return false; | |
3437 } | |
3438 } | |
3439 // For external_word_type/runtime_call_type if it is reachable from where we | |
3440 // are now (possibly a temp buffer) and where we might end up | |
3441 // anywhere in the codeCache then we are always reachable. | |
3442 // This would have to change if we ever save/restore shared code | |
3443 // to be more pessimistic. | |
3444 | |
3445 disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int)); | |
3446 if (!is_simm32(disp)) return false; | |
3447 disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int)); | |
3448 if (!is_simm32(disp)) return false; | |
3449 | |
3450 disp = (int64_t)adr._target - ((int64_t)_code_pos + sizeof(int)); | |
3451 | |
3452 // Because rip relative is a disp + address_of_next_instruction and we | |
3453 // don't know the value of address_of_next_instruction we apply a fudge factor | |
3454 // to make sure we will be ok no matter the size of the instruction we get placed into. | |
3455 // We don't have to fudge the checks above here because they are already worst case. | |
3456 | |
3457 // 12 == override/rex byte, opcode byte, rm byte, sib byte, a 4-byte disp , 4-byte literal | |
3458 // + 4 because better safe than sorry. | |
3459 const int fudge = 12 + 4; | |
3460 if (disp < 0) { | |
3461 disp -= fudge; | |
3462 } else { | |
3463 disp += fudge; | |
3464 } | |
3465 return is_simm32(disp); | |
3466 } | |
3467 | |
3468 void Assembler::emit_data64(jlong data, | |
3469 relocInfo::relocType rtype, | |
3470 int format) { | |
3471 if (rtype == relocInfo::none) { | |
3472 emit_long64(data); | |
3473 } else { | |
3474 emit_data64(data, Relocation::spec_simple(rtype), format); | |
3475 } | |
3476 } | |
3477 | |
3478 void Assembler::emit_data64(jlong data, | |
3479 RelocationHolder const& rspec, | |
3480 int format) { | |
3481 assert(imm_operand == 0, "default format must be immediate in this file"); | |
3482 assert(imm_operand == format, "must be immediate"); | |
3483 assert(inst_mark() != NULL, "must be inside InstructionMark"); | |
3484 // Do not use AbstractAssembler::relocate, which is not intended for | |
3485 // embedded words. Instead, relocate to the enclosing instruction. | |
3486 code_section()->relocate(inst_mark(), rspec, format); | |
3487 #ifdef ASSERT | |
3488 check_relocation(rspec, format); | |
3489 #endif | |
3490 emit_long64(data); | |
3491 } | |
3492 | |
3493 int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { | |
3494 if (reg_enc >= 8) { | |
3495 prefix(REX_B); | |
3496 reg_enc -= 8; | |
3497 } else if (byteinst && reg_enc >= 4) { | |
3498 prefix(REX); | |
3499 } | |
3500 return reg_enc; | |
3501 } | |
3502 | |
3503 int Assembler::prefixq_and_encode(int reg_enc) { | |
3504 if (reg_enc < 8) { | |
3505 prefix(REX_W); | |
3506 } else { | |
3507 prefix(REX_WB); | |
3508 reg_enc -= 8; | |
3509 } | |
3510 return reg_enc; | |
3511 } | |
3512 | |
3513 int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) { | |
3514 if (dst_enc < 8) { | |
3515 if (src_enc >= 8) { | |
3516 prefix(REX_B); | |
3517 src_enc -= 8; | |
3518 } else if (byteinst && src_enc >= 4) { | |
3519 prefix(REX); | |
3520 } | |
3521 } else { | |
3522 if (src_enc < 8) { | |
3523 prefix(REX_R); | |
3524 } else { | |
3525 prefix(REX_RB); | |
3526 src_enc -= 8; | |
3527 } | |
3528 dst_enc -= 8; | |
3529 } | |
3530 return dst_enc << 3 | src_enc; | |
3531 } | |
3532 | |
3533 int Assembler::prefixq_and_encode(int dst_enc, int src_enc) { | |
3534 if (dst_enc < 8) { | |
3535 if (src_enc < 8) { | |
3536 prefix(REX_W); | |
3537 } else { | |
3538 prefix(REX_WB); | |
3539 src_enc -= 8; | |
3540 } | |
3541 } else { | |
3542 if (src_enc < 8) { | |
3543 prefix(REX_WR); | |
3544 } else { | |
3545 prefix(REX_WRB); | |
3546 src_enc -= 8; | |
3547 } | |
3548 dst_enc -= 8; | |
3549 } | |
3550 return dst_enc << 3 | src_enc; | |
3551 } | |
3552 | |
3553 void Assembler::prefix(Register reg) { | |
3554 if (reg->encoding() >= 8) { | |
3555 prefix(REX_B); | |
3556 } | |
3557 } | |
3558 | |
3559 void Assembler::prefix(Address adr) { | |
3560 if (adr.base_needs_rex()) { | |
3561 if (adr.index_needs_rex()) { | |
3562 prefix(REX_XB); | |
3563 } else { | |
3564 prefix(REX_B); | |
3565 } | |
3566 } else { | |
3567 if (adr.index_needs_rex()) { | |
3568 prefix(REX_X); | |
3569 } | |
3570 } | |
3571 } | |
3572 | |
3573 void Assembler::prefixq(Address adr) { | |
3574 if (adr.base_needs_rex()) { | |
3575 if (adr.index_needs_rex()) { | |
3576 prefix(REX_WXB); | |
3577 } else { | |
3578 prefix(REX_WB); | |
3579 } | |
3580 } else { | |
3581 if (adr.index_needs_rex()) { | |
3582 prefix(REX_WX); | |
3583 } else { | |
3584 prefix(REX_W); | |
3585 } | |
3586 } | |
3587 } | |
3588 | |
3589 | |
3590 void Assembler::prefix(Address adr, Register reg, bool byteinst) { | |
3591 if (reg->encoding() < 8) { | |
3592 if (adr.base_needs_rex()) { | |
3593 if (adr.index_needs_rex()) { | |
3594 prefix(REX_XB); | |
3595 } else { | |
3596 prefix(REX_B); | |
3597 } | |
3598 } else { | |
3599 if (adr.index_needs_rex()) { | |
3600 prefix(REX_X); | |
3601 } else if (reg->encoding() >= 4 ) { | |
3602 prefix(REX); | |
3603 } | |
3604 } | |
3605 } else { | |
3606 if (adr.base_needs_rex()) { | |
3607 if (adr.index_needs_rex()) { | |
3608 prefix(REX_RXB); | |
3609 } else { | |
3610 prefix(REX_RB); | |
3611 } | |
3612 } else { | |
3613 if (adr.index_needs_rex()) { | |
3614 prefix(REX_RX); | |
3615 } else { | |
3616 prefix(REX_R); | |
3617 } | |
3618 } | |
3619 } | |
3620 } | |
3621 | |
3622 void Assembler::prefixq(Address adr, Register src) { | |
3623 if (src->encoding() < 8) { | |
3624 if (adr.base_needs_rex()) { | |
3625 if (adr.index_needs_rex()) { | |
3626 prefix(REX_WXB); | |
3627 } else { | |
3628 prefix(REX_WB); | |
3629 } | |
3630 } else { | |
3631 if (adr.index_needs_rex()) { | |
3632 prefix(REX_WX); | |
3633 } else { | |
3634 prefix(REX_W); | |
3635 } | |
3636 } | |
3637 } else { | |
3638 if (adr.base_needs_rex()) { | |
3639 if (adr.index_needs_rex()) { | |
3640 prefix(REX_WRXB); | |
3641 } else { | |
3642 prefix(REX_WRB); | |
3643 } | |
3644 } else { | |
3645 if (adr.index_needs_rex()) { | |
3646 prefix(REX_WRX); | |
3647 } else { | |
3648 prefix(REX_WR); | |
3649 } | |
3650 } | |
3651 } | |
3652 } | |
3653 | |
3654 void Assembler::prefix(Address adr, XMMRegister reg) { | |
3655 if (reg->encoding() < 8) { | |
3656 if (adr.base_needs_rex()) { | |
3657 if (adr.index_needs_rex()) { | |
3658 prefix(REX_XB); | |
3659 } else { | |
3660 prefix(REX_B); | |
3661 } | |
3662 } else { | |
3663 if (adr.index_needs_rex()) { | |
3664 prefix(REX_X); | |
3665 } | |
3666 } | |
3667 } else { | |
3668 if (adr.base_needs_rex()) { | |
3669 if (adr.index_needs_rex()) { | |
3670 prefix(REX_RXB); | |
3671 } else { | |
3672 prefix(REX_RB); | |
3673 } | |
3674 } else { | |
3675 if (adr.index_needs_rex()) { | |
3676 prefix(REX_RX); | |
3677 } else { | |
3678 prefix(REX_R); | |
3679 } | |
3680 } | |
3681 } | |
3682 } | |
3683 | |
3684 void Assembler::adcq(Register dst, int32_t imm32) { | |
3685 (void) prefixq_and_encode(dst->encoding()); | |
3686 emit_arith(0x81, 0xD0, dst, imm32); | |
3687 } | |
3688 | |
3689 void Assembler::adcq(Register dst, Address src) { | |
3690 InstructionMark im(this); | |
3691 prefixq(src, dst); | |
3692 emit_byte(0x13); | |
3693 emit_operand(dst, src); | |
3694 } | |
3695 | |
3696 void Assembler::adcq(Register dst, Register src) { | |
3697 (int) prefixq_and_encode(dst->encoding(), src->encoding()); | |
3698 emit_arith(0x13, 0xC0, dst, src); | |
3699 } | |
3700 | |
3701 void Assembler::addq(Address dst, int32_t imm32) { | |
3702 InstructionMark im(this); | |
3703 prefixq(dst); | |
3704 emit_arith_operand(0x81, rax, dst,imm32); | |
3705 } | |
3706 | |
3707 void Assembler::addq(Address dst, Register src) { | |
3708 InstructionMark im(this); | |
3709 prefixq(dst, src); | |
3710 emit_byte(0x01); | |
3711 emit_operand(src, dst); | |
3712 } | |
3713 | |
3714 void Assembler::addq(Register dst, int32_t imm32) { | |
3715 (void) prefixq_and_encode(dst->encoding()); | |
3716 emit_arith(0x81, 0xC0, dst, imm32); | |
3717 } | |
3718 | |
3719 void Assembler::addq(Register dst, Address src) { | |
3720 InstructionMark im(this); | |
3721 prefixq(src, dst); | |
3722 emit_byte(0x03); | |
3723 emit_operand(dst, src); | |
3724 } | |
3725 | |
3726 void Assembler::addq(Register dst, Register src) { | |
3727 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
3728 emit_arith(0x03, 0xC0, dst, src); | |
3729 } | |
3730 | |
3731 void Assembler::andq(Register dst, int32_t imm32) { | |
3732 (void) prefixq_and_encode(dst->encoding()); | |
3733 emit_arith(0x81, 0xE0, dst, imm32); | |
3734 } | |
3735 | |
3736 void Assembler::andq(Register dst, Address src) { | |
3737 InstructionMark im(this); | |
3738 prefixq(src, dst); | |
3739 emit_byte(0x23); | |
3740 emit_operand(dst, src); | |
3741 } | |
3742 | |
3743 void Assembler::andq(Register dst, Register src) { | |
3744 (int) prefixq_and_encode(dst->encoding(), src->encoding()); | |
3745 emit_arith(0x23, 0xC0, dst, src); | |
3746 } | |
3747 | |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3748 void Assembler::bsfq(Register dst, Register src) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3749 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3750 emit_byte(0x0F); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3751 emit_byte(0xBC); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3752 emit_byte(0xC0 | encode); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3753 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3754 |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3755 void Assembler::bsrq(Register dst, Register src) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3756 assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT"); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3757 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3758 emit_byte(0x0F); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3759 emit_byte(0xBD); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3760 emit_byte(0xC0 | encode); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3761 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
3762 |
304 | 3763 void Assembler::bswapq(Register reg) { |
3764 int encode = prefixq_and_encode(reg->encoding()); | |
3765 emit_byte(0x0F); | |
3766 emit_byte(0xC8 | encode); | |
3767 } | |
3768 | |
3769 void Assembler::cdqq() { | |
3770 prefix(REX_W); | |
3771 emit_byte(0x99); | |
3772 } | |
3773 | |
3774 void Assembler::clflush(Address adr) { | |
3775 prefix(adr); | |
3776 emit_byte(0x0F); | |
3777 emit_byte(0xAE); | |
3778 emit_operand(rdi, adr); | |
3779 } | |
3780 | |
3781 void Assembler::cmovq(Condition cc, Register dst, Register src) { | |
3782 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3783 emit_byte(0x0F); | |
3784 emit_byte(0x40 | cc); | |
3785 emit_byte(0xC0 | encode); | |
3786 } | |
3787 | |
3788 void Assembler::cmovq(Condition cc, Register dst, Address src) { | |
3789 InstructionMark im(this); | |
3790 prefixq(src, dst); | |
3791 emit_byte(0x0F); | |
3792 emit_byte(0x40 | cc); | |
3793 emit_operand(dst, src); | |
3794 } | |
3795 | |
3796 void Assembler::cmpq(Address dst, int32_t imm32) { | |
3797 InstructionMark im(this); | |
3798 prefixq(dst); | |
3799 emit_byte(0x81); | |
3800 emit_operand(rdi, dst, 4); | |
3801 emit_long(imm32); | |
3802 } | |
3803 | |
3804 void Assembler::cmpq(Register dst, int32_t imm32) { | |
3805 (void) prefixq_and_encode(dst->encoding()); | |
3806 emit_arith(0x81, 0xF8, dst, imm32); | |
3807 } | |
3808 | |
3809 void Assembler::cmpq(Address dst, Register src) { | |
3810 InstructionMark im(this); | |
3811 prefixq(dst, src); | |
3812 emit_byte(0x3B); | |
3813 emit_operand(src, dst); | |
3814 } | |
3815 | |
3816 void Assembler::cmpq(Register dst, Register src) { | |
3817 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
3818 emit_arith(0x3B, 0xC0, dst, src); | |
3819 } | |
3820 | |
3821 void Assembler::cmpq(Register dst, Address src) { | |
3822 InstructionMark im(this); | |
3823 prefixq(src, dst); | |
3824 emit_byte(0x3B); | |
3825 emit_operand(dst, src); | |
3826 } | |
3827 | |
3828 void Assembler::cmpxchgq(Register reg, Address adr) { | |
3829 InstructionMark im(this); | |
3830 prefixq(adr, reg); | |
3831 emit_byte(0x0F); | |
3832 emit_byte(0xB1); | |
3833 emit_operand(reg, adr); | |
3834 } | |
3835 | |
3836 void Assembler::cvtsi2sdq(XMMRegister dst, Register src) { | |
3837 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
3838 emit_byte(0xF2); | |
3839 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3840 emit_byte(0x0F); | |
3841 emit_byte(0x2A); | |
3842 emit_byte(0xC0 | encode); | |
3843 } | |
3844 | |
3845 void Assembler::cvtsi2ssq(XMMRegister dst, Register src) { | |
3846 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
3847 emit_byte(0xF3); | |
3848 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3849 emit_byte(0x0F); | |
3850 emit_byte(0x2A); | |
3851 emit_byte(0xC0 | encode); | |
3852 } | |
3853 | |
3854 void Assembler::cvttsd2siq(Register dst, XMMRegister src) { | |
3855 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
3856 emit_byte(0xF2); | |
3857 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3858 emit_byte(0x0F); | |
3859 emit_byte(0x2C); | |
3860 emit_byte(0xC0 | encode); | |
3861 } | |
3862 | |
3863 void Assembler::cvttss2siq(Register dst, XMMRegister src) { | |
3864 NOT_LP64(assert(VM_Version::supports_sse(), "")); | |
3865 emit_byte(0xF3); | |
3866 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3867 emit_byte(0x0F); | |
3868 emit_byte(0x2C); | |
3869 emit_byte(0xC0 | encode); | |
3870 } | |
3871 | |
3872 void Assembler::decl(Register dst) { | |
3873 // Don't use it directly. Use MacroAssembler::decrementl() instead. | |
3874 // Use two-byte form (one-byte form is a REX prefix in 64-bit mode) | |
3875 int encode = prefix_and_encode(dst->encoding()); | |
3876 emit_byte(0xFF); | |
3877 emit_byte(0xC8 | encode); | |
3878 } | |
3879 | |
3880 void Assembler::decq(Register dst) { | |
3881 // Don't use it directly. Use MacroAssembler::decrementq() instead. | |
3882 // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) | |
3883 int encode = prefixq_and_encode(dst->encoding()); | |
3884 emit_byte(0xFF); | |
3885 emit_byte(0xC8 | encode); | |
3886 } | |
3887 | |
3888 void Assembler::decq(Address dst) { | |
3889 // Don't use it directly. Use MacroAssembler::decrementq() instead. | |
3890 InstructionMark im(this); | |
3891 prefixq(dst); | |
3892 emit_byte(0xFF); | |
3893 emit_operand(rcx, dst); | |
3894 } | |
3895 | |
3896 void Assembler::fxrstor(Address src) { | |
3897 prefixq(src); | |
3898 emit_byte(0x0F); | |
3899 emit_byte(0xAE); | |
3900 emit_operand(as_Register(1), src); | |
3901 } | |
3902 | |
3903 void Assembler::fxsave(Address dst) { | |
3904 prefixq(dst); | |
3905 emit_byte(0x0F); | |
3906 emit_byte(0xAE); | |
3907 emit_operand(as_Register(0), dst); | |
3908 } | |
3909 | |
3910 void Assembler::idivq(Register src) { | |
3911 int encode = prefixq_and_encode(src->encoding()); | |
3912 emit_byte(0xF7); | |
3913 emit_byte(0xF8 | encode); | |
3914 } | |
3915 | |
3916 void Assembler::imulq(Register dst, Register src) { | |
3917 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3918 emit_byte(0x0F); | |
3919 emit_byte(0xAF); | |
3920 emit_byte(0xC0 | encode); | |
3921 } | |
3922 | |
3923 void Assembler::imulq(Register dst, Register src, int value) { | |
3924 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
3925 if (is8bit(value)) { | |
3926 emit_byte(0x6B); | |
3927 emit_byte(0xC0 | encode); | |
1914
ae065c367d93
6987135: Performance regression on Intel platform with 32-bits edition between 6u13 and 6u14.
kvn
parents:
1846
diff
changeset
|
3928 emit_byte(value & 0xFF); |
304 | 3929 } else { |
3930 emit_byte(0x69); | |
3931 emit_byte(0xC0 | encode); | |
3932 emit_long(value); | |
3933 } | |
3934 } | |
3935 | |
3936 void Assembler::incl(Register dst) { | |
3937 // Don't use it directly. Use MacroAssembler::incrementl() instead. | |
3938 // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) | |
3939 int encode = prefix_and_encode(dst->encoding()); | |
3940 emit_byte(0xFF); | |
3941 emit_byte(0xC0 | encode); | |
3942 } | |
3943 | |
3944 void Assembler::incq(Register dst) { | |
3945 // Don't use it directly. Use MacroAssembler::incrementq() instead. | |
3946 // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) | |
3947 int encode = prefixq_and_encode(dst->encoding()); | |
3948 emit_byte(0xFF); | |
3949 emit_byte(0xC0 | encode); | |
3950 } | |
3951 | |
3952 void Assembler::incq(Address dst) { | |
3953 // Don't use it directly. Use MacroAssembler::incrementq() instead. | |
3954 InstructionMark im(this); | |
3955 prefixq(dst); | |
3956 emit_byte(0xFF); | |
3957 emit_operand(rax, dst); | |
3958 } | |
3959 | |
3960 void Assembler::lea(Register dst, Address src) { | |
3961 leaq(dst, src); | |
3962 } | |
3963 | |
3964 void Assembler::leaq(Register dst, Address src) { | |
3965 InstructionMark im(this); | |
3966 prefixq(src, dst); | |
3967 emit_byte(0x8D); | |
3968 emit_operand(dst, src); | |
3969 } | |
3970 | |
3971 void Assembler::mov64(Register dst, int64_t imm64) { | |
3972 InstructionMark im(this); | |
3973 int encode = prefixq_and_encode(dst->encoding()); | |
3974 emit_byte(0xB8 | encode); | |
3975 emit_long64(imm64); | |
3976 } | |
3977 | |
3978 void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec) { | |
3979 InstructionMark im(this); | |
3980 int encode = prefixq_and_encode(dst->encoding()); | |
3981 emit_byte(0xB8 | encode); | |
3982 emit_data64(imm64, rspec); | |
3983 } | |
3984 | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3985 void Assembler::mov_narrow_oop(Register dst, int32_t imm32, RelocationHolder const& rspec) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3986 InstructionMark im(this); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3987 int encode = prefix_and_encode(dst->encoding()); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3988 emit_byte(0xB8 | encode); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3989 emit_data((int)imm32, rspec, narrow_oop_operand); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3990 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3991 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3992 void Assembler::mov_narrow_oop(Address dst, int32_t imm32, RelocationHolder const& rspec) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3993 InstructionMark im(this); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3994 prefix(dst); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3995 emit_byte(0xC7); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3996 emit_operand(rax, dst, 4); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3997 emit_data((int)imm32, rspec, narrow_oop_operand); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3998 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
3999 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4000 void Assembler::cmp_narrow_oop(Register src1, int32_t imm32, RelocationHolder const& rspec) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4001 InstructionMark im(this); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4002 int encode = prefix_and_encode(src1->encoding()); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4003 emit_byte(0x81); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4004 emit_byte(0xF8 | encode); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4005 emit_data((int)imm32, rspec, narrow_oop_operand); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4006 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4007 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4008 void Assembler::cmp_narrow_oop(Address src1, int32_t imm32, RelocationHolder const& rspec) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4009 InstructionMark im(this); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4010 prefix(src1); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4011 emit_byte(0x81); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4012 emit_operand(rax, src1, 4); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4013 emit_data((int)imm32, rspec, narrow_oop_operand); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4014 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
4015 |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4016 void Assembler::lzcntq(Register dst, Register src) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4017 assert(VM_Version::supports_lzcnt(), "encoding is treated as BSR"); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4018 emit_byte(0xF3); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4019 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4020 emit_byte(0x0F); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4021 emit_byte(0xBD); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4022 emit_byte(0xC0 | encode); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4023 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
710
diff
changeset
|
4024 |
304 | 4025 void Assembler::movdq(XMMRegister dst, Register src) { |
4026 // table D-1 says MMX/SSE2 | |
4027 NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); | |
0 | 4028 emit_byte(0x66); |
304 | 4029 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); |
0 | 4030 emit_byte(0x0F); |
304 | 4031 emit_byte(0x6E); |
4032 emit_byte(0xC0 | encode); | |
4033 } | |
4034 | |
4035 void Assembler::movdq(Register dst, XMMRegister src) { | |
4036 // table D-1 says MMX/SSE2 | |
4037 NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); | |
0 | 4038 emit_byte(0x66); |
304 | 4039 // swap src/dst to get correct prefix |
4040 int encode = prefixq_and_encode(src->encoding(), dst->encoding()); | |
0 | 4041 emit_byte(0x0F); |
4042 emit_byte(0x7E); | |
304 | 4043 emit_byte(0xC0 | encode); |
4044 } | |
4045 | |
4046 void Assembler::movq(Register dst, Register src) { | |
4047 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4048 emit_byte(0x8B); | |
4049 emit_byte(0xC0 | encode); | |
4050 } | |
4051 | |
4052 void Assembler::movq(Register dst, Address src) { | |
4053 InstructionMark im(this); | |
4054 prefixq(src, dst); | |
4055 emit_byte(0x8B); | |
4056 emit_operand(dst, src); | |
4057 } | |
4058 | |
4059 void Assembler::movq(Address dst, Register src) { | |
4060 InstructionMark im(this); | |
4061 prefixq(dst, src); | |
4062 emit_byte(0x89); | |
4063 emit_operand(src, dst); | |
4064 } | |
4065 | |
624 | 4066 void Assembler::movsbq(Register dst, Address src) { |
4067 InstructionMark im(this); | |
4068 prefixq(src, dst); | |
4069 emit_byte(0x0F); | |
4070 emit_byte(0xBE); | |
4071 emit_operand(dst, src); | |
4072 } | |
4073 | |
4074 void Assembler::movsbq(Register dst, Register src) { | |
4075 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4076 emit_byte(0x0F); | |
4077 emit_byte(0xBE); | |
4078 emit_byte(0xC0 | encode); | |
4079 } | |
4080 | |
304 | 4081 void Assembler::movslq(Register dst, int32_t imm32) { |
4082 // dbx shows movslq(rcx, 3) as movq $0x0000000049000000,(%rbx) | |
4083 // and movslq(r8, 3); as movl $0x0000000048000000,(%rbx) | |
4084 // as a result we shouldn't use until tested at runtime... | |
4085 ShouldNotReachHere(); | |
4086 InstructionMark im(this); | |
4087 int encode = prefixq_and_encode(dst->encoding()); | |
4088 emit_byte(0xC7 | encode); | |
4089 emit_long(imm32); | |
4090 } | |
4091 | |
4092 void Assembler::movslq(Address dst, int32_t imm32) { | |
4093 assert(is_simm32(imm32), "lost bits"); | |
4094 InstructionMark im(this); | |
4095 prefixq(dst); | |
4096 emit_byte(0xC7); | |
4097 emit_operand(rax, dst, 4); | |
4098 emit_long(imm32); | |
4099 } | |
4100 | |
4101 void Assembler::movslq(Register dst, Address src) { | |
4102 InstructionMark im(this); | |
4103 prefixq(src, dst); | |
4104 emit_byte(0x63); | |
4105 emit_operand(dst, src); | |
4106 } | |
4107 | |
4108 void Assembler::movslq(Register dst, Register src) { | |
4109 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4110 emit_byte(0x63); | |
4111 emit_byte(0xC0 | encode); | |
4112 } | |
4113 | |
624 | 4114 void Assembler::movswq(Register dst, Address src) { |
4115 InstructionMark im(this); | |
4116 prefixq(src, dst); | |
4117 emit_byte(0x0F); | |
4118 emit_byte(0xBF); | |
4119 emit_operand(dst, src); | |
4120 } | |
4121 | |
4122 void Assembler::movswq(Register dst, Register src) { | |
4123 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4124 emit_byte(0x0F); | |
4125 emit_byte(0xBF); | |
4126 emit_byte(0xC0 | encode); | |
4127 } | |
4128 | |
4129 void Assembler::movzbq(Register dst, Address src) { | |
4130 InstructionMark im(this); | |
4131 prefixq(src, dst); | |
4132 emit_byte(0x0F); | |
4133 emit_byte(0xB6); | |
4134 emit_operand(dst, src); | |
4135 } | |
4136 | |
4137 void Assembler::movzbq(Register dst, Register src) { | |
4138 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4139 emit_byte(0x0F); | |
4140 emit_byte(0xB6); | |
4141 emit_byte(0xC0 | encode); | |
4142 } | |
4143 | |
4144 void Assembler::movzwq(Register dst, Address src) { | |
4145 InstructionMark im(this); | |
4146 prefixq(src, dst); | |
4147 emit_byte(0x0F); | |
4148 emit_byte(0xB7); | |
4149 emit_operand(dst, src); | |
4150 } | |
4151 | |
4152 void Assembler::movzwq(Register dst, Register src) { | |
4153 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4154 emit_byte(0x0F); | |
4155 emit_byte(0xB7); | |
4156 emit_byte(0xC0 | encode); | |
4157 } | |
4158 | |
304 | 4159 void Assembler::negq(Register dst) { |
4160 int encode = prefixq_and_encode(dst->encoding()); | |
4161 emit_byte(0xF7); | |
4162 emit_byte(0xD8 | encode); | |
4163 } | |
4164 | |
4165 void Assembler::notq(Register dst) { | |
4166 int encode = prefixq_and_encode(dst->encoding()); | |
4167 emit_byte(0xF7); | |
4168 emit_byte(0xD0 | encode); | |
4169 } | |
4170 | |
4171 void Assembler::orq(Address dst, int32_t imm32) { | |
4172 InstructionMark im(this); | |
4173 prefixq(dst); | |
4174 emit_byte(0x81); | |
4175 emit_operand(rcx, dst, 4); | |
4176 emit_long(imm32); | |
4177 } | |
4178 | |
4179 void Assembler::orq(Register dst, int32_t imm32) { | |
4180 (void) prefixq_and_encode(dst->encoding()); | |
4181 emit_arith(0x81, 0xC8, dst, imm32); | |
4182 } | |
4183 | |
4184 void Assembler::orq(Register dst, Address src) { | |
4185 InstructionMark im(this); | |
4186 prefixq(src, dst); | |
4187 emit_byte(0x0B); | |
4188 emit_operand(dst, src); | |
4189 } | |
4190 | |
4191 void Assembler::orq(Register dst, Register src) { | |
4192 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
4193 emit_arith(0x0B, 0xC0, dst, src); | |
4194 } | |
4195 | |
4196 void Assembler::popa() { // 64bit | |
4197 movq(r15, Address(rsp, 0)); | |
4198 movq(r14, Address(rsp, wordSize)); | |
4199 movq(r13, Address(rsp, 2 * wordSize)); | |
4200 movq(r12, Address(rsp, 3 * wordSize)); | |
4201 movq(r11, Address(rsp, 4 * wordSize)); | |
4202 movq(r10, Address(rsp, 5 * wordSize)); | |
4203 movq(r9, Address(rsp, 6 * wordSize)); | |
4204 movq(r8, Address(rsp, 7 * wordSize)); | |
4205 movq(rdi, Address(rsp, 8 * wordSize)); | |
4206 movq(rsi, Address(rsp, 9 * wordSize)); | |
4207 movq(rbp, Address(rsp, 10 * wordSize)); | |
4208 // skip rsp | |
4209 movq(rbx, Address(rsp, 12 * wordSize)); | |
4210 movq(rdx, Address(rsp, 13 * wordSize)); | |
4211 movq(rcx, Address(rsp, 14 * wordSize)); | |
4212 movq(rax, Address(rsp, 15 * wordSize)); | |
4213 | |
4214 addq(rsp, 16 * wordSize); | |
4215 } | |
4216 | |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4217 void Assembler::popcntq(Register dst, Address src) { |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4218 assert(VM_Version::supports_popcnt(), "must support"); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4219 InstructionMark im(this); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4220 emit_byte(0xF3); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4221 prefixq(src, dst); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4222 emit_byte(0x0F); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4223 emit_byte(0xB8); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4224 emit_operand(dst, src); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4225 } |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4226 |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4227 void Assembler::popcntq(Register dst, Register src) { |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4228 assert(VM_Version::supports_popcnt(), "must support"); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4229 emit_byte(0xF3); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4230 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4231 emit_byte(0x0F); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4232 emit_byte(0xB8); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4233 emit_byte(0xC0 | encode); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4234 } |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
642
diff
changeset
|
4235 |
304 | 4236 void Assembler::popq(Address dst) { |
4237 InstructionMark im(this); | |
4238 prefixq(dst); | |
4239 emit_byte(0x8F); | |
4240 emit_operand(rax, dst); | |
4241 } | |
4242 | |
4243 void Assembler::pusha() { // 64bit | |
4244 // we have to store original rsp. ABI says that 128 bytes | |
4245 // below rsp are local scratch. | |
4246 movq(Address(rsp, -5 * wordSize), rsp); | |
4247 | |
4248 subq(rsp, 16 * wordSize); | |
4249 | |
4250 movq(Address(rsp, 15 * wordSize), rax); | |
4251 movq(Address(rsp, 14 * wordSize), rcx); | |
4252 movq(Address(rsp, 13 * wordSize), rdx); | |
4253 movq(Address(rsp, 12 * wordSize), rbx); | |
4254 // skip rsp | |
4255 movq(Address(rsp, 10 * wordSize), rbp); | |
4256 movq(Address(rsp, 9 * wordSize), rsi); | |
4257 movq(Address(rsp, 8 * wordSize), rdi); | |
4258 movq(Address(rsp, 7 * wordSize), r8); | |
4259 movq(Address(rsp, 6 * wordSize), r9); | |
4260 movq(Address(rsp, 5 * wordSize), r10); | |
4261 movq(Address(rsp, 4 * wordSize), r11); | |
4262 movq(Address(rsp, 3 * wordSize), r12); | |
4263 movq(Address(rsp, 2 * wordSize), r13); | |
4264 movq(Address(rsp, wordSize), r14); | |
4265 movq(Address(rsp, 0), r15); | |
4266 } | |
4267 | |
4268 void Assembler::pushq(Address src) { | |
4269 InstructionMark im(this); | |
4270 prefixq(src); | |
4271 emit_byte(0xFF); | |
4272 emit_operand(rsi, src); | |
4273 } | |
4274 | |
4275 void Assembler::rclq(Register dst, int imm8) { | |
4276 assert(isShiftCount(imm8 >> 1), "illegal shift count"); | |
4277 int encode = prefixq_and_encode(dst->encoding()); | |
4278 if (imm8 == 1) { | |
4279 emit_byte(0xD1); | |
4280 emit_byte(0xD0 | encode); | |
4281 } else { | |
4282 emit_byte(0xC1); | |
4283 emit_byte(0xD0 | encode); | |
4284 emit_byte(imm8); | |
4285 } | |
4286 } | |
4287 void Assembler::sarq(Register dst, int imm8) { | |
4288 assert(isShiftCount(imm8 >> 1), "illegal shift count"); | |
4289 int encode = prefixq_and_encode(dst->encoding()); | |
4290 if (imm8 == 1) { | |
4291 emit_byte(0xD1); | |
4292 emit_byte(0xF8 | encode); | |
4293 } else { | |
4294 emit_byte(0xC1); | |
4295 emit_byte(0xF8 | encode); | |
4296 emit_byte(imm8); | |
4297 } | |
4298 } | |
4299 | |
4300 void Assembler::sarq(Register dst) { | |
4301 int encode = prefixq_and_encode(dst->encoding()); | |
4302 emit_byte(0xD3); | |
4303 emit_byte(0xF8 | encode); | |
4304 } | |
4305 void Assembler::sbbq(Address dst, int32_t imm32) { | |
4306 InstructionMark im(this); | |
4307 prefixq(dst); | |
4308 emit_arith_operand(0x81, rbx, dst, imm32); | |
4309 } | |
4310 | |
4311 void Assembler::sbbq(Register dst, int32_t imm32) { | |
4312 (void) prefixq_and_encode(dst->encoding()); | |
4313 emit_arith(0x81, 0xD8, dst, imm32); | |
4314 } | |
4315 | |
4316 void Assembler::sbbq(Register dst, Address src) { | |
4317 InstructionMark im(this); | |
4318 prefixq(src, dst); | |
4319 emit_byte(0x1B); | |
4320 emit_operand(dst, src); | |
4321 } | |
4322 | |
4323 void Assembler::sbbq(Register dst, Register src) { | |
4324 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
4325 emit_arith(0x1B, 0xC0, dst, src); | |
4326 } | |
4327 | |
4328 void Assembler::shlq(Register dst, int imm8) { | |
4329 assert(isShiftCount(imm8 >> 1), "illegal shift count"); | |
4330 int encode = prefixq_and_encode(dst->encoding()); | |
4331 if (imm8 == 1) { | |
4332 emit_byte(0xD1); | |
4333 emit_byte(0xE0 | encode); | |
4334 } else { | |
4335 emit_byte(0xC1); | |
4336 emit_byte(0xE0 | encode); | |
4337 emit_byte(imm8); | |
4338 } | |
4339 } | |
4340 | |
4341 void Assembler::shlq(Register dst) { | |
4342 int encode = prefixq_and_encode(dst->encoding()); | |
4343 emit_byte(0xD3); | |
4344 emit_byte(0xE0 | encode); | |
4345 } | |
4346 | |
4347 void Assembler::shrq(Register dst, int imm8) { | |
4348 assert(isShiftCount(imm8 >> 1), "illegal shift count"); | |
4349 int encode = prefixq_and_encode(dst->encoding()); | |
4350 emit_byte(0xC1); | |
4351 emit_byte(0xE8 | encode); | |
4352 emit_byte(imm8); | |
4353 } | |
4354 | |
4355 void Assembler::shrq(Register dst) { | |
4356 int encode = prefixq_and_encode(dst->encoding()); | |
4357 emit_byte(0xD3); | |
4358 emit_byte(0xE8 | encode); | |
4359 } | |
4360 | |
4361 void Assembler::sqrtsd(XMMRegister dst, Address src) { | |
4362 NOT_LP64(assert(VM_Version::supports_sse2(), "")); | |
0 | 4363 InstructionMark im(this); |
4364 emit_byte(0xF2); | |
304 | 4365 prefix(src, dst); |
0 | 4366 emit_byte(0x0F); |
304 | 4367 emit_byte(0x51); |
4368 emit_operand(dst, src); | |
4369 } | |
4370 | |
4371 void Assembler::subq(Address dst, int32_t imm32) { | |
4372 InstructionMark im(this); | |
4373 prefixq(dst); | |
4374 if (is8bit(imm32)) { | |
4375 emit_byte(0x83); | |
4376 emit_operand(rbp, dst, 1); | |
4377 emit_byte(imm32 & 0xFF); | |
4378 } else { | |
4379 emit_byte(0x81); | |
4380 emit_operand(rbp, dst, 4); | |
4381 emit_long(imm32); | |
4382 } | |
4383 } | |
4384 | |
4385 void Assembler::subq(Register dst, int32_t imm32) { | |
4386 (void) prefixq_and_encode(dst->encoding()); | |
4387 emit_arith(0x81, 0xE8, dst, imm32); | |
4388 } | |
4389 | |
4390 void Assembler::subq(Address dst, Register src) { | |
4391 InstructionMark im(this); | |
4392 prefixq(dst, src); | |
4393 emit_byte(0x29); | |
4394 emit_operand(src, dst); | |
4395 } | |
4396 | |
4397 void Assembler::subq(Register dst, Address src) { | |
4398 InstructionMark im(this); | |
4399 prefixq(src, dst); | |
4400 emit_byte(0x2B); | |
4401 emit_operand(dst, src); | |
4402 } | |
4403 | |
4404 void Assembler::subq(Register dst, Register src) { | |
4405 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
4406 emit_arith(0x2B, 0xC0, dst, src); | |
4407 } | |
4408 | |
4409 void Assembler::testq(Register dst, int32_t imm32) { | |
4410 // not using emit_arith because test | |
4411 // doesn't support sign-extension of | |
4412 // 8bit operands | |
4413 int encode = dst->encoding(); | |
4414 if (encode == 0) { | |
4415 prefix(REX_W); | |
4416 emit_byte(0xA9); | |
4417 } else { | |
4418 encode = prefixq_and_encode(encode); | |
4419 emit_byte(0xF7); | |
4420 emit_byte(0xC0 | encode); | |
4421 } | |
4422 emit_long(imm32); | |
4423 } | |
4424 | |
4425 void Assembler::testq(Register dst, Register src) { | |
4426 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
4427 emit_arith(0x85, 0xC0, dst, src); | |
4428 } | |
4429 | |
4430 void Assembler::xaddq(Address dst, Register src) { | |
4431 InstructionMark im(this); | |
4432 prefixq(dst, src); | |
71 | 4433 emit_byte(0x0F); |
304 | 4434 emit_byte(0xC1); |
4435 emit_operand(src, dst); | |
4436 } | |
4437 | |
4438 void Assembler::xchgq(Register dst, Address src) { | |
4439 InstructionMark im(this); | |
4440 prefixq(src, dst); | |
4441 emit_byte(0x87); | |
4442 emit_operand(dst, src); | |
4443 } | |
4444 | |
4445 void Assembler::xchgq(Register dst, Register src) { | |
4446 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4447 emit_byte(0x87); | |
4448 emit_byte(0xc0 | encode); | |
4449 } | |
4450 | |
4451 void Assembler::xorq(Register dst, Register src) { | |
4452 (void) prefixq_and_encode(dst->encoding(), src->encoding()); | |
4453 emit_arith(0x33, 0xC0, dst, src); | |
4454 } | |
4455 | |
4456 void Assembler::xorq(Register dst, Address src) { | |
4457 InstructionMark im(this); | |
4458 prefixq(src, dst); | |
4459 emit_byte(0x33); | |
4460 emit_operand(dst, src); | |
4461 } | |
4462 | |
4463 #endif // !LP64 | |
4464 | |
4465 static Assembler::Condition reverse[] = { | |
4466 Assembler::noOverflow /* overflow = 0x0 */ , | |
4467 Assembler::overflow /* noOverflow = 0x1 */ , | |
4468 Assembler::aboveEqual /* carrySet = 0x2, below = 0x2 */ , | |
4469 Assembler::below /* aboveEqual = 0x3, carryClear = 0x3 */ , | |
4470 Assembler::notZero /* zero = 0x4, equal = 0x4 */ , | |
4471 Assembler::zero /* notZero = 0x5, notEqual = 0x5 */ , | |
4472 Assembler::above /* belowEqual = 0x6 */ , | |
4473 Assembler::belowEqual /* above = 0x7 */ , | |
4474 Assembler::positive /* negative = 0x8 */ , | |
4475 Assembler::negative /* positive = 0x9 */ , | |
4476 Assembler::noParity /* parity = 0xa */ , | |
4477 Assembler::parity /* noParity = 0xb */ , | |
4478 Assembler::greaterEqual /* less = 0xc */ , | |
4479 Assembler::less /* greaterEqual = 0xd */ , | |
4480 Assembler::greater /* lessEqual = 0xe */ , | |
4481 Assembler::lessEqual /* greater = 0xf, */ | |
4482 | |
4483 }; | |
4484 | |
0 | 4485 |
4486 // Implementation of MacroAssembler | |
4487 | |
304 | 4488 // First all the versions that have distinct versions depending on 32/64 bit |
4489 // Unless the difference is trivial (1 line or so). | |
4490 | |
4491 #ifndef _LP64 | |
4492 | |
4493 // 32bit versions | |
4494 | |
0 | 4495 Address MacroAssembler::as_Address(AddressLiteral adr) { |
4496 return Address(adr.target(), adr.rspec()); | |
4497 } | |
4498 | |
4499 Address MacroAssembler::as_Address(ArrayAddress adr) { | |
4500 return Address::make_array(adr); | |
4501 } | |
4502 | |
304 | 4503 int MacroAssembler::biased_locking_enter(Register lock_reg, |
4504 Register obj_reg, | |
4505 Register swap_reg, | |
4506 Register tmp_reg, | |
4507 bool swap_reg_contains_mark, | |
4508 Label& done, | |
4509 Label* slow_case, | |
4510 BiasedLockingCounters* counters) { | |
4511 assert(UseBiasedLocking, "why call this otherwise?"); | |
4512 assert(swap_reg == rax, "swap_reg must be rax, for cmpxchg"); | |
4513 assert_different_registers(lock_reg, obj_reg, swap_reg); | |
4514 | |
4515 if (PrintBiasedLockingStatistics && counters == NULL) | |
4516 counters = BiasedLocking::counters(); | |
4517 | |
4518 bool need_tmp_reg = false; | |
4519 if (tmp_reg == noreg) { | |
4520 need_tmp_reg = true; | |
4521 tmp_reg = lock_reg; | |
4522 } else { | |
4523 assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); | |
4524 } | |
4525 assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); | |
4526 Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); | |
4527 Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); | |
4528 Address saved_mark_addr(lock_reg, 0); | |
4529 | |
4530 // Biased locking | |
4531 // See whether the lock is currently biased toward our thread and | |
4532 // whether the epoch is still valid | |
4533 // Note that the runtime guarantees sufficient alignment of JavaThread | |
4534 // pointers to allow age to be placed into low bits | |
4535 // First check to see whether biasing is even enabled for this object | |
4536 Label cas_label; | |
4537 int null_check_offset = -1; | |
4538 if (!swap_reg_contains_mark) { | |
4539 null_check_offset = offset(); | |
4540 movl(swap_reg, mark_addr); | |
4541 } | |
4542 if (need_tmp_reg) { | |
4543 push(tmp_reg); | |
4544 } | |
4545 movl(tmp_reg, swap_reg); | |
4546 andl(tmp_reg, markOopDesc::biased_lock_mask_in_place); | |
4547 cmpl(tmp_reg, markOopDesc::biased_lock_pattern); | |
4548 if (need_tmp_reg) { | |
4549 pop(tmp_reg); | |
4550 } | |
4551 jcc(Assembler::notEqual, cas_label); | |
4552 // The bias pattern is present in the object's header. Need to check | |
4553 // whether the bias owner and the epoch are both still current. | |
4554 // Note that because there is no current thread register on x86 we | |
4555 // need to store off the mark word we read out of the object to | |
4556 // avoid reloading it and needing to recheck invariants below. This | |
4557 // store is unfortunate but it makes the overall code shorter and | |
4558 // simpler. | |
4559 movl(saved_mark_addr, swap_reg); | |
4560 if (need_tmp_reg) { | |
4561 push(tmp_reg); | |
4562 } | |
4563 get_thread(tmp_reg); | |
4564 xorl(swap_reg, tmp_reg); | |
4565 if (swap_reg_contains_mark) { | |
4566 null_check_offset = offset(); | |
4567 } | |
4568 movl(tmp_reg, klass_addr); | |
4569 xorl(swap_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | |
4570 andl(swap_reg, ~((int) markOopDesc::age_mask_in_place)); | |
4571 if (need_tmp_reg) { | |
4572 pop(tmp_reg); | |
4573 } | |
4574 if (counters != NULL) { | |
4575 cond_inc32(Assembler::zero, | |
4576 ExternalAddress((address)counters->biased_lock_entry_count_addr())); | |
4577 } | |
4578 jcc(Assembler::equal, done); | |
4579 | |
4580 Label try_revoke_bias; | |
4581 Label try_rebias; | |
4582 | |
4583 // At this point we know that the header has the bias pattern and | |
4584 // that we are not the bias owner in the current epoch. We need to | |
4585 // figure out more details about the state of the header in order to | |
4586 // know what operations can be legally performed on the object's | |
4587 // header. | |
4588 | |
4589 // If the low three bits in the xor result aren't clear, that means | |
4590 // the prototype header is no longer biased and we have to revoke | |
4591 // the bias on this object. | |
4592 testl(swap_reg, markOopDesc::biased_lock_mask_in_place); | |
4593 jcc(Assembler::notZero, try_revoke_bias); | |
4594 | |
4595 // Biasing is still enabled for this data type. See whether the | |
4596 // epoch of the current bias is still valid, meaning that the epoch | |
4597 // bits of the mark word are equal to the epoch bits of the | |
4598 // prototype header. (Note that the prototype header's epoch bits | |
4599 // only change at a safepoint.) If not, attempt to rebias the object | |
4600 // toward the current thread. Note that we must be absolutely sure | |
4601 // that the current epoch is invalid in order to do this because | |
4602 // otherwise the manipulations it performs on the mark word are | |
4603 // illegal. | |
4604 testl(swap_reg, markOopDesc::epoch_mask_in_place); | |
4605 jcc(Assembler::notZero, try_rebias); | |
4606 | |
4607 // The epoch of the current bias is still valid but we know nothing | |
4608 // about the owner; it might be set or it might be clear. Try to | |
4609 // acquire the bias of the object using an atomic operation. If this | |
4610 // fails we will go in to the runtime to revoke the object's bias. | |
4611 // Note that we first construct the presumed unbiased header so we | |
4612 // don't accidentally blow away another thread's valid bias. | |
4613 movl(swap_reg, saved_mark_addr); | |
4614 andl(swap_reg, | |
4615 markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); | |
4616 if (need_tmp_reg) { | |
4617 push(tmp_reg); | |
4618 } | |
4619 get_thread(tmp_reg); | |
4620 orl(tmp_reg, swap_reg); | |
4621 if (os::is_MP()) { | |
4622 lock(); | |
4623 } | |
4624 cmpxchgptr(tmp_reg, Address(obj_reg, 0)); | |
4625 if (need_tmp_reg) { | |
4626 pop(tmp_reg); | |
4627 } | |
4628 // If the biasing toward our thread failed, this means that | |
4629 // another thread succeeded in biasing it toward itself and we | |
4630 // need to revoke that bias. The revocation will occur in the | |
4631 // interpreter runtime in the slow case. | |
4632 if (counters != NULL) { | |
4633 cond_inc32(Assembler::zero, | |
4634 ExternalAddress((address)counters->anonymously_biased_lock_entry_count_addr())); | |
4635 } | |
4636 if (slow_case != NULL) { | |
4637 jcc(Assembler::notZero, *slow_case); | |
4638 } | |
4639 jmp(done); | |
4640 | |
4641 bind(try_rebias); | |
4642 // At this point we know the epoch has expired, meaning that the | |
4643 // current "bias owner", if any, is actually invalid. Under these | |
4644 // circumstances _only_, we are allowed to use the current header's | |
4645 // value as the comparison value when doing the cas to acquire the | |
4646 // bias in the current epoch. In other words, we allow transfer of | |
4647 // the bias from one thread to another directly in this situation. | |
4648 // | |
4649 // FIXME: due to a lack of registers we currently blow away the age | |
4650 // bits in this situation. Should attempt to preserve them. | |
4651 if (need_tmp_reg) { | |
4652 push(tmp_reg); | |
4653 } | |
4654 get_thread(tmp_reg); | |
4655 movl(swap_reg, klass_addr); | |
4656 orl(tmp_reg, Address(swap_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | |
4657 movl(swap_reg, saved_mark_addr); | |
4658 if (os::is_MP()) { | |
4659 lock(); | |
4660 } | |
4661 cmpxchgptr(tmp_reg, Address(obj_reg, 0)); | |
4662 if (need_tmp_reg) { | |
4663 pop(tmp_reg); | |
4664 } | |
4665 // If the biasing toward our thread failed, then another thread | |
4666 // succeeded in biasing it toward itself and we need to revoke that | |
4667 // bias. The revocation will occur in the runtime in the slow case. | |
4668 if (counters != NULL) { | |
4669 cond_inc32(Assembler::zero, | |
4670 ExternalAddress((address)counters->rebiased_lock_entry_count_addr())); | |
4671 } | |
4672 if (slow_case != NULL) { | |
4673 jcc(Assembler::notZero, *slow_case); | |
4674 } | |
4675 jmp(done); | |
4676 | |
4677 bind(try_revoke_bias); | |
4678 // The prototype mark in the klass doesn't have the bias bit set any | |
4679 // more, indicating that objects of this data type are not supposed | |
4680 // to be biased any more. We are going to try to reset the mark of | |
4681 // this object to the prototype value and fall through to the | |
4682 // CAS-based locking scheme. Note that if our CAS fails, it means | |
4683 // that another thread raced us for the privilege of revoking the | |
4684 // bias of this particular object, so it's okay to continue in the | |
4685 // normal locking code. | |
4686 // | |
4687 // FIXME: due to a lack of registers we currently blow away the age | |
4688 // bits in this situation. Should attempt to preserve them. | |
4689 movl(swap_reg, saved_mark_addr); | |
4690 if (need_tmp_reg) { | |
4691 push(tmp_reg); | |
4692 } | |
4693 movl(tmp_reg, klass_addr); | |
4694 movl(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | |
4695 if (os::is_MP()) { | |
4696 lock(); | |
4697 } | |
4698 cmpxchgptr(tmp_reg, Address(obj_reg, 0)); | |
4699 if (need_tmp_reg) { | |
4700 pop(tmp_reg); | |
4701 } | |
4702 // Fall through to the normal CAS-based lock, because no matter what | |
4703 // the result of the above CAS, some thread must have succeeded in | |
4704 // removing the bias bit from the object's header. | |
4705 if (counters != NULL) { | |
4706 cond_inc32(Assembler::zero, | |
4707 ExternalAddress((address)counters->revoked_lock_entry_count_addr())); | |
4708 } | |
4709 | |
4710 bind(cas_label); | |
4711 | |
4712 return null_check_offset; | |
4713 } | |
4714 void MacroAssembler::call_VM_leaf_base(address entry_point, | |
4715 int number_of_arguments) { | |
4716 call(RuntimeAddress(entry_point)); | |
4717 increment(rsp, number_of_arguments * wordSize); | |
4718 } | |
4719 | |
4720 void MacroAssembler::cmpoop(Address src1, jobject obj) { | |
4721 cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); | |
4722 } | |
4723 | |
4724 void MacroAssembler::cmpoop(Register src1, jobject obj) { | |
4725 cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); | |
4726 } | |
4727 | |
4728 void MacroAssembler::extend_sign(Register hi, Register lo) { | |
4729 // According to Intel Doc. AP-526, "Integer Divide", p.18. | |
4730 if (VM_Version::is_P6() && hi == rdx && lo == rax) { | |
4731 cdql(); | |
4732 } else { | |
4733 movl(hi, lo); | |
4734 sarl(hi, 31); | |
4735 } | |
4736 } | |
4737 | |
0 | 4738 void MacroAssembler::fat_nop() { |
4739 // A 5 byte nop that is safe for patching (see patch_verified_entry) | |
4740 emit_byte(0x26); // es: | |
4741 emit_byte(0x2e); // cs: | |
4742 emit_byte(0x64); // fs: | |
4743 emit_byte(0x65); // gs: | |
4744 emit_byte(0x90); | |
4745 } | |
4746 | |
304 | 4747 void MacroAssembler::jC2(Register tmp, Label& L) { |
4748 // set parity bit if FPU flag C2 is set (via rax) | |
4749 save_rax(tmp); | |
4750 fwait(); fnstsw_ax(); | |
4751 sahf(); | |
4752 restore_rax(tmp); | |
4753 // branch | |
4754 jcc(Assembler::parity, L); | |
4755 } | |
4756 | |
4757 void MacroAssembler::jnC2(Register tmp, Label& L) { | |
4758 // set parity bit if FPU flag C2 is set (via rax) | |
4759 save_rax(tmp); | |
4760 fwait(); fnstsw_ax(); | |
4761 sahf(); | |
4762 restore_rax(tmp); | |
4763 // branch | |
4764 jcc(Assembler::noParity, L); | |
4765 } | |
4766 | |
0 | 4767 // 32bit can do a case table jump in one instruction but we no longer allow the base |
4768 // to be installed in the Address class | |
4769 void MacroAssembler::jump(ArrayAddress entry) { | |
4770 jmp(as_Address(entry)); | |
4771 } | |
4772 | |
304 | 4773 // Note: y_lo will be destroyed |
4774 void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { | |
4775 // Long compare for Java (semantics as described in JVM spec.) | |
4776 Label high, low, done; | |
4777 | |
4778 cmpl(x_hi, y_hi); | |
4779 jcc(Assembler::less, low); | |
4780 jcc(Assembler::greater, high); | |
4781 // x_hi is the return register | |
4782 xorl(x_hi, x_hi); | |
4783 cmpl(x_lo, y_lo); | |
4784 jcc(Assembler::below, low); | |
4785 jcc(Assembler::equal, done); | |
4786 | |
4787 bind(high); | |
4788 xorl(x_hi, x_hi); | |
4789 increment(x_hi); | |
4790 jmp(done); | |
4791 | |
4792 bind(low); | |
4793 xorl(x_hi, x_hi); | |
4794 decrementl(x_hi); | |
4795 | |
4796 bind(done); | |
4797 } | |
4798 | |
4799 void MacroAssembler::lea(Register dst, AddressLiteral src) { | |
4800 mov_literal32(dst, (int32_t)src.target(), src.rspec()); | |
0 | 4801 } |
4802 | |
4803 void MacroAssembler::lea(Address dst, AddressLiteral adr) { | |
4804 // leal(dst, as_Address(adr)); | |
304 | 4805 // see note in movl as to why we must use a move |
0 | 4806 mov_literal32(dst, (int32_t) adr.target(), adr.rspec()); |
4807 } | |
4808 | |
4809 void MacroAssembler::leave() { | |
304 | 4810 mov(rsp, rbp); |
4811 pop(rbp); | |
4812 } | |
0 | 4813 |
4814 void MacroAssembler::lmul(int x_rsp_offset, int y_rsp_offset) { | |
4815 // Multiplication of two Java long values stored on the stack | |
4816 // as illustrated below. Result is in rdx:rax. | |
4817 // | |
4818 // rsp ---> [ ?? ] \ \ | |
4819 // .... | y_rsp_offset | | |
4820 // [ y_lo ] / (in bytes) | x_rsp_offset | |
4821 // [ y_hi ] | (in bytes) | |
4822 // .... | | |
4823 // [ x_lo ] / | |
4824 // [ x_hi ] | |
4825 // .... | |
4826 // | |
4827 // Basic idea: lo(result) = lo(x_lo * y_lo) | |
4828 // hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) + lo(x_lo * y_hi) | |
4829 Address x_hi(rsp, x_rsp_offset + wordSize); Address x_lo(rsp, x_rsp_offset); | |
4830 Address y_hi(rsp, y_rsp_offset + wordSize); Address y_lo(rsp, y_rsp_offset); | |
4831 Label quick; | |
4832 // load x_hi, y_hi and check if quick | |
4833 // multiplication is possible | |
4834 movl(rbx, x_hi); | |
4835 movl(rcx, y_hi); | |
4836 movl(rax, rbx); | |
4837 orl(rbx, rcx); // rbx, = 0 <=> x_hi = 0 and y_hi = 0 | |
4838 jcc(Assembler::zero, quick); // if rbx, = 0 do quick multiply | |
4839 // do full multiplication | |
4840 // 1st step | |
4841 mull(y_lo); // x_hi * y_lo | |
4842 movl(rbx, rax); // save lo(x_hi * y_lo) in rbx, | |
4843 // 2nd step | |
4844 movl(rax, x_lo); | |
4845 mull(rcx); // x_lo * y_hi | |
4846 addl(rbx, rax); // add lo(x_lo * y_hi) to rbx, | |
4847 // 3rd step | |
4848 bind(quick); // note: rbx, = 0 if quick multiply! | |
4849 movl(rax, x_lo); | |
4850 mull(y_lo); // x_lo * y_lo | |
4851 addl(rdx, rbx); // correct hi(x_lo * y_lo) | |
4852 } | |
4853 | |
304 | 4854 void MacroAssembler::lneg(Register hi, Register lo) { |
4855 negl(lo); | |
4856 adcl(hi, 0); | |
4857 negl(hi); | |
4858 } | |
0 | 4859 |
4860 void MacroAssembler::lshl(Register hi, Register lo) { | |
4861 // Java shift left long support (semantics as described in JVM spec., p.305) | |
4862 // (basic idea for shift counts s >= n: x << s == (x << n) << (s - n)) | |
4863 // shift value is in rcx ! | |
4864 assert(hi != rcx, "must not use rcx"); | |
4865 assert(lo != rcx, "must not use rcx"); | |
4866 const Register s = rcx; // shift count | |
4867 const int n = BitsPerWord; | |
4868 Label L; | |
4869 andl(s, 0x3f); // s := s & 0x3f (s < 0x40) | |
4870 cmpl(s, n); // if (s < n) | |
4871 jcc(Assembler::less, L); // else (s >= n) | |
4872 movl(hi, lo); // x := x << n | |
4873 xorl(lo, lo); | |
4874 // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! | |
4875 bind(L); // s (mod n) < n | |
4876 shldl(hi, lo); // x := x << s | |
4877 shll(lo); | |
4878 } | |
4879 | |
4880 | |
4881 void MacroAssembler::lshr(Register hi, Register lo, bool sign_extension) { | |
4882 // Java shift right long support (semantics as described in JVM spec., p.306 & p.310) | |
4883 // (basic idea for shift counts s >= n: x >> s == (x >> n) >> (s - n)) | |
4884 assert(hi != rcx, "must not use rcx"); | |
4885 assert(lo != rcx, "must not use rcx"); | |
4886 const Register s = rcx; // shift count | |
4887 const int n = BitsPerWord; | |
4888 Label L; | |
4889 andl(s, 0x3f); // s := s & 0x3f (s < 0x40) | |
4890 cmpl(s, n); // if (s < n) | |
4891 jcc(Assembler::less, L); // else (s >= n) | |
4892 movl(lo, hi); // x := x >> n | |
4893 if (sign_extension) sarl(hi, 31); | |
4894 else xorl(hi, hi); | |
4895 // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! | |
4896 bind(L); // s (mod n) < n | |
4897 shrdl(lo, hi); // x := x >> s | |
4898 if (sign_extension) sarl(hi); | |
4899 else shrl(hi); | |
4900 } | |
4901 | |
304 | 4902 void MacroAssembler::movoop(Register dst, jobject obj) { |
4903 mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); | |
4904 } | |
4905 | |
4906 void MacroAssembler::movoop(Address dst, jobject obj) { | |
4907 mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); | |
4908 } | |
4909 | |
4910 void MacroAssembler::movptr(Register dst, AddressLiteral src) { | |
4911 if (src.is_lval()) { | |
4912 mov_literal32(dst, (intptr_t)src.target(), src.rspec()); | |
4913 } else { | |
4914 movl(dst, as_Address(src)); | |
4915 } | |
4916 } | |
4917 | |
4918 void MacroAssembler::movptr(ArrayAddress dst, Register src) { | |
4919 movl(as_Address(dst), src); | |
4920 } | |
4921 | |
4922 void MacroAssembler::movptr(Register dst, ArrayAddress src) { | |
4923 movl(dst, as_Address(src)); | |
4924 } | |
4925 | |
4926 // src should NEVER be a real pointer. Use AddressLiteral for true pointers | |
4927 void MacroAssembler::movptr(Address dst, intptr_t src) { | |
4928 movl(dst, src); | |
4929 } | |
4930 | |
4931 | |
4932 void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) { | |
4933 movsd(dst, as_Address(src)); | |
4934 } | |
4935 | |
4936 void MacroAssembler::pop_callee_saved_registers() { | |
4937 pop(rcx); | |
4938 pop(rdx); | |
4939 pop(rdi); | |
4940 pop(rsi); | |
4941 } | |
4942 | |
4943 void MacroAssembler::pop_fTOS() { | |
4944 fld_d(Address(rsp, 0)); | |
4945 addl(rsp, 2 * wordSize); | |
4946 } | |
4947 | |
4948 void MacroAssembler::push_callee_saved_registers() { | |
4949 push(rsi); | |
4950 push(rdi); | |
4951 push(rdx); | |
4952 push(rcx); | |
4953 } | |
4954 | |
4955 void MacroAssembler::push_fTOS() { | |
4956 subl(rsp, 2 * wordSize); | |
4957 fstp_d(Address(rsp, 0)); | |
4958 } | |
4959 | |
4960 | |
4961 void MacroAssembler::pushoop(jobject obj) { | |
4962 push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); | |
4963 } | |
4964 | |
4965 | |
4966 void MacroAssembler::pushptr(AddressLiteral src) { | |
4967 if (src.is_lval()) { | |
4968 push_literal32((int32_t)src.target(), src.rspec()); | |
4969 } else { | |
4970 pushl(as_Address(src)); | |
4971 } | |
4972 } | |
4973 | |
4974 void MacroAssembler::set_word_if_not_zero(Register dst) { | |
4975 xorl(dst, dst); | |
4976 set_byte_if_not_zero(dst); | |
4977 } | |
4978 | |
4979 static void pass_arg0(MacroAssembler* masm, Register arg) { | |
4980 masm->push(arg); | |
4981 } | |
4982 | |
4983 static void pass_arg1(MacroAssembler* masm, Register arg) { | |
4984 masm->push(arg); | |
4985 } | |
4986 | |
4987 static void pass_arg2(MacroAssembler* masm, Register arg) { | |
4988 masm->push(arg); | |
4989 } | |
4990 | |
4991 static void pass_arg3(MacroAssembler* masm, Register arg) { | |
4992 masm->push(arg); | |
4993 } | |
4994 | |
4995 #ifndef PRODUCT | |
4996 extern "C" void findpc(intptr_t x); | |
4997 #endif | |
4998 | |
4999 void MacroAssembler::debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg) { | |
5000 // In order to get locks to work, we need to fake a in_VM state | |
5001 JavaThread* thread = JavaThread::current(); | |
5002 JavaThreadState saved_state = thread->thread_state(); | |
5003 thread->set_thread_state(_thread_in_vm); | |
5004 if (ShowMessageBoxOnError) { | |
5005 JavaThread* thread = JavaThread::current(); | |
5006 JavaThreadState saved_state = thread->thread_state(); | |
5007 thread->set_thread_state(_thread_in_vm); | |
5008 if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { | |
5009 ttyLocker ttyl; | |
5010 BytecodeCounter::print(); | |
5011 } | |
5012 // To see where a verify_oop failed, get $ebx+40/X for this frame. | |
5013 // This is the value of eip which points to where verify_oop will return. | |
5014 if (os::message_box(msg, "Execution stopped, print registers?")) { | |
5015 ttyLocker ttyl; | |
5016 tty->print_cr("eip = 0x%08x", eip); | |
5017 #ifndef PRODUCT | |
1793
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5018 if ((WizardMode || Verbose) && PrintMiscellaneous) { |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5019 tty->cr(); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5020 findpc(eip); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5021 tty->cr(); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5022 } |
304 | 5023 #endif |
1793
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5024 tty->print_cr("rax = 0x%08x", rax); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5025 tty->print_cr("rbx = 0x%08x", rbx); |
304 | 5026 tty->print_cr("rcx = 0x%08x", rcx); |
5027 tty->print_cr("rdx = 0x%08x", rdx); | |
5028 tty->print_cr("rdi = 0x%08x", rdi); | |
5029 tty->print_cr("rsi = 0x%08x", rsi); | |
1793
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5030 tty->print_cr("rbp = 0x%08x", rbp); |
304 | 5031 tty->print_cr("rsp = 0x%08x", rsp); |
5032 BREAKPOINT; | |
1793
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
5033 assert(false, "start up GDB"); |
304 | 5034 } |
5035 } else { | |
5036 ttyLocker ttyl; | |
5037 ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); | |
5038 assert(false, "DEBUG MESSAGE"); | |
5039 } | |
5040 ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); | |
5041 } | |
5042 | |
5043 void MacroAssembler::stop(const char* msg) { | |
5044 ExternalAddress message((address)msg); | |
5045 // push address of message | |
5046 pushptr(message.addr()); | |
5047 { Label L; call(L, relocInfo::none); bind(L); } // push eip | |
5048 pusha(); // push registers | |
5049 call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32))); | |
5050 hlt(); | |
5051 } | |
5052 | |
5053 void MacroAssembler::warn(const char* msg) { | |
5054 push_CPU_state(); | |
5055 | |
5056 ExternalAddress message((address) msg); | |
5057 // push address of message | |
5058 pushptr(message.addr()); | |
5059 | |
5060 call(RuntimeAddress(CAST_FROM_FN_PTR(address, warning))); | |
5061 addl(rsp, wordSize); // discard argument | |
5062 pop_CPU_state(); | |
5063 } | |
5064 | |
5065 #else // _LP64 | |
5066 | |
5067 // 64 bit versions | |
5068 | |
5069 Address MacroAssembler::as_Address(AddressLiteral adr) { | |
5070 // amd64 always does this as a pc-rel | |
5071 // we can be absolute or disp based on the instruction type | |
5072 // jmp/call are displacements others are absolute | |
5073 assert(!adr.is_lval(), "must be rval"); | |
5074 assert(reachable(adr), "must be"); | |
5075 return Address((int32_t)(intptr_t)(adr.target() - pc()), adr.target(), adr.reloc()); | |
5076 | |
5077 } | |
5078 | |
5079 Address MacroAssembler::as_Address(ArrayAddress adr) { | |
5080 AddressLiteral base = adr.base(); | |
5081 lea(rscratch1, base); | |
5082 Address index = adr.index(); | |
5083 assert(index._disp == 0, "must not have disp"); // maybe it can? | |
5084 Address array(rscratch1, index._index, index._scale, index._disp); | |
5085 return array; | |
5086 } | |
5087 | |
5088 int MacroAssembler::biased_locking_enter(Register lock_reg, | |
5089 Register obj_reg, | |
5090 Register swap_reg, | |
5091 Register tmp_reg, | |
5092 bool swap_reg_contains_mark, | |
5093 Label& done, | |
5094 Label* slow_case, | |
5095 BiasedLockingCounters* counters) { | |
5096 assert(UseBiasedLocking, "why call this otherwise?"); | |
5097 assert(swap_reg == rax, "swap_reg must be rax for cmpxchgq"); | |
5098 assert(tmp_reg != noreg, "tmp_reg must be supplied"); | |
5099 assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); | |
5100 assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); | |
5101 Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); | |
5102 Address saved_mark_addr(lock_reg, 0); | |
5103 | |
5104 if (PrintBiasedLockingStatistics && counters == NULL) | |
5105 counters = BiasedLocking::counters(); | |
5106 | |
5107 // Biased locking | |
5108 // See whether the lock is currently biased toward our thread and | |
5109 // whether the epoch is still valid | |
5110 // Note that the runtime guarantees sufficient alignment of JavaThread | |
5111 // pointers to allow age to be placed into low bits | |
5112 // First check to see whether biasing is even enabled for this object | |
5113 Label cas_label; | |
5114 int null_check_offset = -1; | |
5115 if (!swap_reg_contains_mark) { | |
5116 null_check_offset = offset(); | |
5117 movq(swap_reg, mark_addr); | |
5118 } | |
5119 movq(tmp_reg, swap_reg); | |
5120 andq(tmp_reg, markOopDesc::biased_lock_mask_in_place); | |
5121 cmpq(tmp_reg, markOopDesc::biased_lock_pattern); | |
5122 jcc(Assembler::notEqual, cas_label); | |
5123 // The bias pattern is present in the object's header. Need to check | |
5124 // whether the bias owner and the epoch are both still current. | |
5125 load_prototype_header(tmp_reg, obj_reg); | |
5126 orq(tmp_reg, r15_thread); | |
5127 xorq(tmp_reg, swap_reg); | |
5128 andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place)); | |
5129 if (counters != NULL) { | |
5130 cond_inc32(Assembler::zero, | |
5131 ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); | |
5132 } | |
0 | 5133 jcc(Assembler::equal, done); |
5134 | |
304 | 5135 Label try_revoke_bias; |
5136 Label try_rebias; | |
5137 | |
5138 // At this point we know that the header has the bias pattern and | |
5139 // that we are not the bias owner in the current epoch. We need to | |
5140 // figure out more details about the state of the header in order to | |
5141 // know what operations can be legally performed on the object's | |
5142 // header. | |
5143 | |
5144 // If the low three bits in the xor result aren't clear, that means | |
5145 // the prototype header is no longer biased and we have to revoke | |
5146 // the bias on this object. | |
5147 testq(tmp_reg, markOopDesc::biased_lock_mask_in_place); | |
5148 jcc(Assembler::notZero, try_revoke_bias); | |
5149 | |
5150 // Biasing is still enabled for this data type. See whether the | |
5151 // epoch of the current bias is still valid, meaning that the epoch | |
5152 // bits of the mark word are equal to the epoch bits of the | |
5153 // prototype header. (Note that the prototype header's epoch bits | |
5154 // only change at a safepoint.) If not, attempt to rebias the object | |
5155 // toward the current thread. Note that we must be absolutely sure | |
5156 // that the current epoch is invalid in order to do this because | |
5157 // otherwise the manipulations it performs on the mark word are | |
5158 // illegal. | |
5159 testq(tmp_reg, markOopDesc::epoch_mask_in_place); | |
5160 jcc(Assembler::notZero, try_rebias); | |
5161 | |
5162 // The epoch of the current bias is still valid but we know nothing | |
5163 // about the owner; it might be set or it might be clear. Try to | |
5164 // acquire the bias of the object using an atomic operation. If this | |
5165 // fails we will go in to the runtime to revoke the object's bias. | |
5166 // Note that we first construct the presumed unbiased header so we | |
5167 // don't accidentally blow away another thread's valid bias. | |
5168 andq(swap_reg, | |
5169 markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); | |
5170 movq(tmp_reg, swap_reg); | |
5171 orq(tmp_reg, r15_thread); | |
5172 if (os::is_MP()) { | |
5173 lock(); | |
5174 } | |
5175 cmpxchgq(tmp_reg, Address(obj_reg, 0)); | |
5176 // If the biasing toward our thread failed, this means that | |
5177 // another thread succeeded in biasing it toward itself and we | |
5178 // need to revoke that bias. The revocation will occur in the | |
5179 // interpreter runtime in the slow case. | |
5180 if (counters != NULL) { | |
5181 cond_inc32(Assembler::zero, | |
5182 ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); | |
5183 } | |
5184 if (slow_case != NULL) { | |
5185 jcc(Assembler::notZero, *slow_case); | |
5186 } | |
0 | 5187 jmp(done); |
5188 | |
304 | 5189 bind(try_rebias); |
5190 // At this point we know the epoch has expired, meaning that the | |
5191 // current "bias owner", if any, is actually invalid. Under these | |
5192 // circumstances _only_, we are allowed to use the current header's | |
5193 // value as the comparison value when doing the cas to acquire the | |
5194 // bias in the current epoch. In other words, we allow transfer of | |
5195 // the bias from one thread to another directly in this situation. | |
5196 // | |
5197 // FIXME: due to a lack of registers we currently blow away the age | |
5198 // bits in this situation. Should attempt to preserve them. | |
5199 load_prototype_header(tmp_reg, obj_reg); | |
5200 orq(tmp_reg, r15_thread); | |
5201 if (os::is_MP()) { | |
5202 lock(); | |
5203 } | |
5204 cmpxchgq(tmp_reg, Address(obj_reg, 0)); | |
5205 // If the biasing toward our thread failed, then another thread | |
5206 // succeeded in biasing it toward itself and we need to revoke that | |
5207 // bias. The revocation will occur in the runtime in the slow case. | |
5208 if (counters != NULL) { | |
5209 cond_inc32(Assembler::zero, | |
5210 ExternalAddress((address) counters->rebiased_lock_entry_count_addr())); | |
5211 } | |
5212 if (slow_case != NULL) { | |
5213 jcc(Assembler::notZero, *slow_case); | |
0 | 5214 } |
5215 jmp(done); | |
5216 | |
304 | 5217 bind(try_revoke_bias); |
5218 // The prototype mark in the klass doesn't have the bias bit set any | |
5219 // more, indicating that objects of this data type are not supposed | |
5220 // to be biased any more. We are going to try to reset the mark of | |
5221 // this object to the prototype value and fall through to the | |
5222 // CAS-based locking scheme. Note that if our CAS fails, it means | |
5223 // that another thread raced us for the privilege of revoking the | |
5224 // bias of this particular object, so it's okay to continue in the | |
5225 // normal locking code. | |
5226 // | |
5227 // FIXME: due to a lack of registers we currently blow away the age | |
5228 // bits in this situation. Should attempt to preserve them. | |
5229 load_prototype_header(tmp_reg, obj_reg); | |
5230 if (os::is_MP()) { | |
5231 lock(); | |
5232 } | |
5233 cmpxchgq(tmp_reg, Address(obj_reg, 0)); | |
5234 // Fall through to the normal CAS-based lock, because no matter what | |
5235 // the result of the above CAS, some thread must have succeeded in | |
5236 // removing the bias bit from the object's header. | |
5237 if (counters != NULL) { | |
5238 cond_inc32(Assembler::zero, | |
5239 ExternalAddress((address) counters->revoked_lock_entry_count_addr())); | |
5240 } | |
5241 | |
5242 bind(cas_label); | |
5243 | |
5244 return null_check_offset; | |
5245 } | |
5246 | |
5247 void MacroAssembler::call_VM_leaf_base(address entry_point, int num_args) { | |
5248 Label L, E; | |
5249 | |
5250 #ifdef _WIN64 | |
5251 // Windows always allocates space for it's register args | |
5252 assert(num_args <= 4, "only register arguments supported"); | |
5253 subq(rsp, frame::arg_reg_save_area_bytes); | |
5254 #endif | |
5255 | |
5256 // Align stack if necessary | |
5257 testl(rsp, 15); | |
5258 jcc(Assembler::zero, L); | |
5259 | |
5260 subq(rsp, 8); | |
5261 { | |
5262 call(RuntimeAddress(entry_point)); | |
5263 } | |
5264 addq(rsp, 8); | |
5265 jmp(E); | |
5266 | |
5267 bind(L); | |
5268 { | |
5269 call(RuntimeAddress(entry_point)); | |
5270 } | |
5271 | |
5272 bind(E); | |
5273 | |
5274 #ifdef _WIN64 | |
5275 // restore stack pointer | |
5276 addq(rsp, frame::arg_reg_save_area_bytes); | |
5277 #endif | |
5278 | |
5279 } | |
5280 | |
5281 void MacroAssembler::cmp64(Register src1, AddressLiteral src2) { | |
5282 assert(!src2.is_lval(), "should use cmpptr"); | |
5283 | |
5284 if (reachable(src2)) { | |
5285 cmpq(src1, as_Address(src2)); | |
5286 } else { | |
5287 lea(rscratch1, src2); | |
5288 Assembler::cmpq(src1, Address(rscratch1, 0)); | |
5289 } | |
5290 } | |
5291 | |
5292 int MacroAssembler::corrected_idivq(Register reg) { | |
5293 // Full implementation of Java ldiv and lrem; checks for special | |
5294 // case as described in JVM spec., p.243 & p.271. The function | |
5295 // returns the (pc) offset of the idivl instruction - may be needed | |
5296 // for implicit exceptions. | |
5297 // | |
5298 // normal case special case | |
5299 // | |
5300 // input : rax: dividend min_long | |
5301 // reg: divisor (may not be eax/edx) -1 | |
5302 // | |
5303 // output: rax: quotient (= rax idiv reg) min_long | |
5304 // rdx: remainder (= rax irem reg) 0 | |
5305 assert(reg != rax && reg != rdx, "reg cannot be rax or rdx register"); | |
5306 static const int64_t min_long = 0x8000000000000000; | |
5307 Label normal_case, special_case; | |
5308 | |
5309 // check for special case | |
5310 cmp64(rax, ExternalAddress((address) &min_long)); | |
5311 jcc(Assembler::notEqual, normal_case); | |
5312 xorl(rdx, rdx); // prepare rdx for possible special case (where | |
5313 // remainder = 0) | |
5314 cmpq(reg, -1); | |
5315 jcc(Assembler::equal, special_case); | |
5316 | |
5317 // handle normal case | |
5318 bind(normal_case); | |
5319 cdqq(); | |
5320 int idivq_offset = offset(); | |
5321 idivq(reg); | |
5322 | |
5323 // normal and special case exit | |
5324 bind(special_case); | |
5325 | |
5326 return idivq_offset; | |
5327 } | |
5328 | |
5329 void MacroAssembler::decrementq(Register reg, int value) { | |
5330 if (value == min_jint) { subq(reg, value); return; } | |
5331 if (value < 0) { incrementq(reg, -value); return; } | |
5332 if (value == 0) { ; return; } | |
5333 if (value == 1 && UseIncDec) { decq(reg) ; return; } | |
5334 /* else */ { subq(reg, value) ; return; } | |
5335 } | |
5336 | |
5337 void MacroAssembler::decrementq(Address dst, int value) { | |
5338 if (value == min_jint) { subq(dst, value); return; } | |
5339 if (value < 0) { incrementq(dst, -value); return; } | |
5340 if (value == 0) { ; return; } | |
5341 if (value == 1 && UseIncDec) { decq(dst) ; return; } | |
5342 /* else */ { subq(dst, value) ; return; } | |
5343 } | |
5344 | |
5345 void MacroAssembler::fat_nop() { | |
5346 // A 5 byte nop that is safe for patching (see patch_verified_entry) | |
5347 // Recommened sequence from 'Software Optimization Guide for the AMD | |
5348 // Hammer Processor' | |
5349 emit_byte(0x66); | |
5350 emit_byte(0x66); | |
5351 emit_byte(0x90); | |
5352 emit_byte(0x66); | |
5353 emit_byte(0x90); | |
5354 } | |
5355 | |
5356 void MacroAssembler::incrementq(Register reg, int value) { | |
5357 if (value == min_jint) { addq(reg, value); return; } | |
5358 if (value < 0) { decrementq(reg, -value); return; } | |
5359 if (value == 0) { ; return; } | |
5360 if (value == 1 && UseIncDec) { incq(reg) ; return; } | |
5361 /* else */ { addq(reg, value) ; return; } | |
5362 } | |
5363 | |
5364 void MacroAssembler::incrementq(Address dst, int value) { | |
5365 if (value == min_jint) { addq(dst, value); return; } | |
5366 if (value < 0) { decrementq(dst, -value); return; } | |
5367 if (value == 0) { ; return; } | |
5368 if (value == 1 && UseIncDec) { incq(dst) ; return; } | |
5369 /* else */ { addq(dst, value) ; return; } | |
5370 } | |
5371 | |
5372 // 32bit can do a case table jump in one instruction but we no longer allow the base | |
5373 // to be installed in the Address class | |
5374 void MacroAssembler::jump(ArrayAddress entry) { | |
5375 lea(rscratch1, entry.base()); | |
5376 Address dispatch = entry.index(); | |
5377 assert(dispatch._base == noreg, "must be"); | |
5378 dispatch._base = rscratch1; | |
5379 jmp(dispatch); | |
5380 } | |
5381 | |
5382 void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { | |
5383 ShouldNotReachHere(); // 64bit doesn't use two regs | |
5384 cmpq(x_lo, y_lo); | |
5385 } | |
5386 | |
5387 void MacroAssembler::lea(Register dst, AddressLiteral src) { | |
5388 mov_literal64(dst, (intptr_t)src.target(), src.rspec()); | |
5389 } | |
5390 | |
5391 void MacroAssembler::lea(Address dst, AddressLiteral adr) { | |
5392 mov_literal64(rscratch1, (intptr_t)adr.target(), adr.rspec()); | |
5393 movptr(dst, rscratch1); | |
5394 } | |
5395 | |
5396 void MacroAssembler::leave() { | |
5397 // %%% is this really better? Why not on 32bit too? | |
5398 emit_byte(0xC9); // LEAVE | |
5399 } | |
5400 | |
5401 void MacroAssembler::lneg(Register hi, Register lo) { | |
5402 ShouldNotReachHere(); // 64bit doesn't use two regs | |
5403 negq(lo); | |
5404 } | |
5405 | |
5406 void MacroAssembler::movoop(Register dst, jobject obj) { | |
5407 mov_literal64(dst, (intptr_t)obj, oop_Relocation::spec_for_immediate()); | |
5408 } | |
5409 | |
5410 void MacroAssembler::movoop(Address dst, jobject obj) { | |
5411 mov_literal64(rscratch1, (intptr_t)obj, oop_Relocation::spec_for_immediate()); | |
5412 movq(dst, rscratch1); | |
5413 } | |
5414 | |
5415 void MacroAssembler::movptr(Register dst, AddressLiteral src) { | |
5416 if (src.is_lval()) { | |
5417 mov_literal64(dst, (intptr_t)src.target(), src.rspec()); | |
5418 } else { | |
5419 if (reachable(src)) { | |
5420 movq(dst, as_Address(src)); | |
5421 } else { | |
5422 lea(rscratch1, src); | |
5423 movq(dst, Address(rscratch1,0)); | |
0 | 5424 } |
304 | 5425 } |
5426 } | |
5427 | |
5428 void MacroAssembler::movptr(ArrayAddress dst, Register src) { | |
5429 movq(as_Address(dst), src); | |
5430 } | |
5431 | |
5432 void MacroAssembler::movptr(Register dst, ArrayAddress src) { | |
5433 movq(dst, as_Address(src)); | |
5434 } | |
5435 | |
5436 // src should NEVER be a real pointer. Use AddressLiteral for true pointers | |
5437 void MacroAssembler::movptr(Address dst, intptr_t src) { | |
5438 mov64(rscratch1, src); | |
5439 movq(dst, rscratch1); | |
5440 } | |
5441 | |
5442 // These are mostly for initializing NULL | |
5443 void MacroAssembler::movptr(Address dst, int32_t src) { | |
5444 movslq(dst, src); | |
5445 } | |
5446 | |
5447 void MacroAssembler::movptr(Register dst, int32_t src) { | |
5448 mov64(dst, (intptr_t)src); | |
5449 } | |
5450 | |
5451 void MacroAssembler::pushoop(jobject obj) { | |
5452 movoop(rscratch1, obj); | |
5453 push(rscratch1); | |
5454 } | |
5455 | |
5456 void MacroAssembler::pushptr(AddressLiteral src) { | |
5457 lea(rscratch1, src); | |
5458 if (src.is_lval()) { | |
5459 push(rscratch1); | |
5460 } else { | |
5461 pushq(Address(rscratch1, 0)); | |
5462 } | |
5463 } | |
5464 | |
5465 void MacroAssembler::reset_last_Java_frame(bool clear_fp, | |
5466 bool clear_pc) { | |
5467 // we must set sp to zero to clear frame | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
5468 movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); |
304 | 5469 // must clear fp, so that compiled frames are not confused; it is |
5470 // possible that we need it only for debugging | |
5471 if (clear_fp) { | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
5472 movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); |
304 | 5473 } |
5474 | |
5475 if (clear_pc) { | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
5476 movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); |
304 | 5477 } |
5478 } | |
5479 | |
5480 void MacroAssembler::set_last_Java_frame(Register last_java_sp, | |
5481 Register last_java_fp, | |
5482 address last_java_pc) { | |
5483 // determine last_java_sp register | |
5484 if (!last_java_sp->is_valid()) { | |
5485 last_java_sp = rsp; | |
5486 } | |
5487 | |
5488 // last_java_fp is optional | |
5489 if (last_java_fp->is_valid()) { | |
5490 movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), | |
5491 last_java_fp); | |
5492 } | |
5493 | |
5494 // last_java_pc is optional | |
5495 if (last_java_pc != NULL) { | |
5496 Address java_pc(r15_thread, | |
5497 JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); | |
5498 lea(rscratch1, InternalAddress(last_java_pc)); | |
5499 movptr(java_pc, rscratch1); | |
5500 } | |
5501 | |
5502 movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), last_java_sp); | |
5503 } | |
5504 | |
5505 static void pass_arg0(MacroAssembler* masm, Register arg) { | |
5506 if (c_rarg0 != arg ) { | |
5507 masm->mov(c_rarg0, arg); | |
5508 } | |
5509 } | |
5510 | |
5511 static void pass_arg1(MacroAssembler* masm, Register arg) { | |
5512 if (c_rarg1 != arg ) { | |
5513 masm->mov(c_rarg1, arg); | |
5514 } | |
5515 } | |
5516 | |
5517 static void pass_arg2(MacroAssembler* masm, Register arg) { | |
5518 if (c_rarg2 != arg ) { | |
5519 masm->mov(c_rarg2, arg); | |
5520 } | |
5521 } | |
5522 | |
5523 static void pass_arg3(MacroAssembler* masm, Register arg) { | |
5524 if (c_rarg3 != arg ) { | |
5525 masm->mov(c_rarg3, arg); | |
5526 } | |
5527 } | |
5528 | |
5529 void MacroAssembler::stop(const char* msg) { | |
5530 address rip = pc(); | |
5531 pusha(); // get regs on stack | |
5532 lea(c_rarg0, ExternalAddress((address) msg)); | |
5533 lea(c_rarg1, InternalAddress(rip)); | |
5534 movq(c_rarg2, rsp); // pass pointer to regs array | |
5535 andq(rsp, -16); // align stack as required by ABI | |
5536 call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug64))); | |
5537 hlt(); | |
5538 } | |
5539 | |
5540 void MacroAssembler::warn(const char* msg) { | |
5541 push(r12); | |
5542 movq(r12, rsp); | |
5543 andq(rsp, -16); // align stack as required by push_CPU_state and call | |
5544 | |
5545 push_CPU_state(); // keeps alignment at 16 bytes | |
5546 lea(c_rarg0, ExternalAddress((address) msg)); | |
5547 call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0); | |
5548 pop_CPU_state(); | |
5549 | |
5550 movq(rsp, r12); | |
5551 pop(r12); | |
5552 } | |
5553 | |
5554 #ifndef PRODUCT | |
5555 extern "C" void findpc(intptr_t x); | |
5556 #endif | |
5557 | |
5558 void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) { | |
5559 // In order to get locks to work, we need to fake a in_VM state | |
5560 if (ShowMessageBoxOnError ) { | |
5561 JavaThread* thread = JavaThread::current(); | |
5562 JavaThreadState saved_state = thread->thread_state(); | |
5563 thread->set_thread_state(_thread_in_vm); | |
5564 #ifndef PRODUCT | |
5565 if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { | |
5566 ttyLocker ttyl; | |
5567 BytecodeCounter::print(); | |
0 | 5568 } |
304 | 5569 #endif |
5570 // To see where a verify_oop failed, get $ebx+40/X for this frame. | |
5571 // XXX correct this offset for amd64 | |
5572 // This is the value of eip which points to where verify_oop will return. | |
5573 if (os::message_box(msg, "Execution stopped, print registers?")) { | |
5574 ttyLocker ttyl; | |
5575 tty->print_cr("rip = 0x%016lx", pc); | |
5576 #ifndef PRODUCT | |
5577 tty->cr(); | |
5578 findpc(pc); | |
5579 tty->cr(); | |
5580 #endif | |
5581 tty->print_cr("rax = 0x%016lx", regs[15]); | |
5582 tty->print_cr("rbx = 0x%016lx", regs[12]); | |
5583 tty->print_cr("rcx = 0x%016lx", regs[14]); | |
5584 tty->print_cr("rdx = 0x%016lx", regs[13]); | |
5585 tty->print_cr("rdi = 0x%016lx", regs[8]); | |
5586 tty->print_cr("rsi = 0x%016lx", regs[9]); | |
5587 tty->print_cr("rbp = 0x%016lx", regs[10]); | |
5588 tty->print_cr("rsp = 0x%016lx", regs[11]); | |
5589 tty->print_cr("r8 = 0x%016lx", regs[7]); | |
5590 tty->print_cr("r9 = 0x%016lx", regs[6]); | |
5591 tty->print_cr("r10 = 0x%016lx", regs[5]); | |
5592 tty->print_cr("r11 = 0x%016lx", regs[4]); | |
5593 tty->print_cr("r12 = 0x%016lx", regs[3]); | |
5594 tty->print_cr("r13 = 0x%016lx", regs[2]); | |
5595 tty->print_cr("r14 = 0x%016lx", regs[1]); | |
5596 tty->print_cr("r15 = 0x%016lx", regs[0]); | |
5597 BREAKPOINT; | |
0 | 5598 } |
304 | 5599 ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); |
5600 } else { | |
5601 ttyLocker ttyl; | |
5602 ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", | |
5603 msg); | |
5604 } | |
5605 } | |
5606 | |
5607 #endif // _LP64 | |
5608 | |
5609 // Now versions that are common to 32/64 bit | |
5610 | |
5611 void MacroAssembler::addptr(Register dst, int32_t imm32) { | |
5612 LP64_ONLY(addq(dst, imm32)) NOT_LP64(addl(dst, imm32)); | |
5613 } | |
5614 | |
5615 void MacroAssembler::addptr(Register dst, Register src) { | |
5616 LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); | |
5617 } | |
5618 | |
5619 void MacroAssembler::addptr(Address dst, Register src) { | |
5620 LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); | |
5621 } | |
5622 | |
5623 void MacroAssembler::align(int modulus) { | |
5624 if (offset() % modulus != 0) { | |
5625 nop(modulus - (offset() % modulus)); | |
5626 } | |
5627 } | |
5628 | |
5629 void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { | |
1060 | 5630 if (reachable(src)) { |
5631 andpd(dst, as_Address(src)); | |
5632 } else { | |
5633 lea(rscratch1, src); | |
5634 andpd(dst, Address(rscratch1, 0)); | |
5635 } | |
304 | 5636 } |
5637 | |
5638 void MacroAssembler::andptr(Register dst, int32_t imm32) { | |
5639 LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32)); | |
5640 } | |
5641 | |
5642 void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { | |
5643 pushf(); | |
5644 if (os::is_MP()) | |
5645 lock(); | |
5646 incrementl(counter_addr); | |
5647 popf(); | |
5648 } | |
5649 | |
5650 // Writes to stack successive pages until offset reached to check for | |
5651 // stack overflow + shadow pages. This clobbers tmp. | |
5652 void MacroAssembler::bang_stack_size(Register size, Register tmp) { | |
5653 movptr(tmp, rsp); | |
5654 // Bang stack for total size given plus shadow page size. | |
5655 // Bang one page at a time because large size can bang beyond yellow and | |
5656 // red zones. | |
5657 Label loop; | |
5658 bind(loop); | |
5659 movl(Address(tmp, (-os::vm_page_size())), size ); | |
5660 subptr(tmp, os::vm_page_size()); | |
5661 subl(size, os::vm_page_size()); | |
5662 jcc(Assembler::greater, loop); | |
5663 | |
5664 // Bang down shadow pages too. | |
5665 // The -1 because we already subtracted 1 page. | |
5666 for (int i = 0; i< StackShadowPages-1; i++) { | |
5667 // this could be any sized move but this is can be a debugging crumb | |
5668 // so the bigger the better. | |
5669 movptr(Address(tmp, (-i*os::vm_page_size())), size ); | |
5670 } | |
5671 } | |
5672 | |
5673 void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, Label& done) { | |
5674 assert(UseBiasedLocking, "why call this otherwise?"); | |
5675 | |
5676 // Check for biased locking unlock case, which is a no-op | |
5677 // Note: we do not have to check the thread ID for two reasons. | |
5678 // First, the interpreter checks for IllegalMonitorStateException at | |
5679 // a higher level. Second, if the bias was revoked while we held the | |
5680 // lock, the object could not be rebiased toward another thread, so | |
5681 // the bias bit would be clear. | |
5682 movptr(temp_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); | |
5683 andptr(temp_reg, markOopDesc::biased_lock_mask_in_place); | |
5684 cmpptr(temp_reg, markOopDesc::biased_lock_pattern); | |
5685 jcc(Assembler::equal, done); | |
5686 } | |
5687 | |
5688 void MacroAssembler::c2bool(Register x) { | |
5689 // implements x == 0 ? 0 : 1 | |
5690 // note: must only look at least-significant byte of x | |
5691 // since C-style booleans are stored in one byte | |
5692 // only! (was bug) | |
5693 andl(x, 0xFF); | |
5694 setb(Assembler::notZero, x); | |
5695 } | |
5696 | |
5697 // Wouldn't need if AddressLiteral version had new name | |
5698 void MacroAssembler::call(Label& L, relocInfo::relocType rtype) { | |
5699 Assembler::call(L, rtype); | |
5700 } | |
5701 | |
5702 void MacroAssembler::call(Register entry) { | |
5703 Assembler::call(entry); | |
5704 } | |
5705 | |
5706 void MacroAssembler::call(AddressLiteral entry) { | |
5707 if (reachable(entry)) { | |
5708 Assembler::call_literal(entry.target(), entry.rspec()); | |
5709 } else { | |
5710 lea(rscratch1, entry); | |
5711 Assembler::call(rscratch1); | |
5712 } | |
5713 } | |
5714 | |
5715 // Implementation of call_VM versions | |
5716 | |
5717 void MacroAssembler::call_VM(Register oop_result, | |
5718 address entry_point, | |
5719 bool check_exceptions) { | |
5720 Label C, E; | |
5721 call(C, relocInfo::none); | |
5722 jmp(E); | |
5723 | |
5724 bind(C); | |
5725 call_VM_helper(oop_result, entry_point, 0, check_exceptions); | |
5726 ret(0); | |
5727 | |
5728 bind(E); | |
5729 } | |
5730 | |
5731 void MacroAssembler::call_VM(Register oop_result, | |
5732 address entry_point, | |
5733 Register arg_1, | |
5734 bool check_exceptions) { | |
5735 Label C, E; | |
5736 call(C, relocInfo::none); | |
5737 jmp(E); | |
5738 | |
5739 bind(C); | |
5740 pass_arg1(this, arg_1); | |
5741 call_VM_helper(oop_result, entry_point, 1, check_exceptions); | |
5742 ret(0); | |
5743 | |
5744 bind(E); | |
5745 } | |
5746 | |
5747 void MacroAssembler::call_VM(Register oop_result, | |
5748 address entry_point, | |
5749 Register arg_1, | |
5750 Register arg_2, | |
5751 bool check_exceptions) { | |
5752 Label C, E; | |
5753 call(C, relocInfo::none); | |
5754 jmp(E); | |
5755 | |
5756 bind(C); | |
5757 | |
5758 LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); | |
5759 | |
5760 pass_arg2(this, arg_2); | |
5761 pass_arg1(this, arg_1); | |
5762 call_VM_helper(oop_result, entry_point, 2, check_exceptions); | |
5763 ret(0); | |
5764 | |
5765 bind(E); | |
5766 } | |
5767 | |
5768 void MacroAssembler::call_VM(Register oop_result, | |
5769 address entry_point, | |
5770 Register arg_1, | |
5771 Register arg_2, | |
5772 Register arg_3, | |
5773 bool check_exceptions) { | |
5774 Label C, E; | |
5775 call(C, relocInfo::none); | |
5776 jmp(E); | |
5777 | |
5778 bind(C); | |
5779 | |
5780 LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); | |
5781 LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); | |
5782 pass_arg3(this, arg_3); | |
5783 | |
5784 LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); | |
5785 pass_arg2(this, arg_2); | |
5786 | |
5787 pass_arg1(this, arg_1); | |
5788 call_VM_helper(oop_result, entry_point, 3, check_exceptions); | |
5789 ret(0); | |
5790 | |
5791 bind(E); | |
5792 } | |
5793 | |
5794 void MacroAssembler::call_VM(Register oop_result, | |
5795 Register last_java_sp, | |
5796 address entry_point, | |
5797 int number_of_arguments, | |
5798 bool check_exceptions) { | |
5799 Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); | |
5800 call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); | |
5801 } | |
5802 | |
5803 void MacroAssembler::call_VM(Register oop_result, | |
5804 Register last_java_sp, | |
5805 address entry_point, | |
5806 Register arg_1, | |
5807 bool check_exceptions) { | |
5808 pass_arg1(this, arg_1); | |
5809 call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); | |
5810 } | |
5811 | |
5812 void MacroAssembler::call_VM(Register oop_result, | |
5813 Register last_java_sp, | |
5814 address entry_point, | |
5815 Register arg_1, | |
5816 Register arg_2, | |
5817 bool check_exceptions) { | |
5818 | |
5819 LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); | |
5820 pass_arg2(this, arg_2); | |
5821 pass_arg1(this, arg_1); | |
5822 call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); | |
5823 } | |
5824 | |
5825 void MacroAssembler::call_VM(Register oop_result, | |
5826 Register last_java_sp, | |
5827 address entry_point, | |
5828 Register arg_1, | |
5829 Register arg_2, | |
5830 Register arg_3, | |
5831 bool check_exceptions) { | |
5832 LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); | |
5833 LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); | |
5834 pass_arg3(this, arg_3); | |
5835 LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); | |
5836 pass_arg2(this, arg_2); | |
5837 pass_arg1(this, arg_1); | |
5838 call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); | |
5839 } | |
5840 | |
5841 void MacroAssembler::call_VM_base(Register oop_result, | |
5842 Register java_thread, | |
5843 Register last_java_sp, | |
5844 address entry_point, | |
5845 int number_of_arguments, | |
5846 bool check_exceptions) { | |
5847 // determine java_thread register | |
5848 if (!java_thread->is_valid()) { | |
5849 #ifdef _LP64 | |
5850 java_thread = r15_thread; | |
5851 #else | |
5852 java_thread = rdi; | |
5853 get_thread(java_thread); | |
5854 #endif // LP64 | |
5855 } | |
5856 // determine last_java_sp register | |
5857 if (!last_java_sp->is_valid()) { | |
5858 last_java_sp = rsp; | |
5859 } | |
5860 // debugging support | |
5861 assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); | |
5862 LP64_ONLY(assert(java_thread == r15_thread, "unexpected register")); | |
5863 assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); | |
5864 assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp"); | |
5865 | |
5866 // push java thread (becomes first argument of C function) | |
5867 | |
5868 NOT_LP64(push(java_thread); number_of_arguments++); | |
5869 LP64_ONLY(mov(c_rarg0, r15_thread)); | |
5870 | |
5871 // set last Java frame before call | |
5872 assert(last_java_sp != rbp, "can't use ebp/rbp"); | |
5873 | |
5874 // Only interpreter should have to set fp | |
5875 set_last_Java_frame(java_thread, last_java_sp, rbp, NULL); | |
5876 | |
5877 // do the call, remove parameters | |
5878 MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); | |
5879 | |
5880 // restore the thread (cannot use the pushed argument since arguments | |
5881 // may be overwritten by C code generated by an optimizing compiler); | |
5882 // however can use the register value directly if it is callee saved. | |
5883 if (LP64_ONLY(true ||) java_thread == rdi || java_thread == rsi) { | |
5884 // rdi & rsi (also r15) are callee saved -> nothing to do | |
5885 #ifdef ASSERT | |
5886 guarantee(java_thread != rax, "change this code"); | |
5887 push(rax); | |
5888 { Label L; | |
5889 get_thread(rax); | |
5890 cmpptr(java_thread, rax); | |
5891 jcc(Assembler::equal, L); | |
5892 stop("MacroAssembler::call_VM_base: rdi not callee saved?"); | |
5893 bind(L); | |
0 | 5894 } |
304 | 5895 pop(rax); |
5896 #endif | |
5897 } else { | |
5898 get_thread(java_thread); | |
5899 } | |
5900 // reset last Java frame | |
5901 // Only interpreter should have to clear fp | |
5902 reset_last_Java_frame(java_thread, true, false); | |
5903 | |
5904 #ifndef CC_INTERP | |
5905 // C++ interp handles this in the interpreter | |
5906 check_and_handle_popframe(java_thread); | |
5907 check_and_handle_earlyret(java_thread); | |
5908 #endif /* CC_INTERP */ | |
5909 | |
5910 if (check_exceptions) { | |
5911 // check for pending exceptions (java_thread is set upon return) | |
5912 cmpptr(Address(java_thread, Thread::pending_exception_offset()), (int32_t) NULL_WORD); | |
5913 #ifndef _LP64 | |
5914 jump_cc(Assembler::notEqual, | |
5915 RuntimeAddress(StubRoutines::forward_exception_entry())); | |
5916 #else | |
5917 // This used to conditionally jump to forward_exception however it is | |
5918 // possible if we relocate that the branch will not reach. So we must jump | |
5919 // around so we can always reach | |
5920 | |
5921 Label ok; | |
5922 jcc(Assembler::equal, ok); | |
5923 jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | |
5924 bind(ok); | |
5925 #endif // LP64 | |
5926 } | |
5927 | |
5928 // get oop result if there is one and reset the value in the thread | |
5929 if (oop_result->is_valid()) { | |
5930 movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
5931 movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); |
304 | 5932 verify_oop(oop_result, "broken oop in call_VM_base"); |
5933 } | |
5934 } | |
5935 | |
5936 void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { | |
5937 | |
5938 // Calculate the value for last_Java_sp | |
5939 // somewhat subtle. call_VM does an intermediate call | |
5940 // which places a return address on the stack just under the | |
5941 // stack pointer as the user finsihed with it. This allows | |
5942 // use to retrieve last_Java_pc from last_Java_sp[-1]. | |
5943 // On 32bit we then have to push additional args on the stack to accomplish | |
5944 // the actual requested call. On 64bit call_VM only can use register args | |
5945 // so the only extra space is the return address that call_VM created. | |
5946 // This hopefully explains the calculations here. | |
5947 | |
5948 #ifdef _LP64 | |
5949 // We've pushed one address, correct last_Java_sp | |
5950 lea(rax, Address(rsp, wordSize)); | |
5951 #else | |
5952 lea(rax, Address(rsp, (1 + number_of_arguments) * wordSize)); | |
5953 #endif // LP64 | |
5954 | |
5955 call_VM_base(oop_result, noreg, rax, entry_point, number_of_arguments, check_exceptions); | |
5956 | |
5957 } | |
5958 | |
5959 void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) { | |
5960 call_VM_leaf_base(entry_point, number_of_arguments); | |
5961 } | |
5962 | |
5963 void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0) { | |
5964 pass_arg0(this, arg_0); | |
5965 call_VM_leaf(entry_point, 1); | |
5966 } | |
5967 | |
5968 void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { | |
5969 | |
5970 LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); | |
5971 pass_arg1(this, arg_1); | |
5972 pass_arg0(this, arg_0); | |
5973 call_VM_leaf(entry_point, 2); | |
5974 } | |
5975 | |
5976 void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { | |
5977 LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); | |
5978 LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); | |
5979 pass_arg2(this, arg_2); | |
5980 LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); | |
5981 pass_arg1(this, arg_1); | |
5982 pass_arg0(this, arg_0); | |
5983 call_VM_leaf(entry_point, 3); | |
5984 } | |
5985 | |
5986 void MacroAssembler::check_and_handle_earlyret(Register java_thread) { | |
5987 } | |
5988 | |
5989 void MacroAssembler::check_and_handle_popframe(Register java_thread) { | |
5990 } | |
5991 | |
5992 void MacroAssembler::cmp32(AddressLiteral src1, int32_t imm) { | |
5993 if (reachable(src1)) { | |
5994 cmpl(as_Address(src1), imm); | |
5995 } else { | |
5996 lea(rscratch1, src1); | |
5997 cmpl(Address(rscratch1, 0), imm); | |
5998 } | |
5999 } | |
6000 | |
6001 void MacroAssembler::cmp32(Register src1, AddressLiteral src2) { | |
6002 assert(!src2.is_lval(), "use cmpptr"); | |
6003 if (reachable(src2)) { | |
6004 cmpl(src1, as_Address(src2)); | |
6005 } else { | |
6006 lea(rscratch1, src2); | |
6007 cmpl(src1, Address(rscratch1, 0)); | |
6008 } | |
6009 } | |
6010 | |
6011 void MacroAssembler::cmp32(Register src1, int32_t imm) { | |
6012 Assembler::cmpl(src1, imm); | |
6013 } | |
6014 | |
6015 void MacroAssembler::cmp32(Register src1, Address src2) { | |
6016 Assembler::cmpl(src1, src2); | |
6017 } | |
6018 | |
6019 void MacroAssembler::cmpsd2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less) { | |
6020 ucomisd(opr1, opr2); | |
6021 | |
6022 Label L; | |
6023 if (unordered_is_less) { | |
6024 movl(dst, -1); | |
6025 jcc(Assembler::parity, L); | |
6026 jcc(Assembler::below , L); | |
6027 movl(dst, 0); | |
6028 jcc(Assembler::equal , L); | |
6029 increment(dst); | |
6030 } else { // unordered is greater | |
6031 movl(dst, 1); | |
6032 jcc(Assembler::parity, L); | |
6033 jcc(Assembler::above , L); | |
6034 movl(dst, 0); | |
6035 jcc(Assembler::equal , L); | |
6036 decrementl(dst); | |
6037 } | |
6038 bind(L); | |
6039 } | |
6040 | |
6041 void MacroAssembler::cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less) { | |
6042 ucomiss(opr1, opr2); | |
6043 | |
6044 Label L; | |
6045 if (unordered_is_less) { | |
6046 movl(dst, -1); | |
6047 jcc(Assembler::parity, L); | |
6048 jcc(Assembler::below , L); | |
6049 movl(dst, 0); | |
6050 jcc(Assembler::equal , L); | |
6051 increment(dst); | |
6052 } else { // unordered is greater | |
6053 movl(dst, 1); | |
6054 jcc(Assembler::parity, L); | |
6055 jcc(Assembler::above , L); | |
6056 movl(dst, 0); | |
6057 jcc(Assembler::equal , L); | |
6058 decrementl(dst); | |
6059 } | |
6060 bind(L); | |
6061 } | |
6062 | |
6063 | |
6064 void MacroAssembler::cmp8(AddressLiteral src1, int imm) { | |
6065 if (reachable(src1)) { | |
6066 cmpb(as_Address(src1), imm); | |
6067 } else { | |
6068 lea(rscratch1, src1); | |
6069 cmpb(Address(rscratch1, 0), imm); | |
6070 } | |
6071 } | |
6072 | |
6073 void MacroAssembler::cmpptr(Register src1, AddressLiteral src2) { | |
6074 #ifdef _LP64 | |
6075 if (src2.is_lval()) { | |
6076 movptr(rscratch1, src2); | |
6077 Assembler::cmpq(src1, rscratch1); | |
6078 } else if (reachable(src2)) { | |
6079 cmpq(src1, as_Address(src2)); | |
6080 } else { | |
6081 lea(rscratch1, src2); | |
6082 Assembler::cmpq(src1, Address(rscratch1, 0)); | |
6083 } | |
6084 #else | |
6085 if (src2.is_lval()) { | |
6086 cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); | |
6087 } else { | |
6088 cmpl(src1, as_Address(src2)); | |
6089 } | |
6090 #endif // _LP64 | |
6091 } | |
6092 | |
6093 void MacroAssembler::cmpptr(Address src1, AddressLiteral src2) { | |
6094 assert(src2.is_lval(), "not a mem-mem compare"); | |
6095 #ifdef _LP64 | |
6096 // moves src2's literal address | |
6097 movptr(rscratch1, src2); | |
6098 Assembler::cmpq(src1, rscratch1); | |
6099 #else | |
6100 cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); | |
6101 #endif // _LP64 | |
6102 } | |
6103 | |
6104 void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr) { | |
6105 if (reachable(adr)) { | |
6106 if (os::is_MP()) | |
6107 lock(); | |
6108 cmpxchgptr(reg, as_Address(adr)); | |
6109 } else { | |
6110 lea(rscratch1, adr); | |
6111 if (os::is_MP()) | |
6112 lock(); | |
6113 cmpxchgptr(reg, Address(rscratch1, 0)); | |
6114 } | |
6115 } | |
6116 | |
6117 void MacroAssembler::cmpxchgptr(Register reg, Address adr) { | |
6118 LP64_ONLY(cmpxchgq(reg, adr)) NOT_LP64(cmpxchgl(reg, adr)); | |
6119 } | |
6120 | |
6121 void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) { | |
1060 | 6122 if (reachable(src)) { |
6123 comisd(dst, as_Address(src)); | |
6124 } else { | |
6125 lea(rscratch1, src); | |
6126 comisd(dst, Address(rscratch1, 0)); | |
6127 } | |
304 | 6128 } |
6129 | |
6130 void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) { | |
1060 | 6131 if (reachable(src)) { |
6132 comiss(dst, as_Address(src)); | |
6133 } else { | |
6134 lea(rscratch1, src); | |
6135 comiss(dst, Address(rscratch1, 0)); | |
6136 } | |
304 | 6137 } |
6138 | |
6139 | |
6140 void MacroAssembler::cond_inc32(Condition cond, AddressLiteral counter_addr) { | |
6141 Condition negated_cond = negate_condition(cond); | |
6142 Label L; | |
6143 jcc(negated_cond, L); | |
6144 atomic_incl(counter_addr); | |
6145 bind(L); | |
6146 } | |
6147 | |
6148 int MacroAssembler::corrected_idivl(Register reg) { | |
6149 // Full implementation of Java idiv and irem; checks for | |
6150 // special case as described in JVM spec., p.243 & p.271. | |
6151 // The function returns the (pc) offset of the idivl | |
6152 // instruction - may be needed for implicit exceptions. | |
6153 // | |
6154 // normal case special case | |
6155 // | |
6156 // input : rax,: dividend min_int | |
6157 // reg: divisor (may not be rax,/rdx) -1 | |
6158 // | |
6159 // output: rax,: quotient (= rax, idiv reg) min_int | |
6160 // rdx: remainder (= rax, irem reg) 0 | |
6161 assert(reg != rax && reg != rdx, "reg cannot be rax, or rdx register"); | |
6162 const int min_int = 0x80000000; | |
6163 Label normal_case, special_case; | |
6164 | |
6165 // check for special case | |
6166 cmpl(rax, min_int); | |
6167 jcc(Assembler::notEqual, normal_case); | |
6168 xorl(rdx, rdx); // prepare rdx for possible special case (where remainder = 0) | |
6169 cmpl(reg, -1); | |
6170 jcc(Assembler::equal, special_case); | |
6171 | |
6172 // handle normal case | |
6173 bind(normal_case); | |
6174 cdql(); | |
6175 int idivl_offset = offset(); | |
6176 idivl(reg); | |
6177 | |
6178 // normal and special case exit | |
6179 bind(special_case); | |
6180 | |
6181 return idivl_offset; | |
6182 } | |
6183 | |
6184 | |
6185 | |
6186 void MacroAssembler::decrementl(Register reg, int value) { | |
6187 if (value == min_jint) {subl(reg, value) ; return; } | |
6188 if (value < 0) { incrementl(reg, -value); return; } | |
6189 if (value == 0) { ; return; } | |
6190 if (value == 1 && UseIncDec) { decl(reg) ; return; } | |
6191 /* else */ { subl(reg, value) ; return; } | |
6192 } | |
6193 | |
6194 void MacroAssembler::decrementl(Address dst, int value) { | |
6195 if (value == min_jint) {subl(dst, value) ; return; } | |
6196 if (value < 0) { incrementl(dst, -value); return; } | |
6197 if (value == 0) { ; return; } | |
6198 if (value == 1 && UseIncDec) { decl(dst) ; return; } | |
6199 /* else */ { subl(dst, value) ; return; } | |
6200 } | |
6201 | |
6202 void MacroAssembler::division_with_shift (Register reg, int shift_value) { | |
6203 assert (shift_value > 0, "illegal shift value"); | |
6204 Label _is_positive; | |
6205 testl (reg, reg); | |
6206 jcc (Assembler::positive, _is_positive); | |
6207 int offset = (1 << shift_value) - 1 ; | |
6208 | |
6209 if (offset == 1) { | |
6210 incrementl(reg); | |
6211 } else { | |
6212 addl(reg, offset); | |
6213 } | |
6214 | |
6215 bind (_is_positive); | |
6216 sarl(reg, shift_value); | |
6217 } | |
6218 | |
6219 // !defined(COMPILER2) is because of stupid core builds | |
6220 #if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) | |
6221 void MacroAssembler::empty_FPU_stack() { | |
6222 if (VM_Version::supports_mmx()) { | |
6223 emms(); | |
6224 } else { | |
6225 for (int i = 8; i-- > 0; ) ffree(i); | |
6226 } | |
6227 } | |
6228 #endif // !LP64 || C1 || !C2 | |
6229 | |
6230 | |
6231 // Defines obj, preserves var_size_in_bytes | |
6232 void MacroAssembler::eden_allocate(Register obj, | |
6233 Register var_size_in_bytes, | |
6234 int con_size_in_bytes, | |
6235 Register t1, | |
6236 Label& slow_case) { | |
6237 assert(obj == rax, "obj must be in rax, for cmpxchg"); | |
6238 assert_different_registers(obj, var_size_in_bytes, t1); | |
362 | 6239 if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { |
6240 jmp(slow_case); | |
304 | 6241 } else { |
362 | 6242 Register end = t1; |
6243 Label retry; | |
6244 bind(retry); | |
6245 ExternalAddress heap_top((address) Universe::heap()->top_addr()); | |
6246 movptr(obj, heap_top); | |
6247 if (var_size_in_bytes == noreg) { | |
6248 lea(end, Address(obj, con_size_in_bytes)); | |
6249 } else { | |
6250 lea(end, Address(obj, var_size_in_bytes, Address::times_1)); | |
6251 } | |
6252 // if end < obj then we wrapped around => object too long => slow case | |
6253 cmpptr(end, obj); | |
6254 jcc(Assembler::below, slow_case); | |
6255 cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr())); | |
6256 jcc(Assembler::above, slow_case); | |
6257 // Compare obj with the top addr, and if still equal, store the new top addr in | |
6258 // end at the address of the top addr pointer. Sets ZF if was equal, and clears | |
6259 // it otherwise. Use lock prefix for atomicity on MPs. | |
6260 locked_cmpxchgptr(end, heap_top); | |
6261 jcc(Assembler::notEqual, retry); | |
6262 } | |
304 | 6263 } |
6264 | |
6265 void MacroAssembler::enter() { | |
6266 push(rbp); | |
6267 mov(rbp, rsp); | |
6268 } | |
0 | 6269 |
6270 void MacroAssembler::fcmp(Register tmp) { | |
6271 fcmp(tmp, 1, true, true); | |
6272 } | |
6273 | |
6274 void MacroAssembler::fcmp(Register tmp, int index, bool pop_left, bool pop_right) { | |
6275 assert(!pop_right || pop_left, "usage error"); | |
6276 if (VM_Version::supports_cmov()) { | |
6277 assert(tmp == noreg, "unneeded temp"); | |
6278 if (pop_left) { | |
6279 fucomip(index); | |
6280 } else { | |
6281 fucomi(index); | |
6282 } | |
6283 if (pop_right) { | |
6284 fpop(); | |
6285 } | |
6286 } else { | |
6287 assert(tmp != noreg, "need temp"); | |
6288 if (pop_left) { | |
6289 if (pop_right) { | |
6290 fcompp(); | |
6291 } else { | |
6292 fcomp(index); | |
6293 } | |
6294 } else { | |
6295 fcom(index); | |
6296 } | |
6297 // convert FPU condition into eflags condition via rax, | |
6298 save_rax(tmp); | |
6299 fwait(); fnstsw_ax(); | |
6300 sahf(); | |
6301 restore_rax(tmp); | |
6302 } | |
6303 // condition codes set as follows: | |
6304 // | |
6305 // CF (corresponds to C0) if x < y | |
6306 // PF (corresponds to C2) if unordered | |
6307 // ZF (corresponds to C3) if x = y | |
6308 } | |
6309 | |
6310 void MacroAssembler::fcmp2int(Register dst, bool unordered_is_less) { | |
6311 fcmp2int(dst, unordered_is_less, 1, true, true); | |
6312 } | |
6313 | |
6314 void MacroAssembler::fcmp2int(Register dst, bool unordered_is_less, int index, bool pop_left, bool pop_right) { | |
6315 fcmp(VM_Version::supports_cmov() ? noreg : dst, index, pop_left, pop_right); | |
6316 Label L; | |
6317 if (unordered_is_less) { | |
6318 movl(dst, -1); | |
6319 jcc(Assembler::parity, L); | |
6320 jcc(Assembler::below , L); | |
6321 movl(dst, 0); | |
6322 jcc(Assembler::equal , L); | |
6323 increment(dst); | |
6324 } else { // unordered is greater | |
6325 movl(dst, 1); | |
6326 jcc(Assembler::parity, L); | |
6327 jcc(Assembler::above , L); | |
6328 movl(dst, 0); | |
6329 jcc(Assembler::equal , L); | |
304 | 6330 decrementl(dst); |
0 | 6331 } |
6332 bind(L); | |
6333 } | |
6334 | |
304 | 6335 void MacroAssembler::fld_d(AddressLiteral src) { |
6336 fld_d(as_Address(src)); | |
6337 } | |
6338 | |
6339 void MacroAssembler::fld_s(AddressLiteral src) { | |
6340 fld_s(as_Address(src)); | |
6341 } | |
6342 | |
6343 void MacroAssembler::fld_x(AddressLiteral src) { | |
6344 Assembler::fld_x(as_Address(src)); | |
6345 } | |
6346 | |
6347 void MacroAssembler::fldcw(AddressLiteral src) { | |
6348 Assembler::fldcw(as_Address(src)); | |
6349 } | |
0 | 6350 |
6351 void MacroAssembler::fpop() { | |
6352 ffree(); | |
6353 fincstp(); | |
6354 } | |
6355 | |
304 | 6356 void MacroAssembler::fremr(Register tmp) { |
6357 save_rax(tmp); | |
6358 { Label L; | |
6359 bind(L); | |
6360 fprem(); | |
6361 fwait(); fnstsw_ax(); | |
6362 #ifdef _LP64 | |
6363 testl(rax, 0x400); | |
6364 jcc(Assembler::notEqual, L); | |
6365 #else | |
6366 sahf(); | |
6367 jcc(Assembler::parity, L); | |
6368 #endif // _LP64 | |
6369 } | |
6370 restore_rax(tmp); | |
6371 // Result is in ST0. | |
6372 // Note: fxch & fpop to get rid of ST1 | |
6373 // (otherwise FPU stack could overflow eventually) | |
6374 fxch(1); | |
6375 fpop(); | |
6376 } | |
6377 | |
6378 | |
6379 void MacroAssembler::incrementl(AddressLiteral dst) { | |
6380 if (reachable(dst)) { | |
6381 incrementl(as_Address(dst)); | |
0 | 6382 } else { |
304 | 6383 lea(rscratch1, dst); |
6384 incrementl(Address(rscratch1, 0)); | |
6385 } | |
6386 } | |
6387 | |
6388 void MacroAssembler::incrementl(ArrayAddress dst) { | |
6389 incrementl(as_Address(dst)); | |
6390 } | |
6391 | |
6392 void MacroAssembler::incrementl(Register reg, int value) { | |
6393 if (value == min_jint) {addl(reg, value) ; return; } | |
6394 if (value < 0) { decrementl(reg, -value); return; } | |
6395 if (value == 0) { ; return; } | |
6396 if (value == 1 && UseIncDec) { incl(reg) ; return; } | |
6397 /* else */ { addl(reg, value) ; return; } | |
6398 } | |
6399 | |
6400 void MacroAssembler::incrementl(Address dst, int value) { | |
6401 if (value == min_jint) {addl(dst, value) ; return; } | |
6402 if (value < 0) { decrementl(dst, -value); return; } | |
6403 if (value == 0) { ; return; } | |
6404 if (value == 1 && UseIncDec) { incl(dst) ; return; } | |
6405 /* else */ { addl(dst, value) ; return; } | |
6406 } | |
6407 | |
6408 void MacroAssembler::jump(AddressLiteral dst) { | |
6409 if (reachable(dst)) { | |
6410 jmp_literal(dst.target(), dst.rspec()); | |
6411 } else { | |
6412 lea(rscratch1, dst); | |
6413 jmp(rscratch1); | |
6414 } | |
6415 } | |
6416 | |
6417 void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) { | |
6418 if (reachable(dst)) { | |
6419 InstructionMark im(this); | |
6420 relocate(dst.reloc()); | |
6421 const int short_size = 2; | |
6422 const int long_size = 6; | |
6423 int offs = (intptr_t)dst.target() - ((intptr_t)_code_pos); | |
6424 if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) { | |
6425 // 0111 tttn #8-bit disp | |
6426 emit_byte(0x70 | cc); | |
6427 emit_byte((offs - short_size) & 0xFF); | |
6428 } else { | |
6429 // 0000 1111 1000 tttn #32-bit disp | |
6430 emit_byte(0x0F); | |
6431 emit_byte(0x80 | cc); | |
6432 emit_long(offs - long_size); | |
6433 } | |
0 | 6434 } else { |
304 | 6435 #ifdef ASSERT |
6436 warning("reversing conditional branch"); | |
6437 #endif /* ASSERT */ | |
6438 Label skip; | |
6439 jccb(reverse[cc], skip); | |
6440 lea(rscratch1, dst); | |
6441 Assembler::jmp(rscratch1); | |
6442 bind(skip); | |
6443 } | |
6444 } | |
6445 | |
6446 void MacroAssembler::ldmxcsr(AddressLiteral src) { | |
6447 if (reachable(src)) { | |
6448 Assembler::ldmxcsr(as_Address(src)); | |
6449 } else { | |
6450 lea(rscratch1, src); | |
6451 Assembler::ldmxcsr(Address(rscratch1, 0)); | |
6452 } | |
6453 } | |
6454 | |
6455 int MacroAssembler::load_signed_byte(Register dst, Address src) { | |
6456 int off; | |
6457 if (LP64_ONLY(true ||) VM_Version::is_P6()) { | |
6458 off = offset(); | |
6459 movsbl(dst, src); // movsxb | |
6460 } else { | |
6461 off = load_unsigned_byte(dst, src); | |
6462 shll(dst, 24); | |
6463 sarl(dst, 24); | |
6464 } | |
6465 return off; | |
6466 } | |
6467 | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6468 // Note: load_signed_short used to be called load_signed_word. |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6469 // Although the 'w' in x86 opcodes refers to the term "word" in the assembler |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6470 // manual, which means 16 bits, that usage is found nowhere in HotSpot code. |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6471 // The term "word" in HotSpot means a 32- or 64-bit machine word. |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6472 int MacroAssembler::load_signed_short(Register dst, Address src) { |
304 | 6473 int off; |
6474 if (LP64_ONLY(true ||) VM_Version::is_P6()) { | |
6475 // This is dubious to me since it seems safe to do a signed 16 => 64 bit | |
6476 // version but this is what 64bit has always done. This seems to imply | |
6477 // that users are only using 32bits worth. | |
6478 off = offset(); | |
6479 movswl(dst, src); // movsxw | |
6480 } else { | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6481 off = load_unsigned_short(dst, src); |
304 | 6482 shll(dst, 16); |
6483 sarl(dst, 16); | |
6484 } | |
6485 return off; | |
6486 } | |
6487 | |
6488 int MacroAssembler::load_unsigned_byte(Register dst, Address src) { | |
6489 // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, | |
6490 // and "3.9 Partial Register Penalties", p. 22). | |
6491 int off; | |
6492 if (LP64_ONLY(true || ) VM_Version::is_P6() || src.uses(dst)) { | |
6493 off = offset(); | |
6494 movzbl(dst, src); // movzxb | |
6495 } else { | |
6496 xorl(dst, dst); | |
6497 off = offset(); | |
6498 movb(dst, src); | |
6499 } | |
6500 return off; | |
6501 } | |
6502 | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6503 // Note: load_unsigned_short used to be called load_unsigned_word. |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6504 int MacroAssembler::load_unsigned_short(Register dst, Address src) { |
304 | 6505 // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, |
6506 // and "3.9 Partial Register Penalties", p. 22). | |
6507 int off; | |
6508 if (LP64_ONLY(true ||) VM_Version::is_P6() || src.uses(dst)) { | |
6509 off = offset(); | |
6510 movzwl(dst, src); // movzxw | |
6511 } else { | |
6512 xorl(dst, dst); | |
6513 off = offset(); | |
6514 movw(dst, src); | |
6515 } | |
6516 return off; | |
6517 } | |
6518 | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6519 void MacroAssembler::load_sized_value(Register dst, Address src, |
1503 | 6520 size_t size_in_bytes, bool is_signed) { |
6521 switch (size_in_bytes) { | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6522 #ifndef _LP64 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6523 // For case 8, caller is responsible for manually loading |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6524 // the second word into another register. |
1503 | 6525 case 8: movl(dst, src); break; |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6526 #else |
1503 | 6527 case 8: movq(dst, src); break; |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6528 #endif |
1503 | 6529 case 4: movl(dst, src); break; |
6530 case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; | |
6531 case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; | |
6532 default: ShouldNotReachHere(); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6533 } |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6534 } |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
6535 |
304 | 6536 void MacroAssembler::mov32(AddressLiteral dst, Register src) { |
6537 if (reachable(dst)) { | |
6538 movl(as_Address(dst), src); | |
6539 } else { | |
6540 lea(rscratch1, dst); | |
6541 movl(Address(rscratch1, 0), src); | |
6542 } | |
6543 } | |
6544 | |
6545 void MacroAssembler::mov32(Register dst, AddressLiteral src) { | |
6546 if (reachable(src)) { | |
6547 movl(dst, as_Address(src)); | |
6548 } else { | |
6549 lea(rscratch1, src); | |
6550 movl(dst, Address(rscratch1, 0)); | |
6551 } | |
0 | 6552 } |
6553 | |
6554 // C++ bool manipulation | |
6555 | |
6556 void MacroAssembler::movbool(Register dst, Address src) { | |
6557 if(sizeof(bool) == 1) | |
6558 movb(dst, src); | |
6559 else if(sizeof(bool) == 2) | |
6560 movw(dst, src); | |
6561 else if(sizeof(bool) == 4) | |
6562 movl(dst, src); | |
6563 else | |
6564 // unsupported | |
6565 ShouldNotReachHere(); | |
6566 } | |
6567 | |
6568 void MacroAssembler::movbool(Address dst, bool boolconst) { | |
6569 if(sizeof(bool) == 1) | |
6570 movb(dst, (int) boolconst); | |
6571 else if(sizeof(bool) == 2) | |
6572 movw(dst, (int) boolconst); | |
6573 else if(sizeof(bool) == 4) | |
6574 movl(dst, (int) boolconst); | |
6575 else | |
6576 // unsupported | |
6577 ShouldNotReachHere(); | |
6578 } | |
6579 | |
6580 void MacroAssembler::movbool(Address dst, Register src) { | |
6581 if(sizeof(bool) == 1) | |
6582 movb(dst, src); | |
6583 else if(sizeof(bool) == 2) | |
6584 movw(dst, src); | |
6585 else if(sizeof(bool) == 4) | |
6586 movl(dst, src); | |
6587 else | |
6588 // unsupported | |
6589 ShouldNotReachHere(); | |
6590 } | |
6591 | |
304 | 6592 void MacroAssembler::movbyte(ArrayAddress dst, int src) { |
6593 movb(as_Address(dst), src); | |
6594 } | |
6595 | |
6596 void MacroAssembler::movdbl(XMMRegister dst, AddressLiteral src) { | |
6597 if (reachable(src)) { | |
6598 if (UseXmmLoadAndClearUpper) { | |
6599 movsd (dst, as_Address(src)); | |
6600 } else { | |
6601 movlpd(dst, as_Address(src)); | |
6602 } | |
6603 } else { | |
6604 lea(rscratch1, src); | |
6605 if (UseXmmLoadAndClearUpper) { | |
6606 movsd (dst, Address(rscratch1, 0)); | |
6607 } else { | |
6608 movlpd(dst, Address(rscratch1, 0)); | |
6609 } | |
6610 } | |
6611 } | |
6612 | |
6613 void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src) { | |
6614 if (reachable(src)) { | |
6615 movss(dst, as_Address(src)); | |
6616 } else { | |
6617 lea(rscratch1, src); | |
6618 movss(dst, Address(rscratch1, 0)); | |
6619 } | |
6620 } | |
6621 | |
6622 void MacroAssembler::movptr(Register dst, Register src) { | |
6623 LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); | |
6624 } | |
6625 | |
6626 void MacroAssembler::movptr(Register dst, Address src) { | |
6627 LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); | |
6628 } | |
6629 | |
6630 // src should NEVER be a real pointer. Use AddressLiteral for true pointers | |
6631 void MacroAssembler::movptr(Register dst, intptr_t src) { | |
6632 LP64_ONLY(mov64(dst, src)) NOT_LP64(movl(dst, src)); | |
6633 } | |
6634 | |
6635 void MacroAssembler::movptr(Address dst, Register src) { | |
6636 LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); | |
6637 } | |
6638 | |
6639 void MacroAssembler::movss(XMMRegister dst, AddressLiteral src) { | |
6640 if (reachable(src)) { | |
6641 movss(dst, as_Address(src)); | |
6642 } else { | |
6643 lea(rscratch1, src); | |
6644 movss(dst, Address(rscratch1, 0)); | |
6645 } | |
6646 } | |
6647 | |
6648 void MacroAssembler::null_check(Register reg, int offset) { | |
6649 if (needs_explicit_null_check(offset)) { | |
6650 // provoke OS NULL exception if reg = NULL by | |
6651 // accessing M[reg] w/o changing any (non-CC) registers | |
6652 // NOTE: cmpl is plenty here to provoke a segv | |
6653 cmpptr(rax, Address(reg, 0)); | |
6654 // Note: should probably use testl(rax, Address(reg, 0)); | |
6655 // may be shorter code (however, this version of | |
6656 // testl needs to be implemented first) | |
6657 } else { | |
6658 // nothing to do, (later) access of M[reg + offset] | |
6659 // will provoke OS NULL exception if reg = NULL | |
6660 } | |
6661 } | |
6662 | |
6663 void MacroAssembler::os_breakpoint() { | |
6664 // instead of directly emitting a breakpoint, call os:breakpoint for better debugability | |
6665 // (e.g., MSVC can't call ps() otherwise) | |
6666 call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); | |
6667 } | |
6668 | |
6669 void MacroAssembler::pop_CPU_state() { | |
6670 pop_FPU_state(); | |
6671 pop_IU_state(); | |
6672 } | |
6673 | |
6674 void MacroAssembler::pop_FPU_state() { | |
6675 NOT_LP64(frstor(Address(rsp, 0));) | |
6676 LP64_ONLY(fxrstor(Address(rsp, 0));) | |
6677 addptr(rsp, FPUStateSizeInWords * wordSize); | |
6678 } | |
6679 | |
6680 void MacroAssembler::pop_IU_state() { | |
6681 popa(); | |
6682 LP64_ONLY(addq(rsp, 8)); | |
6683 popf(); | |
6684 } | |
6685 | |
6686 // Save Integer and Float state | |
6687 // Warning: Stack must be 16 byte aligned (64bit) | |
6688 void MacroAssembler::push_CPU_state() { | |
6689 push_IU_state(); | |
6690 push_FPU_state(); | |
6691 } | |
6692 | |
6693 void MacroAssembler::push_FPU_state() { | |
6694 subptr(rsp, FPUStateSizeInWords * wordSize); | |
6695 #ifndef _LP64 | |
6696 fnsave(Address(rsp, 0)); | |
6697 fwait(); | |
6698 #else | |
6699 fxsave(Address(rsp, 0)); | |
6700 #endif // LP64 | |
6701 } | |
6702 | |
6703 void MacroAssembler::push_IU_state() { | |
6704 // Push flags first because pusha kills them | |
6705 pushf(); | |
6706 // Make sure rsp stays 16-byte aligned | |
6707 LP64_ONLY(subq(rsp, 8)); | |
6708 pusha(); | |
6709 } | |
6710 | |
6711 void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp, bool clear_pc) { | |
6712 // determine java_thread register | |
6713 if (!java_thread->is_valid()) { | |
6714 java_thread = rdi; | |
6715 get_thread(java_thread); | |
6716 } | |
6717 // we must set sp to zero to clear frame | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
6718 movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); |
304 | 6719 if (clear_fp) { |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
6720 movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); |
304 | 6721 } |
6722 | |
6723 if (clear_pc) | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
420
diff
changeset
|
6724 movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); |
304 | 6725 |
6726 } | |
6727 | |
6728 void MacroAssembler::restore_rax(Register tmp) { | |
6729 if (tmp == noreg) pop(rax); | |
6730 else if (tmp != rax) mov(rax, tmp); | |
6731 } | |
6732 | |
6733 void MacroAssembler::round_to(Register reg, int modulus) { | |
6734 addptr(reg, modulus - 1); | |
6735 andptr(reg, -modulus); | |
6736 } | |
6737 | |
6738 void MacroAssembler::save_rax(Register tmp) { | |
6739 if (tmp == noreg) push(rax); | |
6740 else if (tmp != rax) mov(tmp, rax); | |
6741 } | |
6742 | |
6743 // Write serialization page so VM thread can do a pseudo remote membar. | |
6744 // We use the current thread pointer to calculate a thread specific | |
6745 // offset to write to within the page. This minimizes bus traffic | |
6746 // due to cache line collision. | |
6747 void MacroAssembler::serialize_memory(Register thread, Register tmp) { | |
6748 movl(tmp, thread); | |
6749 shrl(tmp, os::get_serialize_page_shift_count()); | |
6750 andl(tmp, (os::vm_page_size() - sizeof(int))); | |
6751 | |
6752 Address index(noreg, tmp, Address::times_1); | |
6753 ExternalAddress page(os::get_memory_serialize_page()); | |
6754 | |
606
19962e74284f
6811384: MacroAssembler::serialize_memory may touch next page on amd64
never
parents:
520
diff
changeset
|
6755 // Size of store must match masking code above |
19962e74284f
6811384: MacroAssembler::serialize_memory may touch next page on amd64
never
parents:
520
diff
changeset
|
6756 movl(as_Address(ArrayAddress(page, index)), tmp); |
304 | 6757 } |
6758 | |
6759 // Calls to C land | |
6760 // | |
6761 // When entering C land, the rbp, & rsp of the last Java frame have to be recorded | |
6762 // in the (thread-local) JavaThread object. When leaving C land, the last Java fp | |
6763 // has to be reset to 0. This is required to allow proper stack traversal. | |
6764 void MacroAssembler::set_last_Java_frame(Register java_thread, | |
6765 Register last_java_sp, | |
6766 Register last_java_fp, | |
6767 address last_java_pc) { | |
6768 // determine java_thread register | |
6769 if (!java_thread->is_valid()) { | |
6770 java_thread = rdi; | |
6771 get_thread(java_thread); | |
6772 } | |
6773 // determine last_java_sp register | |
6774 if (!last_java_sp->is_valid()) { | |
6775 last_java_sp = rsp; | |
6776 } | |
6777 | |
6778 // last_java_fp is optional | |
6779 | |
6780 if (last_java_fp->is_valid()) { | |
6781 movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), last_java_fp); | |
6782 } | |
6783 | |
6784 // last_java_pc is optional | |
6785 | |
6786 if (last_java_pc != NULL) { | |
6787 lea(Address(java_thread, | |
6788 JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()), | |
6789 InternalAddress(last_java_pc)); | |
6790 | |
6791 } | |
6792 movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), last_java_sp); | |
6793 } | |
6794 | |
6795 void MacroAssembler::shlptr(Register dst, int imm8) { | |
6796 LP64_ONLY(shlq(dst, imm8)) NOT_LP64(shll(dst, imm8)); | |
6797 } | |
6798 | |
6799 void MacroAssembler::shrptr(Register dst, int imm8) { | |
6800 LP64_ONLY(shrq(dst, imm8)) NOT_LP64(shrl(dst, imm8)); | |
6801 } | |
6802 | |
6803 void MacroAssembler::sign_extend_byte(Register reg) { | |
6804 if (LP64_ONLY(true ||) (VM_Version::is_P6() && reg->has_byte_register())) { | |
6805 movsbl(reg, reg); // movsxb | |
6806 } else { | |
6807 shll(reg, 24); | |
6808 sarl(reg, 24); | |
6809 } | |
6810 } | |
6811 | |
6812 void MacroAssembler::sign_extend_short(Register reg) { | |
6813 if (LP64_ONLY(true ||) VM_Version::is_P6()) { | |
6814 movswl(reg, reg); // movsxw | |
6815 } else { | |
6816 shll(reg, 16); | |
6817 sarl(reg, 16); | |
6818 } | |
6819 } | |
6820 | |
362 | 6821 ////////////////////////////////////////////////////////////////////////////////// |
6822 #ifndef SERIALGC | |
6823 | |
6824 void MacroAssembler::g1_write_barrier_pre(Register obj, | |
6825 #ifndef _LP64 | |
6826 Register thread, | |
6827 #endif | |
6828 Register tmp, | |
6829 Register tmp2, | |
6830 bool tosca_live) { | |
6831 LP64_ONLY(Register thread = r15_thread;) | |
6832 Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + | |
6833 PtrQueue::byte_offset_of_active())); | |
6834 | |
6835 Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + | |
6836 PtrQueue::byte_offset_of_index())); | |
6837 Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + | |
6838 PtrQueue::byte_offset_of_buf())); | |
6839 | |
6840 | |
6841 Label done; | |
6842 Label runtime; | |
6843 | |
6844 // if (!marking_in_progress) goto done; | |
6845 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { | |
6846 cmpl(in_progress, 0); | |
6847 } else { | |
6848 assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); | |
6849 cmpb(in_progress, 0); | |
6850 } | |
6851 jcc(Assembler::equal, done); | |
6852 | |
6853 // if (x.f == NULL) goto done; | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6854 #ifdef _LP64 |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6855 load_heap_oop(tmp2, Address(obj, 0)); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6856 #else |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6857 movptr(tmp2, Address(obj, 0)); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6858 #endif |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6859 cmpptr(tmp2, (int32_t) NULL_WORD); |
362 | 6860 jcc(Assembler::equal, done); |
6861 | |
6862 // Can we store original value in the thread's buffer? | |
6863 | |
6864 #ifdef _LP64 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6865 movslq(tmp, index); |
362 | 6866 cmpq(tmp, 0); |
6867 #else | |
6868 cmpl(index, 0); | |
6869 #endif | |
6870 jcc(Assembler::equal, runtime); | |
6871 #ifdef _LP64 | |
6872 subq(tmp, wordSize); | |
6873 movl(index, tmp); | |
6874 addq(tmp, buffer); | |
6875 #else | |
6876 subl(index, wordSize); | |
6877 movl(tmp, buffer); | |
6878 addl(tmp, index); | |
6879 #endif | |
6880 movptr(Address(tmp, 0), tmp2); | |
6881 jmp(done); | |
6882 bind(runtime); | |
6883 // save the live input values | |
6884 if(tosca_live) push(rax); | |
6885 push(obj); | |
6886 #ifdef _LP64 | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
775
diff
changeset
|
6887 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, r15_thread); |
362 | 6888 #else |
6889 push(thread); | |
6890 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, thread); | |
6891 pop(thread); | |
6892 #endif | |
6893 pop(obj); | |
6894 if(tosca_live) pop(rax); | |
6895 bind(done); | |
6896 | |
6897 } | |
6898 | |
6899 void MacroAssembler::g1_write_barrier_post(Register store_addr, | |
6900 Register new_val, | |
6901 #ifndef _LP64 | |
6902 Register thread, | |
6903 #endif | |
6904 Register tmp, | |
6905 Register tmp2) { | |
6906 | |
6907 LP64_ONLY(Register thread = r15_thread;) | |
6908 Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + | |
6909 PtrQueue::byte_offset_of_index())); | |
6910 Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + | |
6911 PtrQueue::byte_offset_of_buf())); | |
6912 BarrierSet* bs = Universe::heap()->barrier_set(); | |
6913 CardTableModRefBS* ct = (CardTableModRefBS*)bs; | |
6914 Label done; | |
6915 Label runtime; | |
6916 | |
6917 // Does store cross heap regions? | |
6918 | |
6919 movptr(tmp, store_addr); | |
6920 xorptr(tmp, new_val); | |
6921 shrptr(tmp, HeapRegion::LogOfHRGrainBytes); | |
6922 jcc(Assembler::equal, done); | |
6923 | |
6924 // crosses regions, storing NULL? | |
6925 | |
6926 cmpptr(new_val, (int32_t) NULL_WORD); | |
6927 jcc(Assembler::equal, done); | |
6928 | |
6929 // storing region crossing non-NULL, is card already dirty? | |
6930 | |
6931 ExternalAddress cardtable((address) ct->byte_map_base); | |
6932 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); | |
6933 #ifdef _LP64 | |
6934 const Register card_addr = tmp; | |
6935 | |
6936 movq(card_addr, store_addr); | |
6937 shrq(card_addr, CardTableModRefBS::card_shift); | |
6938 | |
6939 lea(tmp2, cardtable); | |
6940 | |
6941 // get the address of the card | |
6942 addq(card_addr, tmp2); | |
6943 #else | |
6944 const Register card_index = tmp; | |
6945 | |
6946 movl(card_index, store_addr); | |
6947 shrl(card_index, CardTableModRefBS::card_shift); | |
6948 | |
6949 Address index(noreg, card_index, Address::times_1); | |
6950 const Register card_addr = tmp; | |
6951 lea(card_addr, as_Address(ArrayAddress(cardtable, index))); | |
6952 #endif | |
6953 cmpb(Address(card_addr, 0), 0); | |
6954 jcc(Assembler::equal, done); | |
6955 | |
6956 // storing a region crossing, non-NULL oop, card is clean. | |
6957 // dirty card and log. | |
6958 | |
6959 movb(Address(card_addr, 0), 0); | |
6960 | |
6961 cmpl(queue_index, 0); | |
6962 jcc(Assembler::equal, runtime); | |
6963 subl(queue_index, wordSize); | |
6964 movptr(tmp2, buffer); | |
6965 #ifdef _LP64 | |
6966 movslq(rscratch1, queue_index); | |
6967 addq(tmp2, rscratch1); | |
6968 movq(Address(tmp2, 0), card_addr); | |
6969 #else | |
6970 addl(tmp2, queue_index); | |
6971 movl(Address(tmp2, 0), card_index); | |
6972 #endif | |
6973 jmp(done); | |
6974 | |
6975 bind(runtime); | |
6976 // save the live input values | |
6977 push(store_addr); | |
6978 push(new_val); | |
6979 #ifdef _LP64 | |
6980 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, r15_thread); | |
6981 #else | |
6982 push(thread); | |
6983 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); | |
6984 pop(thread); | |
6985 #endif | |
6986 pop(new_val); | |
6987 pop(store_addr); | |
6988 | |
6989 bind(done); | |
6990 | |
6991 } | |
6992 | |
6993 #endif // SERIALGC | |
6994 ////////////////////////////////////////////////////////////////////////////////// | |
6995 | |
6996 | |
304 | 6997 void MacroAssembler::store_check(Register obj) { |
6998 // Does a store check for the oop in register obj. The content of | |
6999 // register obj is destroyed afterwards. | |
7000 store_check_part_1(obj); | |
7001 store_check_part_2(obj); | |
7002 } | |
7003 | |
7004 void MacroAssembler::store_check(Register obj, Address dst) { | |
7005 store_check(obj); | |
7006 } | |
7007 | |
7008 | |
7009 // split the store check operation so that other instructions can be scheduled inbetween | |
7010 void MacroAssembler::store_check_part_1(Register obj) { | |
7011 BarrierSet* bs = Universe::heap()->barrier_set(); | |
7012 assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); | |
7013 shrptr(obj, CardTableModRefBS::card_shift); | |
7014 } | |
7015 | |
7016 void MacroAssembler::store_check_part_2(Register obj) { | |
7017 BarrierSet* bs = Universe::heap()->barrier_set(); | |
7018 assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); | |
7019 CardTableModRefBS* ct = (CardTableModRefBS*)bs; | |
7020 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); | |
7021 | |
7022 // The calculation for byte_map_base is as follows: | |
7023 // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); | |
7024 // So this essentially converts an address to a displacement and | |
7025 // it will never need to be relocated. On 64bit however the value may be too | |
7026 // large for a 32bit displacement | |
7027 | |
7028 intptr_t disp = (intptr_t) ct->byte_map_base; | |
7029 if (is_simm32(disp)) { | |
7030 Address cardtable(noreg, obj, Address::times_1, disp); | |
7031 movb(cardtable, 0); | |
7032 } else { | |
7033 // By doing it as an ExternalAddress disp could be converted to a rip-relative | |
7034 // displacement and done in a single instruction given favorable mapping and | |
7035 // a smarter version of as_Address. Worst case it is two instructions which | |
7036 // is no worse off then loading disp into a register and doing as a simple | |
7037 // Address() as above. | |
7038 // We can't do as ExternalAddress as the only style since if disp == 0 we'll | |
7039 // assert since NULL isn't acceptable in a reloci (see 6644928). In any case | |
7040 // in some cases we'll get a single instruction version. | |
7041 | |
7042 ExternalAddress cardtable((address)disp); | |
7043 Address index(noreg, obj, Address::times_1); | |
7044 movb(as_Address(ArrayAddress(cardtable, index)), 0); | |
7045 } | |
7046 } | |
7047 | |
7048 void MacroAssembler::subptr(Register dst, int32_t imm32) { | |
7049 LP64_ONLY(subq(dst, imm32)) NOT_LP64(subl(dst, imm32)); | |
7050 } | |
7051 | |
7052 void MacroAssembler::subptr(Register dst, Register src) { | |
7053 LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); | |
7054 } | |
7055 | |
7056 void MacroAssembler::test32(Register src1, AddressLiteral src2) { | |
7057 // src2 must be rval | |
7058 | |
7059 if (reachable(src2)) { | |
7060 testl(src1, as_Address(src2)); | |
7061 } else { | |
7062 lea(rscratch1, src2); | |
7063 testl(src1, Address(rscratch1, 0)); | |
7064 } | |
7065 } | |
7066 | |
7067 // C++ bool manipulation | |
0 | 7068 void MacroAssembler::testbool(Register dst) { |
7069 if(sizeof(bool) == 1) | |
304 | 7070 testb(dst, 0xff); |
0 | 7071 else if(sizeof(bool) == 2) { |
7072 // testw implementation needed for two byte bools | |
7073 ShouldNotReachHere(); | |
7074 } else if(sizeof(bool) == 4) | |
7075 testl(dst, dst); | |
7076 else | |
7077 // unsupported | |
7078 ShouldNotReachHere(); | |
7079 } | |
7080 | |
304 | 7081 void MacroAssembler::testptr(Register dst, Register src) { |
7082 LP64_ONLY(testq(dst, src)) NOT_LP64(testl(dst, src)); | |
7083 } | |
7084 | |
7085 // Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes. | |
7086 void MacroAssembler::tlab_allocate(Register obj, | |
7087 Register var_size_in_bytes, | |
7088 int con_size_in_bytes, | |
7089 Register t1, | |
7090 Register t2, | |
7091 Label& slow_case) { | |
7092 assert_different_registers(obj, t1, t2); | |
7093 assert_different_registers(obj, var_size_in_bytes, t1); | |
7094 Register end = t2; | |
7095 Register thread = NOT_LP64(t1) LP64_ONLY(r15_thread); | |
7096 | |
7097 verify_tlab(); | |
7098 | |
7099 NOT_LP64(get_thread(thread)); | |
7100 | |
7101 movptr(obj, Address(thread, JavaThread::tlab_top_offset())); | |
7102 if (var_size_in_bytes == noreg) { | |
7103 lea(end, Address(obj, con_size_in_bytes)); | |
7104 } else { | |
7105 lea(end, Address(obj, var_size_in_bytes, Address::times_1)); | |
7106 } | |
7107 cmpptr(end, Address(thread, JavaThread::tlab_end_offset())); | |
7108 jcc(Assembler::above, slow_case); | |
7109 | |
7110 // update the tlab top pointer | |
7111 movptr(Address(thread, JavaThread::tlab_top_offset()), end); | |
7112 | |
7113 // recover var_size_in_bytes if necessary | |
7114 if (var_size_in_bytes == end) { | |
7115 subptr(var_size_in_bytes, obj); | |
7116 } | |
7117 verify_tlab(); | |
7118 } | |
7119 | |
7120 // Preserves rbx, and rdx. | |
7121 void MacroAssembler::tlab_refill(Label& retry, | |
7122 Label& try_eden, | |
7123 Label& slow_case) { | |
7124 Register top = rax; | |
7125 Register t1 = rcx; | |
7126 Register t2 = rsi; | |
7127 Register thread_reg = NOT_LP64(rdi) LP64_ONLY(r15_thread); | |
7128 assert_different_registers(top, thread_reg, t1, t2, /* preserve: */ rbx, rdx); | |
7129 Label do_refill, discard_tlab; | |
7130 | |
7131 if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { | |
7132 // No allocation in the shared eden. | |
7133 jmp(slow_case); | |
7134 } | |
7135 | |
7136 NOT_LP64(get_thread(thread_reg)); | |
7137 | |
7138 movptr(top, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); | |
7139 movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); | |
7140 | |
7141 // calculate amount of free space | |
7142 subptr(t1, top); | |
7143 shrptr(t1, LogHeapWordSize); | |
7144 | |
7145 // Retain tlab and allocate object in shared space if | |
7146 // the amount free in the tlab is too large to discard. | |
7147 cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_refill_waste_limit_offset()))); | |
7148 jcc(Assembler::lessEqual, discard_tlab); | |
7149 | |
7150 // Retain | |
7151 // %%% yuck as movptr... | |
7152 movptr(t2, (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); | |
7153 addptr(Address(thread_reg, in_bytes(JavaThread::tlab_refill_waste_limit_offset())), t2); | |
7154 if (TLABStats) { | |
7155 // increment number of slow_allocations | |
7156 addl(Address(thread_reg, in_bytes(JavaThread::tlab_slow_allocations_offset())), 1); | |
7157 } | |
7158 jmp(try_eden); | |
7159 | |
7160 bind(discard_tlab); | |
7161 if (TLABStats) { | |
7162 // increment number of refills | |
7163 addl(Address(thread_reg, in_bytes(JavaThread::tlab_number_of_refills_offset())), 1); | |
7164 // accumulate wastage -- t1 is amount free in tlab | |
7165 addl(Address(thread_reg, in_bytes(JavaThread::tlab_fast_refill_waste_offset())), t1); | |
7166 } | |
7167 | |
7168 // if tlab is currently allocated (top or end != null) then | |
7169 // fill [top, end + alignment_reserve) with array object | |
7170 testptr (top, top); | |
7171 jcc(Assembler::zero, do_refill); | |
7172 | |
7173 // set up the mark word | |
7174 movptr(Address(top, oopDesc::mark_offset_in_bytes()), (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); | |
7175 // set the length to the remaining space | |
7176 subptr(t1, typeArrayOopDesc::header_size(T_INT)); | |
7177 addptr(t1, (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); | |
7178 shlptr(t1, log2_intptr(HeapWordSize/sizeof(jint))); | |
1690 | 7179 movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); |
304 | 7180 // set klass to intArrayKlass |
7181 // dubious reloc why not an oop reloc? | |
7182 movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); | |
7183 // store klass last. concurrent gcs assumes klass length is valid if | |
7184 // klass field is not null. | |
7185 store_klass(top, t1); | |
7186 | |
7187 // refill the tlab with an eden allocation | |
7188 bind(do_refill); | |
7189 movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); | |
7190 shlptr(t1, LogHeapWordSize); | |
7191 // add object_size ?? | |
7192 eden_allocate(top, t1, 0, t2, slow_case); | |
7193 | |
7194 // Check that t1 was preserved in eden_allocate. | |
7195 #ifdef ASSERT | |
7196 if (UseTLAB) { | |
7197 Label ok; | |
7198 Register tsize = rsi; | |
7199 assert_different_registers(tsize, thread_reg, t1); | |
7200 push(tsize); | |
7201 movptr(tsize, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); | |
7202 shlptr(tsize, LogHeapWordSize); | |
7203 cmpptr(t1, tsize); | |
7204 jcc(Assembler::equal, ok); | |
7205 stop("assert(t1 != tlab size)"); | |
7206 should_not_reach_here(); | |
7207 | |
7208 bind(ok); | |
7209 pop(tsize); | |
7210 } | |
7211 #endif | |
7212 movptr(Address(thread_reg, in_bytes(JavaThread::tlab_start_offset())), top); | |
7213 movptr(Address(thread_reg, in_bytes(JavaThread::tlab_top_offset())), top); | |
7214 addptr(top, t1); | |
7215 subptr(top, (int32_t)ThreadLocalAllocBuffer::alignment_reserve_in_bytes()); | |
7216 movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top); | |
7217 verify_tlab(); | |
7218 jmp(retry); | |
7219 } | |
7220 | |
7221 static const double pi_4 = 0.7853981633974483; | |
7222 | |
7223 void MacroAssembler::trigfunc(char trig, int num_fpu_regs_in_use) { | |
7224 // A hand-coded argument reduction for values in fabs(pi/4, pi/2) | |
7225 // was attempted in this code; unfortunately it appears that the | |
7226 // switch to 80-bit precision and back causes this to be | |
7227 // unprofitable compared with simply performing a runtime call if | |
7228 // the argument is out of the (-pi/4, pi/4) range. | |
7229 | |
7230 Register tmp = noreg; | |
7231 if (!VM_Version::supports_cmov()) { | |
7232 // fcmp needs a temporary so preserve rbx, | |
7233 tmp = rbx; | |
7234 push(tmp); | |
7235 } | |
7236 | |
7237 Label slow_case, done; | |
7238 | |
520
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7239 ExternalAddress pi4_adr = (address)&pi_4; |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7240 if (reachable(pi4_adr)) { |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7241 // x ?<= pi/4 |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7242 fld_d(pi4_adr); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7243 fld_s(1); // Stack: X PI/4 X |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7244 fabs(); // Stack: |X| PI/4 X |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7245 fcmp(tmp); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7246 jcc(Assembler::above, slow_case); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7247 |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7248 // fastest case: -pi/4 <= x <= pi/4 |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7249 switch(trig) { |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7250 case 's': |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7251 fsin(); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7252 break; |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7253 case 'c': |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7254 fcos(); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7255 break; |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7256 case 't': |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7257 ftan(); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7258 break; |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7259 default: |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7260 assert(false, "bad intrinsic"); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7261 break; |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7262 } |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7263 jmp(done); |
52a431267315
6791168: Fix invalid code in bytecodeInterpreter that can cause gcc ICE
coleenp
parents:
512
diff
changeset
|
7264 } |
304 | 7265 |
7266 // slow case: runtime call | |
7267 bind(slow_case); | |
7268 // Preserve registers across runtime call | |
7269 pusha(); | |
7270 int incoming_argument_and_return_value_offset = -1; | |
7271 if (num_fpu_regs_in_use > 1) { | |
7272 // Must preserve all other FPU regs (could alternatively convert | |
7273 // SharedRuntime::dsin and dcos into assembly routines known not to trash | |
7274 // FPU state, but can not trust C compiler) | |
7275 NEEDS_CLEANUP; | |
7276 // NOTE that in this case we also push the incoming argument to | |
7277 // the stack and restore it later; we also use this stack slot to | |
7278 // hold the return value from dsin or dcos. | |
7279 for (int i = 0; i < num_fpu_regs_in_use; i++) { | |
7280 subptr(rsp, sizeof(jdouble)); | |
7281 fstp_d(Address(rsp, 0)); | |
7282 } | |
7283 incoming_argument_and_return_value_offset = sizeof(jdouble)*(num_fpu_regs_in_use-1); | |
7284 fld_d(Address(rsp, incoming_argument_and_return_value_offset)); | |
7285 } | |
7286 subptr(rsp, sizeof(jdouble)); | |
7287 fstp_d(Address(rsp, 0)); | |
7288 #ifdef _LP64 | |
7289 movdbl(xmm0, Address(rsp, 0)); | |
7290 #endif // _LP64 | |
7291 | |
7292 // NOTE: we must not use call_VM_leaf here because that requires a | |
7293 // complete interpreter frame in debug mode -- same bug as 4387334 | |
7294 // MacroAssembler::call_VM_leaf_base is perfectly safe and will | |
7295 // do proper 64bit abi | |
7296 | |
7297 NEEDS_CLEANUP; | |
7298 // Need to add stack banging before this runtime call if it needs to | |
7299 // be taken; however, there is no generic stack banging routine at | |
7300 // the MacroAssembler level | |
7301 switch(trig) { | |
7302 case 's': | |
7303 { | |
7304 MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::dsin), 0); | |
7305 } | |
7306 break; | |
7307 case 'c': | |
7308 { | |
7309 MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::dcos), 0); | |
7310 } | |
7311 break; | |
7312 case 't': | |
7313 { | |
7314 MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::dtan), 0); | |
7315 } | |
7316 break; | |
7317 default: | |
7318 assert(false, "bad intrinsic"); | |
7319 break; | |
7320 } | |
7321 #ifdef _LP64 | |
7322 movsd(Address(rsp, 0), xmm0); | |
7323 fld_d(Address(rsp, 0)); | |
7324 #endif // _LP64 | |
7325 addptr(rsp, sizeof(jdouble)); | |
7326 if (num_fpu_regs_in_use > 1) { | |
7327 // Must save return value to stack and then restore entire FPU stack | |
7328 fstp_d(Address(rsp, incoming_argument_and_return_value_offset)); | |
7329 for (int i = 0; i < num_fpu_regs_in_use; i++) { | |
7330 fld_d(Address(rsp, 0)); | |
7331 addptr(rsp, sizeof(jdouble)); | |
7332 } | |
7333 } | |
7334 popa(); | |
7335 | |
7336 // Come here with result in F-TOS | |
7337 bind(done); | |
7338 | |
7339 if (tmp != noreg) { | |
7340 pop(tmp); | |
7341 } | |
7342 } | |
7343 | |
7344 | |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7345 // Look up the method for a megamorphic invokeinterface call. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7346 // The target method is determined by <intf_klass, itable_index>. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7347 // The receiver klass is in recv_klass. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7348 // On success, the result will be in method_result, and execution falls through. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7349 // On failure, execution transfers to the given label. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7350 void MacroAssembler::lookup_interface_method(Register recv_klass, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7351 Register intf_klass, |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7352 RegisterOrConstant itable_index, |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7353 Register method_result, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7354 Register scan_temp, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7355 Label& L_no_such_interface) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7356 assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7357 assert(itable_index.is_constant() || itable_index.as_register() == method_result, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7358 "caller must use same register for non-constant itable index as for method"); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7359 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7360 // Compute start of first itableOffsetEntry (which is at the end of the vtable) |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7361 int vtable_base = instanceKlass::vtable_start_offset() * wordSize; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7362 int itentry_off = itableMethodEntry::method_offset_in_bytes(); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7363 int scan_step = itableOffsetEntry::size() * wordSize; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7364 int vte_size = vtableEntry::size() * wordSize; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7365 Address::ScaleFactor times_vte_scale = Address::times_ptr; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7366 assert(vte_size == wordSize, "else adjust times_vte_scale"); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7367 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7368 movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize)); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7369 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7370 // %%% Could store the aligned, prescaled offset in the klassoop. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7371 lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7372 if (HeapWordsPerLong > 1) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7373 // Round up to align_object_offset boundary |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7374 // see code for instanceKlass::start_of_itable! |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7375 round_to(scan_temp, BytesPerLong); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7376 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7377 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7378 // Adjust recv_klass by scaled itable_index, so we can free itable_index. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7379 assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7380 lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7381 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7382 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7383 // if (scan->interface() == intf) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7384 // result = (klass + scan->offset() + itable_index); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7385 // } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7386 // } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7387 Label search, found_method; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7388 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7389 for (int peel = 1; peel >= 0; peel--) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7390 movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes())); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7391 cmpptr(intf_klass, method_result); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7392 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7393 if (peel) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7394 jccb(Assembler::equal, found_method); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7395 } else { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7396 jccb(Assembler::notEqual, search); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7397 // (invert the test to fall through to found_method...) |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7398 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7399 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7400 if (!peel) break; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7401 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7402 bind(search); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7403 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7404 // Check that the previous entry is non-null. A null entry means that |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7405 // the receiver class doesn't implement the interface, and wasn't the |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7406 // same as when the caller was compiled. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7407 testptr(method_result, method_result); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7408 jcc(Assembler::zero, L_no_such_interface); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7409 addptr(scan_temp, scan_step); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7410 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7411 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7412 bind(found_method); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7413 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7414 // Got a hit. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7415 movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7416 movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7417 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7418 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
7419 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7420 void MacroAssembler::check_klass_subtype(Register sub_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7421 Register super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7422 Register temp_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7423 Label& L_success) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7424 Label L_failure; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7425 check_klass_subtype_fast_path(sub_klass, super_klass, temp_reg, &L_success, &L_failure, NULL); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7426 check_klass_subtype_slow_path(sub_klass, super_klass, temp_reg, noreg, &L_success, NULL); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7427 bind(L_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7428 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7429 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7430 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7431 void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7432 Register super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7433 Register temp_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7434 Label* L_success, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7435 Label* L_failure, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7436 Label* L_slow_path, |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7437 RegisterOrConstant super_check_offset) { |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7438 assert_different_registers(sub_klass, super_klass, temp_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7439 bool must_load_sco = (super_check_offset.constant_or_zero() == -1); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7440 if (super_check_offset.is_register()) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7441 assert_different_registers(sub_klass, super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7442 super_check_offset.as_register()); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7443 } else if (must_load_sco) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7444 assert(temp_reg != noreg, "supply either a temp or a register offset"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7445 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7446 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7447 Label L_fallthrough; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7448 int label_nulls = 0; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7449 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7450 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7451 if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7452 assert(label_nulls <= 1, "at most one NULL in the batch"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7453 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7454 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7455 Klass::secondary_super_cache_offset_in_bytes()); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7456 int sco_offset = (klassOopDesc::header_size() * HeapWordSize + |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7457 Klass::super_check_offset_offset_in_bytes()); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7458 Address super_check_offset_addr(super_klass, sco_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7459 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7460 // Hacked jcc, which "knows" that L_fallthrough, at least, is in |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7461 // range of a jccb. If this routine grows larger, reconsider at |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7462 // least some of these. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7463 #define local_jcc(assembler_cond, label) \ |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7464 if (&(label) == &L_fallthrough) jccb(assembler_cond, label); \ |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7465 else jcc( assembler_cond, label) /*omit semi*/ |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7466 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7467 // Hacked jmp, which may only be used just before L_fallthrough. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7468 #define final_jmp(label) \ |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7469 if (&(label) == &L_fallthrough) { /*do nothing*/ } \ |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7470 else jmp(label) /*omit semi*/ |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7471 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7472 // If the pointers are equal, we are done (e.g., String[] elements). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7473 // This self-check enables sharing of secondary supertype arrays among |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7474 // non-primary types such as array-of-interface. Otherwise, each such |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7475 // type would need its own customized SSA. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7476 // We move this check to the front of the fast path because many |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7477 // type checks are in fact trivially successful in this manner, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7478 // so we get a nicely predicted branch right at the start of the check. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7479 cmpptr(sub_klass, super_klass); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7480 local_jcc(Assembler::equal, *L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7481 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7482 // Check the supertype display: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7483 if (must_load_sco) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7484 // Positive movl does right thing on LP64. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7485 movl(temp_reg, super_check_offset_addr); |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7486 super_check_offset = RegisterOrConstant(temp_reg); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7487 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7488 Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7489 cmpptr(super_klass, super_check_addr); // load displayed supertype |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7490 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7491 // This check has worked decisively for primary supers. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7492 // Secondary supers are sought in the super_cache ('super_cache_addr'). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7493 // (Secondary supers are interfaces and very deeply nested subtypes.) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7494 // This works in the same check above because of a tricky aliasing |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7495 // between the super_cache and the primary super display elements. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7496 // (The 'super_check_addr' can address either, as the case requires.) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7497 // Note that the cache is updated below if it does not help us find |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7498 // what we need immediately. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7499 // So if it was a primary super, we can just fail immediately. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7500 // Otherwise, it's the slow path for us (no success at this point). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7501 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7502 if (super_check_offset.is_register()) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7503 local_jcc(Assembler::equal, *L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7504 cmpl(super_check_offset.as_register(), sc_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7505 if (L_failure == &L_fallthrough) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7506 local_jcc(Assembler::equal, *L_slow_path); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7507 } else { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7508 local_jcc(Assembler::notEqual, *L_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7509 final_jmp(*L_slow_path); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7510 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7511 } else if (super_check_offset.as_constant() == sc_offset) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7512 // Need a slow path; fast failure is impossible. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7513 if (L_slow_path == &L_fallthrough) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7514 local_jcc(Assembler::equal, *L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7515 } else { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7516 local_jcc(Assembler::notEqual, *L_slow_path); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7517 final_jmp(*L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7518 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7519 } else { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7520 // No slow path; it's a fast decision. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7521 if (L_failure == &L_fallthrough) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7522 local_jcc(Assembler::equal, *L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7523 } else { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7524 local_jcc(Assembler::notEqual, *L_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7525 final_jmp(*L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7526 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7527 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7528 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7529 bind(L_fallthrough); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7530 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7531 #undef local_jcc |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7532 #undef final_jmp |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7533 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7534 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7535 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7536 void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7537 Register super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7538 Register temp_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7539 Register temp2_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7540 Label* L_success, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7541 Label* L_failure, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7542 bool set_cond_codes) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7543 assert_different_registers(sub_klass, super_klass, temp_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7544 if (temp2_reg != noreg) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7545 assert_different_registers(sub_klass, super_klass, temp_reg, temp2_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7546 #define IS_A_TEMP(reg) ((reg) == temp_reg || (reg) == temp2_reg) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7547 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7548 Label L_fallthrough; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7549 int label_nulls = 0; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7550 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7551 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7552 assert(label_nulls <= 1, "at most one NULL in the batch"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7553 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7554 // a couple of useful fields in sub_klass: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7555 int ss_offset = (klassOopDesc::header_size() * HeapWordSize + |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7556 Klass::secondary_supers_offset_in_bytes()); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7557 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7558 Klass::secondary_super_cache_offset_in_bytes()); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7559 Address secondary_supers_addr(sub_klass, ss_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7560 Address super_cache_addr( sub_klass, sc_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7561 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7562 // Do a linear scan of the secondary super-klass chain. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7563 // This code is rarely used, so simplicity is a virtue here. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7564 // The repne_scan instruction uses fixed registers, which we must spill. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7565 // Don't worry too much about pre-existing connections with the input regs. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7566 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7567 assert(sub_klass != rax, "killed reg"); // killed by mov(rax, super) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7568 assert(sub_klass != rcx, "killed reg"); // killed by lea(rcx, &pst_counter) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7569 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7570 // Get super_klass value into rax (even if it was in rdi or rcx). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7571 bool pushed_rax = false, pushed_rcx = false, pushed_rdi = false; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7572 if (super_klass != rax || UseCompressedOops) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7573 if (!IS_A_TEMP(rax)) { push(rax); pushed_rax = true; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7574 mov(rax, super_klass); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7575 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7576 if (!IS_A_TEMP(rcx)) { push(rcx); pushed_rcx = true; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7577 if (!IS_A_TEMP(rdi)) { push(rdi); pushed_rdi = true; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7578 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7579 #ifndef PRODUCT |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7580 int* pst_counter = &SharedRuntime::_partial_subtype_ctr; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7581 ExternalAddress pst_counter_addr((address) pst_counter); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7582 NOT_LP64( incrementl(pst_counter_addr) ); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7583 LP64_ONLY( lea(rcx, pst_counter_addr) ); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7584 LP64_ONLY( incrementl(Address(rcx, 0)) ); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7585 #endif //PRODUCT |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7586 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7587 // We will consult the secondary-super array. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7588 movptr(rdi, secondary_supers_addr); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7589 // Load the array length. (Positive movl does right thing on LP64.) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7590 movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7591 // Skip to start of data. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7592 addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7593 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7594 // Scan RCX words at [RDI] for an occurrence of RAX. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7595 // Set NZ/Z based on last compare. |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7596 // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7597 // not change flags (only scas instruction which is repeated sets flags). |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7598 // Set Z = 0 (not equal) before 'repne' to indicate that class was not found. |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7599 #ifdef _LP64 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7600 // This part is tricky, as values in supers array could be 32 or 64 bit wide |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7601 // and we store values in objArrays always encoded, thus we need to encode |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7602 // the value of rax before repne. Note that rax is dead after the repne. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7603 if (UseCompressedOops) { |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7604 encode_heap_oop_not_null(rax); // Changes flags. |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7605 // The superclass is never null; it would be a basic system error if a null |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7606 // pointer were to sneak in here. Note that we have already loaded the |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7607 // Klass::super_check_offset from the super_klass in the fast path, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7608 // so if there is a null in that register, we are already in the afterlife. |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7609 testl(rax,rax); // Set Z = 0 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7610 repne_scanl(); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7611 } else |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7612 #endif // _LP64 |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7613 { |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7614 testptr(rax,rax); // Set Z = 0 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7615 repne_scan(); |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
7616 } |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7617 // Unspill the temp. registers: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7618 if (pushed_rdi) pop(rdi); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7619 if (pushed_rcx) pop(rcx); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7620 if (pushed_rax) pop(rax); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7621 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7622 if (set_cond_codes) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7623 // Special hack for the AD files: rdi is guaranteed non-zero. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7624 assert(!pushed_rdi, "rdi must be left non-NULL"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7625 // Also, the condition codes are properly set Z/NZ on succeed/failure. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7626 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7627 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7628 if (L_failure == &L_fallthrough) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7629 jccb(Assembler::notEqual, *L_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7630 else jcc(Assembler::notEqual, *L_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7631 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7632 // Success. Cache the super we found and proceed in triumph. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7633 movptr(super_cache_addr, super_klass); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7634 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7635 if (L_success != &L_fallthrough) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7636 jmp(*L_success); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7637 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7638 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7639 #undef IS_A_TEMP |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7640 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7641 bind(L_fallthrough); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7642 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7643 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
643
diff
changeset
|
7644 |
304 | 7645 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { |
7646 ucomisd(dst, as_Address(src)); | |
7647 } | |
7648 | |
7649 void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { | |
7650 ucomiss(dst, as_Address(src)); | |
7651 } | |
7652 | |
7653 void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src) { | |
7654 if (reachable(src)) { | |
7655 xorpd(dst, as_Address(src)); | |
7656 } else { | |
7657 lea(rscratch1, src); | |
7658 xorpd(dst, Address(rscratch1, 0)); | |
7659 } | |
7660 } | |
7661 | |
7662 void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) { | |
7663 if (reachable(src)) { | |
7664 xorps(dst, as_Address(src)); | |
7665 } else { | |
7666 lea(rscratch1, src); | |
7667 xorps(dst, Address(rscratch1, 0)); | |
7668 } | |
7669 } | |
7670 | |
0 | 7671 void MacroAssembler::verify_oop(Register reg, const char* s) { |
7672 if (!VerifyOops) return; | |
304 | 7673 |
0 | 7674 // Pass register number to verify_oop_subroutine |
7675 char* b = new char[strlen(s) + 50]; | |
7676 sprintf(b, "verify_oop: %s: %s", reg->name(), s); | |
1583 | 7677 #ifdef _LP64 |
7678 push(rscratch1); // save r10, trashed by movptr() | |
7679 #endif | |
304 | 7680 push(rax); // save rax, |
7681 push(reg); // pass register argument | |
0 | 7682 ExternalAddress buffer((address) b); |
304 | 7683 // avoid using pushptr, as it modifies scratch registers |
7684 // and our contract is not to modify anything | |
7685 movptr(rax, buffer.addr()); | |
7686 push(rax); | |
0 | 7687 // call indirectly to solve generation ordering problem |
7688 movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); | |
7689 call(rax); | |
1583 | 7690 // Caller pops the arguments (oop, message) and restores rax, r10 |
0 | 7691 } |
7692 | |
7693 | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7694 RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7695 Register tmp, |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7696 int offset) { |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7697 intptr_t value = *delayed_value_addr; |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7698 if (value != 0) |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7699 return RegisterOrConstant(value + offset); |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7700 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7701 // load indirectly to solve generation ordering problem |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7702 movptr(tmp, ExternalAddress((address) delayed_value_addr)); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7703 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7704 #ifdef ASSERT |
1793
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7705 { Label L; |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7706 testptr(tmp, tmp); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7707 if (WizardMode) { |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7708 jcc(Assembler::notZero, L); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7709 char* buf = new char[40]; |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7710 sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7711 stop(buf); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7712 } else { |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7713 jccb(Assembler::notZero, L); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7714 hlt(); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7715 } |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7716 bind(L); |
d257356e35f0
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
1763
diff
changeset
|
7717 } |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7718 #endif |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7719 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7720 if (offset != 0) |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7721 addptr(tmp, offset); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7722 |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
647
diff
changeset
|
7723 return RegisterOrConstant(tmp); |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7724 } |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7725 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
606
diff
changeset
|
7726 |
710 | 7727 // registers on entry: |
7728 // - rax ('check' register): required MethodType | |
7729 // - rcx: method handle | |
7730 // - rdx, rsi, or ?: killable temp | |
7731 void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, | |
7732 Register temp_reg, | |
7733 Label& wrong_method_type) { | |
1846 | 7734 Address type_addr(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)); |
710 | 7735 // compare method type against that of the receiver |
1846 | 7736 if (UseCompressedOops) { |
7737 load_heap_oop(temp_reg, type_addr); | |
7738 cmpptr(mtype_reg, temp_reg); | |
7739 } else { | |
7740 cmpptr(mtype_reg, type_addr); | |
7741 } | |
710 | 7742 jcc(Assembler::notEqual, wrong_method_type); |
7743 } | |
7744 | |
7745 | |
7746 // A method handle has a "vmslots" field which gives the size of its | |
7747 // argument list in JVM stack slots. This field is either located directly | |
7748 // in every method handle, or else is indirectly accessed through the | |
7749 // method handle's MethodType. This macro hides the distinction. | |
7750 void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, | |
7751 Register temp_reg) { | |
1503 | 7752 assert_different_registers(vmslots_reg, mh_reg, temp_reg); |
710 | 7753 // load mh.type.form.vmslots |
7754 if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { | |
7755 // hoist vmslots into every mh to avoid dependent load chain | |
7756 movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg))); | |
7757 } else { | |
7758 Register temp2_reg = vmslots_reg; | |
1846 | 7759 load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); |
7760 load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg))); | |
710 | 7761 movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); |
7762 } | |
7763 } | |
7764 | |
7765 | |
7766 // registers on entry: | |
7767 // - rcx: method handle | |
7768 // - rdx: killable temp (interpreted only) | |
7769 // - rax: killable temp (compiled only) | |
7770 void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { | |
7771 assert(mh_reg == rcx, "caller must put MH object in rcx"); | |
7772 assert_different_registers(mh_reg, temp_reg); | |
7773 | |
7774 // pick out the interpreted side of the handler | |
1846 | 7775 // NOTE: vmentry is not an oop! |
710 | 7776 movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg))); |
7777 | |
7778 // off we go... | |
7779 jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); | |
7780 | |
7781 // for the various stubs which take control at this point, | |
7782 // see MethodHandles::generate_method_handle_stub | |
7783 } | |
7784 | |
7785 | |
7786 Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, | |
7787 int extra_slot_offset) { | |
7788 // cf. TemplateTable::prepare_invoke(), if (load_receiver). | |
1506 | 7789 int stackElementSize = Interpreter::stackElementSize; |
710 | 7790 int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); |
7791 #ifdef ASSERT | |
7792 int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); | |
7793 assert(offset1 - offset == stackElementSize, "correct arithmetic"); | |
7794 #endif | |
7795 Register scale_reg = noreg; | |
7796 Address::ScaleFactor scale_factor = Address::no_scale; | |
7797 if (arg_slot.is_constant()) { | |
7798 offset += arg_slot.as_constant() * stackElementSize; | |
7799 } else { | |
7800 scale_reg = arg_slot.as_register(); | |
7801 scale_factor = Address::times(stackElementSize); | |
7802 } | |
7803 offset += wordSize; // return PC is on stack | |
7804 return Address(rsp, scale_reg, scale_factor, offset); | |
7805 } | |
7806 | |
7807 | |
0 | 7808 void MacroAssembler::verify_oop_addr(Address addr, const char* s) { |
7809 if (!VerifyOops) return; | |
304 | 7810 |
0 | 7811 // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); |
7812 // Pass register number to verify_oop_subroutine | |
7813 char* b = new char[strlen(s) + 50]; | |
7814 sprintf(b, "verify_oop_addr: %s", s); | |
304 | 7815 |
1583 | 7816 #ifdef _LP64 |
7817 push(rscratch1); // save r10, trashed by movptr() | |
7818 #endif | |
304 | 7819 push(rax); // save rax, |
0 | 7820 // addr may contain rsp so we will have to adjust it based on the push |
7821 // we just did | |
304 | 7822 // NOTE: 64bit seemed to have had a bug in that it did movq(addr, rax); which |
7823 // stores rax into addr which is backwards of what was intended. | |
0 | 7824 if (addr.uses(rsp)) { |
304 | 7825 lea(rax, addr); |
7826 pushptr(Address(rax, BytesPerWord)); | |
0 | 7827 } else { |
304 | 7828 pushptr(addr); |
7829 } | |
7830 | |
0 | 7831 ExternalAddress buffer((address) b); |
7832 // pass msg argument | |
304 | 7833 // avoid using pushptr, as it modifies scratch registers |
7834 // and our contract is not to modify anything | |
7835 movptr(rax, buffer.addr()); | |
7836 push(rax); | |
7837 | |
0 | 7838 // call indirectly to solve generation ordering problem |
7839 movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); | |
7840 call(rax); | |
1583 | 7841 // Caller pops the arguments (addr, message) and restores rax, r10. |
0 | 7842 } |
7843 | |
304 | 7844 void MacroAssembler::verify_tlab() { |
7845 #ifdef ASSERT | |
7846 if (UseTLAB && VerifyOops) { | |
7847 Label next, ok; | |
7848 Register t1 = rsi; | |
7849 Register thread_reg = NOT_LP64(rbx) LP64_ONLY(r15_thread); | |
7850 | |
7851 push(t1); | |
7852 NOT_LP64(push(thread_reg)); | |
7853 NOT_LP64(get_thread(thread_reg)); | |
7854 | |
7855 movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); | |
7856 cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); | |
7857 jcc(Assembler::aboveEqual, next); | |
7858 stop("assert(top >= start)"); | |
7859 should_not_reach_here(); | |
7860 | |
7861 bind(next); | |
7862 movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); | |
7863 cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); | |
7864 jcc(Assembler::aboveEqual, ok); | |
7865 stop("assert(top <= end)"); | |
7866 should_not_reach_here(); | |
7867 | |
7868 bind(ok); | |
7869 NOT_LP64(pop(thread_reg)); | |
7870 pop(t1); | |
7871 } | |
7872 #endif | |
7873 } | |
0 | 7874 |
7875 class ControlWord { | |
7876 public: | |
7877 int32_t _value; | |
7878 | |
7879 int rounding_control() const { return (_value >> 10) & 3 ; } | |
7880 int precision_control() const { return (_value >> 8) & 3 ; } | |
7881 bool precision() const { return ((_value >> 5) & 1) != 0; } | |
7882 bool underflow() const { return ((_value >> 4) & 1) != 0; } | |
7883 bool overflow() const { return ((_value >> 3) & 1) != 0; } | |
7884 bool zero_divide() const { return ((_value >> 2) & 1) != 0; } | |
7885 bool denormalized() const { return ((_value >> 1) & 1) != 0; } | |
7886 bool invalid() const { return ((_value >> 0) & 1) != 0; } | |
7887 | |
7888 void print() const { | |
7889 // rounding control | |
7890 const char* rc; | |
7891 switch (rounding_control()) { | |
7892 case 0: rc = "round near"; break; | |
7893 case 1: rc = "round down"; break; | |
7894 case 2: rc = "round up "; break; | |
7895 case 3: rc = "chop "; break; | |
7896 }; | |
7897 // precision control | |
7898 const char* pc; | |
7899 switch (precision_control()) { | |
7900 case 0: pc = "24 bits "; break; | |
7901 case 1: pc = "reserved"; break; | |
7902 case 2: pc = "53 bits "; break; | |
7903 case 3: pc = "64 bits "; break; | |
7904 }; | |
7905 // flags | |
7906 char f[9]; | |
7907 f[0] = ' '; | |
7908 f[1] = ' '; | |
7909 f[2] = (precision ()) ? 'P' : 'p'; | |
7910 f[3] = (underflow ()) ? 'U' : 'u'; | |
7911 f[4] = (overflow ()) ? 'O' : 'o'; | |
7912 f[5] = (zero_divide ()) ? 'Z' : 'z'; | |
7913 f[6] = (denormalized()) ? 'D' : 'd'; | |
7914 f[7] = (invalid ()) ? 'I' : 'i'; | |
7915 f[8] = '\x0'; | |
7916 // output | |
7917 printf("%04x masks = %s, %s, %s", _value & 0xFFFF, f, rc, pc); | |
7918 } | |
7919 | |
7920 }; | |
7921 | |
7922 class StatusWord { | |
7923 public: | |
7924 int32_t _value; | |
7925 | |
7926 bool busy() const { return ((_value >> 15) & 1) != 0; } | |
7927 bool C3() const { return ((_value >> 14) & 1) != 0; } | |
7928 bool C2() const { return ((_value >> 10) & 1) != 0; } | |
7929 bool C1() const { return ((_value >> 9) & 1) != 0; } | |
7930 bool C0() const { return ((_value >> 8) & 1) != 0; } | |
7931 int top() const { return (_value >> 11) & 7 ; } | |
7932 bool error_status() const { return ((_value >> 7) & 1) != 0; } | |
7933 bool stack_fault() const { return ((_value >> 6) & 1) != 0; } | |
7934 bool precision() const { return ((_value >> 5) & 1) != 0; } | |
7935 bool underflow() const { return ((_value >> 4) & 1) != 0; } | |
7936 bool overflow() const { return ((_value >> 3) & 1) != 0; } | |
7937 bool zero_divide() const { return ((_value >> 2) & 1) != 0; } | |
7938 bool denormalized() const { return ((_value >> 1) & 1) != 0; } | |
7939 bool invalid() const { return ((_value >> 0) & 1) != 0; } | |
7940 | |
7941 void print() const { | |
7942 // condition codes | |
7943 char c[5]; | |
7944 c[0] = (C3()) ? '3' : '-'; | |
7945 c[1] = (C2()) ? '2' : '-'; | |
7946 c[2] = (C1()) ? '1' : '-'; | |
7947 c[3] = (C0()) ? '0' : '-'; | |
7948 c[4] = '\x0'; | |
7949 // flags | |
7950 char f[9]; | |
7951 f[0] = (error_status()) ? 'E' : '-'; | |
7952 f[1] = (stack_fault ()) ? 'S' : '-'; | |
7953 f[2] = (precision ()) ? 'P' : '-'; | |
7954 f[3] = (underflow ()) ? 'U' : '-'; | |
7955 f[4] = (overflow ()) ? 'O' : '-'; | |
7956 f[5] = (zero_divide ()) ? 'Z' : '-'; | |
7957 f[6] = (denormalized()) ? 'D' : '-'; | |
7958 f[7] = (invalid ()) ? 'I' : '-'; | |
7959 f[8] = '\x0'; | |
7960 // output | |
7961 printf("%04x flags = %s, cc = %s, top = %d", _value & 0xFFFF, f, c, top()); | |
7962 } | |
7963 | |
7964 }; | |
7965 | |
7966 class TagWord { | |
7967 public: | |
7968 int32_t _value; | |
7969 | |
7970 int tag_at(int i) const { return (_value >> (i*2)) & 3; } | |
7971 | |
7972 void print() const { | |
7973 printf("%04x", _value & 0xFFFF); | |
7974 } | |
7975 | |
7976 }; | |
7977 | |
7978 class FPU_Register { | |
7979 public: | |
7980 int32_t _m0; | |
7981 int32_t _m1; | |
7982 int16_t _ex; | |
7983 | |
7984 bool is_indefinite() const { | |
7985 return _ex == -1 && _m1 == (int32_t)0xC0000000 && _m0 == 0; | |
7986 } | |
7987 | |
7988 void print() const { | |
7989 char sign = (_ex < 0) ? '-' : '+'; | |
7990 const char* kind = (_ex == 0x7FFF || _ex == (int16_t)-1) ? "NaN" : " "; | |
7991 printf("%c%04hx.%08x%08x %s", sign, _ex, _m1, _m0, kind); | |
7992 }; | |
7993 | |
7994 }; | |
7995 | |
7996 class FPU_State { | |
7997 public: | |
7998 enum { | |
7999 register_size = 10, | |
8000 number_of_registers = 8, | |
8001 register_mask = 7 | |
8002 }; | |
8003 | |
8004 ControlWord _control_word; | |
8005 StatusWord _status_word; | |
8006 TagWord _tag_word; | |
8007 int32_t _error_offset; | |
8008 int32_t _error_selector; | |
8009 int32_t _data_offset; | |
8010 int32_t _data_selector; | |
8011 int8_t _register[register_size * number_of_registers]; | |
8012 | |
8013 int tag_for_st(int i) const { return _tag_word.tag_at((_status_word.top() + i) & register_mask); } | |
8014 FPU_Register* st(int i) const { return (FPU_Register*)&_register[register_size * i]; } | |
8015 | |
8016 const char* tag_as_string(int tag) const { | |
8017 switch (tag) { | |
8018 case 0: return "valid"; | |
8019 case 1: return "zero"; | |
8020 case 2: return "special"; | |
8021 case 3: return "empty"; | |
8022 } | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1369
diff
changeset
|
8023 ShouldNotReachHere(); |
0 | 8024 return NULL; |
8025 } | |
8026 | |
8027 void print() const { | |
8028 // print computation registers | |
8029 { int t = _status_word.top(); | |
8030 for (int i = 0; i < number_of_registers; i++) { | |
8031 int j = (i - t) & register_mask; | |
8032 printf("%c r%d = ST%d = ", (j == 0 ? '*' : ' '), i, j); | |
8033 st(j)->print(); | |
8034 printf(" %s\n", tag_as_string(_tag_word.tag_at(i))); | |
8035 } | |
8036 } | |
8037 printf("\n"); | |
8038 // print control registers | |
8039 printf("ctrl = "); _control_word.print(); printf("\n"); | |
8040 printf("stat = "); _status_word .print(); printf("\n"); | |
8041 printf("tags = "); _tag_word .print(); printf("\n"); | |
8042 } | |
8043 | |
8044 }; | |
8045 | |
8046 class Flag_Register { | |
8047 public: | |
8048 int32_t _value; | |
8049 | |
8050 bool overflow() const { return ((_value >> 11) & 1) != 0; } | |
8051 bool direction() const { return ((_value >> 10) & 1) != 0; } | |
8052 bool sign() const { return ((_value >> 7) & 1) != 0; } | |
8053 bool zero() const { return ((_value >> 6) & 1) != 0; } | |
8054 bool auxiliary_carry() const { return ((_value >> 4) & 1) != 0; } | |
8055 bool parity() const { return ((_value >> 2) & 1) != 0; } | |
8056 bool carry() const { return ((_value >> 0) & 1) != 0; } | |
8057 | |
8058 void print() const { | |
8059 // flags | |
8060 char f[8]; | |
8061 f[0] = (overflow ()) ? 'O' : '-'; | |
8062 f[1] = (direction ()) ? 'D' : '-'; | |
8063 f[2] = (sign ()) ? 'S' : '-'; | |
8064 f[3] = (zero ()) ? 'Z' : '-'; | |
8065 f[4] = (auxiliary_carry()) ? 'A' : '-'; | |
8066 f[5] = (parity ()) ? 'P' : '-'; | |
8067 f[6] = (carry ()) ? 'C' : '-'; | |
8068 f[7] = '\x0'; | |
8069 // output | |
8070 printf("%08x flags = %s", _value, f); | |
8071 } | |
8072 | |
8073 }; | |
8074 | |
8075 class IU_Register { | |
8076 public: | |
8077 int32_t _value; | |
8078 | |
8079 void print() const { | |
8080 printf("%08x %11d", _value, _value); | |
8081 } | |
8082 | |
8083 }; | |
8084 | |
8085 class IU_State { | |
8086 public: | |
8087 Flag_Register _eflags; | |
8088 IU_Register _rdi; | |
8089 IU_Register _rsi; | |
8090 IU_Register _rbp; | |
8091 IU_Register _rsp; | |
8092 IU_Register _rbx; | |
8093 IU_Register _rdx; | |
8094 IU_Register _rcx; | |
8095 IU_Register _rax; | |
8096 | |
8097 void print() const { | |
8098 // computation registers | |
8099 printf("rax, = "); _rax.print(); printf("\n"); | |
8100 printf("rbx, = "); _rbx.print(); printf("\n"); | |
8101 printf("rcx = "); _rcx.print(); printf("\n"); | |
8102 printf("rdx = "); _rdx.print(); printf("\n"); | |
8103 printf("rdi = "); _rdi.print(); printf("\n"); | |
8104 printf("rsi = "); _rsi.print(); printf("\n"); | |
8105 printf("rbp, = "); _rbp.print(); printf("\n"); | |
8106 printf("rsp = "); _rsp.print(); printf("\n"); | |
8107 printf("\n"); | |
8108 // control registers | |
8109 printf("flgs = "); _eflags.print(); printf("\n"); | |
8110 } | |
8111 }; | |
8112 | |
8113 | |
8114 class CPU_State { | |
8115 public: | |
8116 FPU_State _fpu_state; | |
8117 IU_State _iu_state; | |
8118 | |
8119 void print() const { | |
8120 printf("--------------------------------------------------\n"); | |
8121 _iu_state .print(); | |
8122 printf("\n"); | |
8123 _fpu_state.print(); | |
8124 printf("--------------------------------------------------\n"); | |
8125 } | |
8126 | |
8127 }; | |
8128 | |
8129 | |
8130 static void _print_CPU_state(CPU_State* state) { | |
8131 state->print(); | |
8132 }; | |
8133 | |
8134 | |
8135 void MacroAssembler::print_CPU_state() { | |
8136 push_CPU_state(); | |
304 | 8137 push(rsp); // pass CPU state |
0 | 8138 call(RuntimeAddress(CAST_FROM_FN_PTR(address, _print_CPU_state))); |
304 | 8139 addptr(rsp, wordSize); // discard argument |
0 | 8140 pop_CPU_state(); |
8141 } | |
8142 | |
8143 | |
8144 static bool _verify_FPU(int stack_depth, char* s, CPU_State* state) { | |
8145 static int counter = 0; | |
8146 FPU_State* fs = &state->_fpu_state; | |
8147 counter++; | |
8148 // For leaf calls, only verify that the top few elements remain empty. | |
8149 // We only need 1 empty at the top for C2 code. | |
8150 if( stack_depth < 0 ) { | |
8151 if( fs->tag_for_st(7) != 3 ) { | |
8152 printf("FPR7 not empty\n"); | |
8153 state->print(); | |
8154 assert(false, "error"); | |
8155 return false; | |
8156 } | |
8157 return true; // All other stack states do not matter | |
8158 } | |
8159 | |
8160 assert((fs->_control_word._value & 0xffff) == StubRoutines::_fpu_cntrl_wrd_std, | |
8161 "bad FPU control word"); | |
8162 | |
8163 // compute stack depth | |
8164 int i = 0; | |
8165 while (i < FPU_State::number_of_registers && fs->tag_for_st(i) < 3) i++; | |
8166 int d = i; | |
8167 while (i < FPU_State::number_of_registers && fs->tag_for_st(i) == 3) i++; | |
8168 // verify findings | |
8169 if (i != FPU_State::number_of_registers) { | |
8170 // stack not contiguous | |
8171 printf("%s: stack not contiguous at ST%d\n", s, i); | |
8172 state->print(); | |
8173 assert(false, "error"); | |
8174 return false; | |
8175 } | |
8176 // check if computed stack depth corresponds to expected stack depth | |
8177 if (stack_depth < 0) { | |
8178 // expected stack depth is -stack_depth or less | |
8179 if (d > -stack_depth) { | |
8180 // too many elements on the stack | |
8181 printf("%s: <= %d stack elements expected but found %d\n", s, -stack_depth, d); | |
8182 state->print(); | |
8183 assert(false, "error"); | |
8184 return false; | |
8185 } | |
8186 } else { | |
8187 // expected stack depth is stack_depth | |
8188 if (d != stack_depth) { | |
8189 // wrong stack depth | |
8190 printf("%s: %d stack elements expected but found %d\n", s, stack_depth, d); | |
8191 state->print(); | |
8192 assert(false, "error"); | |
8193 return false; | |
8194 } | |
8195 } | |
8196 // everything is cool | |
8197 return true; | |
8198 } | |
8199 | |
8200 | |
8201 void MacroAssembler::verify_FPU(int stack_depth, const char* s) { | |
8202 if (!VerifyFPU) return; | |
8203 push_CPU_state(); | |
304 | 8204 push(rsp); // pass CPU state |
0 | 8205 ExternalAddress msg((address) s); |
8206 // pass message string s | |
8207 pushptr(msg.addr()); | |
304 | 8208 push(stack_depth); // pass stack depth |
0 | 8209 call(RuntimeAddress(CAST_FROM_FN_PTR(address, _verify_FPU))); |
304 | 8210 addptr(rsp, 3 * wordSize); // discard arguments |
0 | 8211 // check for error |
8212 { Label L; | |
8213 testl(rax, rax); | |
8214 jcc(Assembler::notZero, L); | |
8215 int3(); // break if error condition | |
8216 bind(L); | |
8217 } | |
8218 pop_CPU_state(); | |
8219 } | |
8220 | |
304 | 8221 void MacroAssembler::load_klass(Register dst, Register src) { |
8222 #ifdef _LP64 | |
8223 if (UseCompressedOops) { | |
8224 movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); | |
8225 decode_heap_oop_not_null(dst); | |
8226 } else | |
8227 #endif | |
8228 movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); | |
8229 } | |
8230 | |
8231 void MacroAssembler::load_prototype_header(Register dst, Register src) { | |
8232 #ifdef _LP64 | |
8233 if (UseCompressedOops) { | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8234 assert (Universe::heap() != NULL, "java heap should be initialized"); |
304 | 8235 movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8236 if (Universe::narrow_oop_shift() != 0) { |
1571
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8237 assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8238 if (LogMinObjAlignmentInBytes == Address::times_8) { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8239 movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8240 } else { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8241 // OK to use shift since we don't need to preserve flags. |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8242 shlq(dst, LogMinObjAlignmentInBytes); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8243 movq(dst, Address(r12_heapbase, dst, Address::times_1, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8244 } |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8245 } else { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8246 movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8247 } |
304 | 8248 } else |
8249 #endif | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8250 { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8251 movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8252 movptr(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8253 } |
304 | 8254 } |
8255 | |
8256 void MacroAssembler::store_klass(Register dst, Register src) { | |
8257 #ifdef _LP64 | |
8258 if (UseCompressedOops) { | |
8259 encode_heap_oop_not_null(src); | |
8260 movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); | |
8261 } else | |
8262 #endif | |
8263 movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); | |
8264 } | |
8265 | |
1846 | 8266 void MacroAssembler::load_heap_oop(Register dst, Address src) { |
8267 #ifdef _LP64 | |
8268 if (UseCompressedOops) { | |
8269 movl(dst, src); | |
8270 decode_heap_oop(dst); | |
8271 } else | |
8272 #endif | |
8273 movptr(dst, src); | |
8274 } | |
8275 | |
8276 void MacroAssembler::store_heap_oop(Address dst, Register src) { | |
8277 #ifdef _LP64 | |
8278 if (UseCompressedOops) { | |
8279 assert(!dst.uses(src), "not enough registers"); | |
8280 encode_heap_oop(src); | |
8281 movl(dst, src); | |
8282 } else | |
8283 #endif | |
8284 movptr(dst, src); | |
8285 } | |
8286 | |
8287 // Used for storing NULLs. | |
8288 void MacroAssembler::store_heap_oop_null(Address dst) { | |
8289 #ifdef _LP64 | |
8290 if (UseCompressedOops) { | |
8291 movl(dst, (int32_t)NULL_WORD); | |
8292 } else { | |
8293 movslq(dst, (int32_t)NULL_WORD); | |
8294 } | |
8295 #else | |
8296 movl(dst, (int32_t)NULL_WORD); | |
8297 #endif | |
8298 } | |
8299 | |
304 | 8300 #ifdef _LP64 |
8301 void MacroAssembler::store_klass_gap(Register dst, Register src) { | |
8302 if (UseCompressedOops) { | |
8303 // Store to klass gap in destination | |
8304 movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); | |
8305 } | |
8306 } | |
8307 | |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8308 #ifdef ASSERT |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8309 void MacroAssembler::verify_heapbase(const char* msg) { |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8310 assert (UseCompressedOops, "should be compressed"); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8311 assert (Universe::heap() != NULL, "java heap should be initialized"); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8312 if (CheckCompressedOops) { |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8313 Label ok; |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8314 push(rscratch1); // cmpptr trashes rscratch1 |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8315 cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8316 jcc(Assembler::equal, ok); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8317 stop(msg); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8318 bind(ok); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8319 pop(rscratch1); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8320 } |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8321 } |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8322 #endif |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8323 |
304 | 8324 // Algorithm must match oop.inline.hpp encode_heap_oop. |
8325 void MacroAssembler::encode_heap_oop(Register r) { | |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8326 #ifdef ASSERT |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8327 verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8328 #endif |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8329 verify_oop(r, "broken oop in encode_heap_oop"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8330 if (Universe::narrow_oop_base() == NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8331 if (Universe::narrow_oop_shift() != 0) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8332 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8333 shrq(r, LogMinObjAlignmentInBytes); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8334 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8335 return; |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8336 } |
304 | 8337 testq(r, r); |
8338 cmovq(Assembler::equal, r, r12_heapbase); | |
8339 subq(r, r12_heapbase); | |
8340 shrq(r, LogMinObjAlignmentInBytes); | |
8341 } | |
8342 | |
8343 void MacroAssembler::encode_heap_oop_not_null(Register r) { | |
0 | 8344 #ifdef ASSERT |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8345 verify_heapbase("MacroAssembler::encode_heap_oop_not_null: heap base corrupted?"); |
304 | 8346 if (CheckCompressedOops) { |
0 | 8347 Label ok; |
304 | 8348 testq(r, r); |
8349 jcc(Assembler::notEqual, ok); | |
8350 stop("null oop passed to encode_heap_oop_not_null"); | |
0 | 8351 bind(ok); |
304 | 8352 } |
8353 #endif | |
8354 verify_oop(r, "broken oop in encode_heap_oop_not_null"); | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8355 if (Universe::narrow_oop_base() != NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8356 subq(r, r12_heapbase); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8357 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8358 if (Universe::narrow_oop_shift() != 0) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8359 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8360 shrq(r, LogMinObjAlignmentInBytes); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8361 } |
304 | 8362 } |
8363 | |
8364 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { | |
8365 #ifdef ASSERT | |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8366 verify_heapbase("MacroAssembler::encode_heap_oop_not_null2: heap base corrupted?"); |
304 | 8367 if (CheckCompressedOops) { |
8368 Label ok; | |
8369 testq(src, src); | |
8370 jcc(Assembler::notEqual, ok); | |
8371 stop("null oop passed to encode_heap_oop_not_null2"); | |
8372 bind(ok); | |
0 | 8373 } |
8374 #endif | |
304 | 8375 verify_oop(src, "broken oop in encode_heap_oop_not_null2"); |
8376 if (dst != src) { | |
8377 movq(dst, src); | |
8378 } | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8379 if (Universe::narrow_oop_base() != NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8380 subq(dst, r12_heapbase); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8381 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8382 if (Universe::narrow_oop_shift() != 0) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8383 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8384 shrq(dst, LogMinObjAlignmentInBytes); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8385 } |
304 | 8386 } |
8387 | |
8388 void MacroAssembler::decode_heap_oop(Register r) { | |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8389 #ifdef ASSERT |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8390 verify_heapbase("MacroAssembler::decode_heap_oop: heap base corrupted?"); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8391 #endif |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8392 if (Universe::narrow_oop_base() == NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8393 if (Universe::narrow_oop_shift() != 0) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8394 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8395 shlq(r, LogMinObjAlignmentInBytes); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8396 } |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8397 } else { |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8398 Label done; |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8399 shlq(r, LogMinObjAlignmentInBytes); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8400 jccb(Assembler::equal, done); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8401 addq(r, r12_heapbase); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8402 bind(done); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8403 } |
304 | 8404 verify_oop(r, "broken oop in decode_heap_oop"); |
8405 } | |
8406 | |
8407 void MacroAssembler::decode_heap_oop_not_null(Register r) { | |
1571
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8408 // Note: it will change flags |
304 | 8409 assert (UseCompressedOops, "should only be used for compressed headers"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8410 assert (Universe::heap() != NULL, "java heap should be initialized"); |
304 | 8411 // Cannot assert, unverified entry point counts instructions (see .ad file) |
8412 // vtableStubs also counts instructions in pd_code_size_limit. | |
8413 // Also do not verify_oop as this is called by verify_oop. | |
898
60fea60a6db5
6864914: SPECjvm2008 produces invalid result with zero based Compressed Oops
kvn
parents:
845
diff
changeset
|
8414 if (Universe::narrow_oop_shift() != 0) { |
1571
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8415 assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8416 shlq(r, LogMinObjAlignmentInBytes); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8417 if (Universe::narrow_oop_base() != NULL) { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8418 addq(r, r12_heapbase); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8419 } |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8420 } else { |
898
60fea60a6db5
6864914: SPECjvm2008 produces invalid result with zero based Compressed Oops
kvn
parents:
845
diff
changeset
|
8421 assert (Universe::narrow_oop_base() == NULL, "sanity"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8422 } |
304 | 8423 } |
8424 | |
8425 void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { | |
1571
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8426 // Note: it will change flags |
304 | 8427 assert (UseCompressedOops, "should only be used for compressed headers"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8428 assert (Universe::heap() != NULL, "java heap should be initialized"); |
304 | 8429 // Cannot assert, unverified entry point counts instructions (see .ad file) |
8430 // vtableStubs also counts instructions in pd_code_size_limit. | |
8431 // Also do not verify_oop as this is called by verify_oop. | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8432 if (Universe::narrow_oop_shift() != 0) { |
1571
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8433 assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8434 if (LogMinObjAlignmentInBytes == Address::times_8) { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8435 leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8436 } else { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8437 if (dst != src) { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8438 movq(dst, src); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8439 } |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8440 shlq(dst, LogMinObjAlignmentInBytes); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8441 if (Universe::narrow_oop_base() != NULL) { |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8442 addq(dst, r12_heapbase); |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8443 } |
2d127394260e
6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents:
1513
diff
changeset
|
8444 } |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8445 } else { |
898
60fea60a6db5
6864914: SPECjvm2008 produces invalid result with zero based Compressed Oops
kvn
parents:
845
diff
changeset
|
8446 assert (Universe::narrow_oop_base() == NULL, "sanity"); |
1684
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8447 if (dst != src) { |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8448 movq(dst, src); |
66c5dadb4d61
6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path()
kvn
parents:
1583
diff
changeset
|
8449 } |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8450 } |
304 | 8451 } |
8452 | |
8453 void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8454 assert (UseCompressedOops, "should only be used for compressed headers"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8455 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8456 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8457 int oop_index = oop_recorder()->find_index(obj); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8458 RelocationHolder rspec = oop_Relocation::spec(oop_index); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8459 mov_narrow_oop(dst, oop_index, rspec); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8460 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8461 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8462 void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8463 assert (UseCompressedOops, "should only be used for compressed headers"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8464 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8465 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); |
304 | 8466 int oop_index = oop_recorder()->find_index(obj); |
8467 RelocationHolder rspec = oop_Relocation::spec(oop_index); | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8468 mov_narrow_oop(dst, oop_index, rspec); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8469 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8470 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8471 void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8472 assert (UseCompressedOops, "should only be used for compressed headers"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8473 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8474 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8475 int oop_index = oop_recorder()->find_index(obj); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8476 RelocationHolder rspec = oop_Relocation::spec(oop_index); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8477 Assembler::cmp_narrow_oop(dst, oop_index, rspec); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8478 } |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8479 |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8480 void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8481 assert (UseCompressedOops, "should only be used for compressed headers"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8482 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8483 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8484 int oop_index = oop_recorder()->find_index(obj); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8485 RelocationHolder rspec = oop_Relocation::spec(oop_index); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8486 Assembler::cmp_narrow_oop(dst, oop_index, rspec); |
304 | 8487 } |
8488 | |
8489 void MacroAssembler::reinit_heapbase() { | |
8490 if (UseCompressedOops) { | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
624
diff
changeset
|
8491 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
304 | 8492 } |
8493 } | |
8494 #endif // _LP64 | |
0 | 8495 |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8496 // IndexOf substring. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8497 void MacroAssembler::string_indexof(Register str1, Register str2, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8498 Register cnt1, Register cnt2, Register result, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8499 XMMRegister vec, Register tmp) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8500 assert(UseSSE42Intrinsics, "SSE4.2 is required"); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8501 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8502 Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8503 SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8504 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8505 push(str1); // string addr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8506 push(str2); // substr addr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8507 push(cnt2); // substr count |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8508 jmpb(PREP_FOR_SCAN); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8509 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8510 // Substr count saved at sp |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8511 // Substr saved at sp+1*wordSize |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8512 // String saved at sp+2*wordSize |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8513 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8514 // Reload substr for rescan |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8515 bind(RELOAD_SUBSTR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8516 movl(cnt2, Address(rsp, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8517 movptr(str2, Address(rsp, wordSize)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8518 // We came here after the beginninig of the substring was |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8519 // matched but the rest of it was not so we need to search |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8520 // again. Start from the next element after the previous match. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8521 subptr(str1, result); // Restore counter |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8522 shrl(str1, 1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8523 addl(cnt1, str1); |
1302
2484f4d6a54e
6935535: String.indexOf() returns incorrect result on x86 with SSE4.2
kvn
parents:
1108
diff
changeset
|
8524 decrementl(cnt1); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8525 lea(str1, Address(result, 2)); // Reload string |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8526 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8527 // Load substr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8528 bind(PREP_FOR_SCAN); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8529 movdqu(vec, Address(str2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8530 addl(cnt1, 8); // prime the loop |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8531 subptr(str1, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8532 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8533 // Scan string for substr in 16-byte vectors |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8534 bind(SCAN_TO_SUBSTR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8535 subl(cnt1, 8); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8536 addptr(str1, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8537 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8538 // pcmpestri |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8539 // inputs: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8540 // xmm - substring |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8541 // rax - substring length (elements count) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8542 // mem - scaned string |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8543 // rdx - string length (elements count) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8544 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8545 // outputs: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8546 // rcx - matched index in string |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8547 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8548 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8549 pcmpestri(vec, Address(str1, 0), 0x0d); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8550 jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8551 jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8552 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8553 // Fallthrough: found a potential substr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8554 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8555 // Make sure string is still long enough |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8556 subl(cnt1, tmp); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8557 cmpl(cnt1, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8558 jccb(Assembler::negative, RET_NOT_FOUND); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8559 // Compute start addr of substr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8560 lea(str1, Address(str1, tmp, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8561 movptr(result, str1); // save |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8562 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8563 // Compare potential substr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8564 addl(cnt1, 8); // prime the loop |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8565 addl(cnt2, 8); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8566 subptr(str1, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8567 subptr(str2, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8568 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8569 // Scan 16-byte vectors of string and substr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8570 bind(SCAN_SUBSTR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8571 subl(cnt1, 8); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8572 subl(cnt2, 8); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8573 addptr(str1, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8574 addptr(str2, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8575 movdqu(vec, Address(str2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8576 pcmpestri(vec, Address(str1, 0), 0x0d); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8577 jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8578 jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8579 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8580 // Compute substr offset |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8581 subptr(result, Address(rsp, 2*wordSize)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8582 shrl(result, 1); // index |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8583 jmpb(CLEANUP); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8584 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8585 bind(RET_NOT_FOUND); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8586 movl(result, -1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8587 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8588 bind(CLEANUP); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8589 addptr(rsp, 3*wordSize); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8590 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8591 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8592 // Compare strings. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8593 void MacroAssembler::string_compare(Register str1, Register str2, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8594 Register cnt1, Register cnt2, Register result, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8595 XMMRegister vec1, XMMRegister vec2) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8596 Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8597 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8598 // Compute the minimum of the string lengths and the |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8599 // difference of the string lengths (stack). |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8600 // Do the conditional move stuff |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8601 movl(result, cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8602 subl(cnt1, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8603 push(cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8604 if (VM_Version::supports_cmov()) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8605 cmovl(Assembler::lessEqual, cnt2, result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8606 } else { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8607 Label GT_LABEL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8608 jccb(Assembler::greater, GT_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8609 movl(cnt2, result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8610 bind(GT_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8611 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8612 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8613 // Is the minimum length zero? |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8614 testl(cnt2, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8615 jcc(Assembler::zero, LENGTH_DIFF_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8616 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8617 // Load first characters |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8618 load_unsigned_short(result, Address(str1, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8619 load_unsigned_short(cnt1, Address(str2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8620 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8621 // Compare first characters |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8622 subl(result, cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8623 jcc(Assembler::notZero, POP_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8624 decrementl(cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8625 jcc(Assembler::zero, LENGTH_DIFF_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8626 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8627 { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8628 // Check after comparing first character to see if strings are equivalent |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8629 Label LSkip2; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8630 // Check if the strings start at same location |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8631 cmpptr(str1, str2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8632 jccb(Assembler::notEqual, LSkip2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8633 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8634 // Check if the length difference is zero (from stack) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8635 cmpl(Address(rsp, 0), 0x0); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8636 jcc(Assembler::equal, LENGTH_DIFF_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8637 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8638 // Strings might not be equivalent |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8639 bind(LSkip2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8640 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8641 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8642 // Advance to next character |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8643 addptr(str1, 2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8644 addptr(str2, 2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8645 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8646 if (UseSSE42Intrinsics) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8647 // With SSE4.2, use double quad vector compare |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8648 Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8649 // Setup to compare 16-byte vectors |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8650 movl(cnt1, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8651 andl(cnt2, 0xfffffff8); // cnt2 holds the vector count |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8652 andl(cnt1, 0x00000007); // cnt1 holds the tail count |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8653 testl(cnt2, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8654 jccb(Assembler::zero, COMPARE_TAIL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8655 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8656 lea(str2, Address(str2, cnt2, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8657 lea(str1, Address(str1, cnt2, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8658 negptr(cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8659 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8660 bind(COMPARE_VECTORS); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8661 movdqu(vec1, Address(str1, cnt2, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8662 movdqu(vec2, Address(str2, cnt2, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8663 pxor(vec1, vec2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8664 ptest(vec1, vec1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8665 jccb(Assembler::notZero, VECTOR_NOT_EQUAL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8666 addptr(cnt2, 8); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8667 jcc(Assembler::notZero, COMPARE_VECTORS); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8668 jmpb(COMPARE_TAIL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8669 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8670 // Mismatched characters in the vectors |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8671 bind(VECTOR_NOT_EQUAL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8672 lea(str1, Address(str1, cnt2, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8673 lea(str2, Address(str2, cnt2, Address::times_2)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8674 movl(cnt1, 8); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8675 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8676 // Compare tail (< 8 chars), or rescan last vectors to |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8677 // find 1st mismatched characters |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8678 bind(COMPARE_TAIL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8679 testl(cnt1, cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8680 jccb(Assembler::zero, LENGTH_DIFF_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8681 movl(cnt2, cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8682 // Fallthru to tail compare |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8683 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8684 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8685 // Shift str2 and str1 to the end of the arrays, negate min |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8686 lea(str1, Address(str1, cnt2, Address::times_2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8687 lea(str2, Address(str2, cnt2, Address::times_2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8688 negptr(cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8689 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8690 // Compare the rest of the characters |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8691 bind(WHILE_HEAD_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8692 load_unsigned_short(result, Address(str1, cnt2, Address::times_2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8693 load_unsigned_short(cnt1, Address(str2, cnt2, Address::times_2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8694 subl(result, cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8695 jccb(Assembler::notZero, POP_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8696 increment(cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8697 jcc(Assembler::notZero, WHILE_HEAD_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8698 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8699 // Strings are equal up to min length. Return the length difference. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8700 bind(LENGTH_DIFF_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8701 pop(result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8702 jmpb(DONE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8703 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8704 // Discard the stored length difference |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8705 bind(POP_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8706 addptr(rsp, wordSize); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8707 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8708 // That's it |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8709 bind(DONE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8710 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8711 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8712 // Compare char[] arrays aligned to 4 bytes or substrings. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8713 void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8714 Register limit, Register result, Register chr, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8715 XMMRegister vec1, XMMRegister vec2) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8716 Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8717 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8718 int length_offset = arrayOopDesc::length_offset_in_bytes(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8719 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8720 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8721 // Check the input args |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8722 cmpptr(ary1, ary2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8723 jcc(Assembler::equal, TRUE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8724 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8725 if (is_array_equ) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8726 // Need additional checks for arrays_equals. |
1016 | 8727 testptr(ary1, ary1); |
8728 jcc(Assembler::zero, FALSE_LABEL); | |
8729 testptr(ary2, ary2); | |
8730 jcc(Assembler::zero, FALSE_LABEL); | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8731 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8732 // Check the lengths |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8733 movl(limit, Address(ary1, length_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8734 cmpl(limit, Address(ary2, length_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8735 jcc(Assembler::notEqual, FALSE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8736 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8737 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8738 // count == 0 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8739 testl(limit, limit); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8740 jcc(Assembler::zero, TRUE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8741 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8742 if (is_array_equ) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8743 // Load array address |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8744 lea(ary1, Address(ary1, base_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8745 lea(ary2, Address(ary2, base_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8746 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8747 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8748 shll(limit, 1); // byte count != 0 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8749 movl(result, limit); // copy |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8750 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8751 if (UseSSE42Intrinsics) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8752 // With SSE4.2, use double quad vector compare |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8753 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8754 // Compare 16-byte vectors |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8755 andl(result, 0x0000000e); // tail count (in bytes) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8756 andl(limit, 0xfffffff0); // vector count (in bytes) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8757 jccb(Assembler::zero, COMPARE_TAIL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8758 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8759 lea(ary1, Address(ary1, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8760 lea(ary2, Address(ary2, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8761 negptr(limit); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8762 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8763 bind(COMPARE_WIDE_VECTORS); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8764 movdqu(vec1, Address(ary1, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8765 movdqu(vec2, Address(ary2, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8766 pxor(vec1, vec2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8767 ptest(vec1, vec1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8768 jccb(Assembler::notZero, FALSE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8769 addptr(limit, 16); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8770 jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8771 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8772 bind(COMPARE_TAIL); // limit is zero |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8773 movl(limit, result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8774 // Fallthru to tail compare |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8775 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8776 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8777 // Compare 4-byte vectors |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8778 andl(limit, 0xfffffffc); // vector count (in bytes) |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8779 jccb(Assembler::zero, COMPARE_CHAR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8780 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8781 lea(ary1, Address(ary1, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8782 lea(ary2, Address(ary2, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8783 negptr(limit); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8784 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8785 bind(COMPARE_VECTORS); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8786 movl(chr, Address(ary1, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8787 cmpl(chr, Address(ary2, limit, Address::times_1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8788 jccb(Assembler::notEqual, FALSE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8789 addptr(limit, 4); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8790 jcc(Assembler::notZero, COMPARE_VECTORS); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8791 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8792 // Compare trailing char (final 2 bytes), if any |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8793 bind(COMPARE_CHAR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8794 testl(result, 0x2); // tail char |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8795 jccb(Assembler::zero, TRUE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8796 load_unsigned_short(chr, Address(ary1, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8797 load_unsigned_short(limit, Address(ary2, 0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8798 cmpl(chr, limit); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8799 jccb(Assembler::notEqual, FALSE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8800 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8801 bind(TRUE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8802 movl(result, 1); // return true |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8803 jmpb(DONE); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8804 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8805 bind(FALSE_LABEL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8806 xorl(result, result); // return false |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8807 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8808 // That's it |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8809 bind(DONE); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8810 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
898
diff
changeset
|
8811 |
1763 | 8812 #ifdef PRODUCT |
8813 #define BLOCK_COMMENT(str) /* nothing */ | |
8814 #else | |
8815 #define BLOCK_COMMENT(str) block_comment(str) | |
8816 #endif | |
8817 | |
8818 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") | |
8819 void MacroAssembler::generate_fill(BasicType t, bool aligned, | |
8820 Register to, Register value, Register count, | |
8821 Register rtmp, XMMRegister xtmp) { | |
8822 assert_different_registers(to, value, count, rtmp); | |
8823 Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte; | |
8824 Label L_fill_2_bytes, L_fill_4_bytes; | |
8825 | |
8826 int shift = -1; | |
8827 switch (t) { | |
8828 case T_BYTE: | |
8829 shift = 2; | |
8830 break; | |
8831 case T_SHORT: | |
8832 shift = 1; | |
8833 break; | |
8834 case T_INT: | |
8835 shift = 0; | |
8836 break; | |
8837 default: ShouldNotReachHere(); | |
8838 } | |
8839 | |
8840 if (t == T_BYTE) { | |
8841 andl(value, 0xff); | |
8842 movl(rtmp, value); | |
8843 shll(rtmp, 8); | |
8844 orl(value, rtmp); | |
8845 } | |
8846 if (t == T_SHORT) { | |
8847 andl(value, 0xffff); | |
8848 } | |
8849 if (t == T_BYTE || t == T_SHORT) { | |
8850 movl(rtmp, value); | |
8851 shll(rtmp, 16); | |
8852 orl(value, rtmp); | |
8853 } | |
8854 | |
8855 cmpl(count, 2<<shift); // Short arrays (< 8 bytes) fill by element | |
8856 jcc(Assembler::below, L_fill_4_bytes); // use unsigned cmp | |
8857 if (!UseUnalignedLoadStores && !aligned && (t == T_BYTE || t == T_SHORT)) { | |
8858 // align source address at 4 bytes address boundary | |
8859 if (t == T_BYTE) { | |
8860 // One byte misalignment happens only for byte arrays | |
8861 testptr(to, 1); | |
8862 jccb(Assembler::zero, L_skip_align1); | |
8863 movb(Address(to, 0), value); | |
8864 increment(to); | |
8865 decrement(count); | |
8866 BIND(L_skip_align1); | |
8867 } | |
8868 // Two bytes misalignment happens only for byte and short (char) arrays | |
8869 testptr(to, 2); | |
8870 jccb(Assembler::zero, L_skip_align2); | |
8871 movw(Address(to, 0), value); | |
8872 addptr(to, 2); | |
8873 subl(count, 1<<(shift-1)); | |
8874 BIND(L_skip_align2); | |
8875 } | |
8876 if (UseSSE < 2) { | |
8877 Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes; | |
8878 // Fill 32-byte chunks | |
8879 subl(count, 8 << shift); | |
8880 jcc(Assembler::less, L_check_fill_8_bytes); | |
8881 align(16); | |
8882 | |
8883 BIND(L_fill_32_bytes_loop); | |
8884 | |
8885 for (int i = 0; i < 32; i += 4) { | |
8886 movl(Address(to, i), value); | |
8887 } | |
8888 | |
8889 addptr(to, 32); | |
8890 subl(count, 8 << shift); | |
8891 jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); | |
8892 BIND(L_check_fill_8_bytes); | |
8893 addl(count, 8 << shift); | |
8894 jccb(Assembler::zero, L_exit); | |
8895 jmpb(L_fill_8_bytes); | |
8896 | |
8897 // | |
8898 // length is too short, just fill qwords | |
8899 // | |
8900 BIND(L_fill_8_bytes_loop); | |
8901 movl(Address(to, 0), value); | |
8902 movl(Address(to, 4), value); | |
8903 addptr(to, 8); | |
8904 BIND(L_fill_8_bytes); | |
8905 subl(count, 1 << (shift + 1)); | |
8906 jcc(Assembler::greaterEqual, L_fill_8_bytes_loop); | |
8907 // fall through to fill 4 bytes | |
8908 } else { | |
8909 Label L_fill_32_bytes; | |
8910 if (!UseUnalignedLoadStores) { | |
8911 // align to 8 bytes, we know we are 4 byte aligned to start | |
8912 testptr(to, 4); | |
8913 jccb(Assembler::zero, L_fill_32_bytes); | |
8914 movl(Address(to, 0), value); | |
8915 addptr(to, 4); | |
8916 subl(count, 1<<shift); | |
8917 } | |
8918 BIND(L_fill_32_bytes); | |
8919 { | |
8920 assert( UseSSE >= 2, "supported cpu only" ); | |
8921 Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes; | |
8922 // Fill 32-byte chunks | |
8923 movdl(xtmp, value); | |
8924 pshufd(xtmp, xtmp, 0); | |
8925 | |
8926 subl(count, 8 << shift); | |
8927 jcc(Assembler::less, L_check_fill_8_bytes); | |
8928 align(16); | |
8929 | |
8930 BIND(L_fill_32_bytes_loop); | |
8931 | |
8932 if (UseUnalignedLoadStores) { | |
8933 movdqu(Address(to, 0), xtmp); | |
8934 movdqu(Address(to, 16), xtmp); | |
8935 } else { | |
8936 movq(Address(to, 0), xtmp); | |
8937 movq(Address(to, 8), xtmp); | |
8938 movq(Address(to, 16), xtmp); | |
8939 movq(Address(to, 24), xtmp); | |
8940 } | |
8941 | |
8942 addptr(to, 32); | |
8943 subl(count, 8 << shift); | |
8944 jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); | |
8945 BIND(L_check_fill_8_bytes); | |
8946 addl(count, 8 << shift); | |
8947 jccb(Assembler::zero, L_exit); | |
8948 jmpb(L_fill_8_bytes); | |
8949 | |
8950 // | |
8951 // length is too short, just fill qwords | |
8952 // | |
8953 BIND(L_fill_8_bytes_loop); | |
8954 movq(Address(to, 0), xtmp); | |
8955 addptr(to, 8); | |
8956 BIND(L_fill_8_bytes); | |
8957 subl(count, 1 << (shift + 1)); | |
8958 jcc(Assembler::greaterEqual, L_fill_8_bytes_loop); | |
8959 } | |
8960 } | |
8961 // fill trailing 4 bytes | |
8962 BIND(L_fill_4_bytes); | |
8963 testl(count, 1<<shift); | |
8964 jccb(Assembler::zero, L_fill_2_bytes); | |
8965 movl(Address(to, 0), value); | |
8966 if (t == T_BYTE || t == T_SHORT) { | |
8967 addptr(to, 4); | |
8968 BIND(L_fill_2_bytes); | |
8969 // fill trailing 2 bytes | |
8970 testl(count, 1<<(shift-1)); | |
8971 jccb(Assembler::zero, L_fill_byte); | |
8972 movw(Address(to, 0), value); | |
8973 if (t == T_BYTE) { | |
8974 addptr(to, 2); | |
8975 BIND(L_fill_byte); | |
8976 // fill trailing byte | |
8977 testl(count, 1); | |
8978 jccb(Assembler::zero, L_exit); | |
8979 movb(Address(to, 0), value); | |
8980 } else { | |
8981 BIND(L_fill_byte); | |
8982 } | |
8983 } else { | |
8984 BIND(L_fill_2_bytes); | |
8985 } | |
8986 BIND(L_exit); | |
8987 } | |
8988 #undef BIND | |
8989 #undef BLOCK_COMMENT | |
8990 | |
8991 | |
0 | 8992 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { |
8993 switch (cond) { | |
8994 // Note some conditions are synonyms for others | |
8995 case Assembler::zero: return Assembler::notZero; | |
8996 case Assembler::notZero: return Assembler::zero; | |
8997 case Assembler::less: return Assembler::greaterEqual; | |
8998 case Assembler::lessEqual: return Assembler::greater; | |
8999 case Assembler::greater: return Assembler::lessEqual; | |
9000 case Assembler::greaterEqual: return Assembler::less; | |
9001 case Assembler::below: return Assembler::aboveEqual; | |
9002 case Assembler::belowEqual: return Assembler::above; | |
9003 case Assembler::above: return Assembler::belowEqual; | |
9004 case Assembler::aboveEqual: return Assembler::below; | |
9005 case Assembler::overflow: return Assembler::noOverflow; | |
9006 case Assembler::noOverflow: return Assembler::overflow; | |
9007 case Assembler::negative: return Assembler::positive; | |
9008 case Assembler::positive: return Assembler::negative; | |
9009 case Assembler::parity: return Assembler::noParity; | |
9010 case Assembler::noParity: return Assembler::parity; | |
9011 } | |
9012 ShouldNotReachHere(); return Assembler::overflow; | |
9013 } | |
9014 | |
9015 SkipIfEqual::SkipIfEqual( | |
9016 MacroAssembler* masm, const bool* flag_addr, bool value) { | |
9017 _masm = masm; | |
9018 _masm->cmp8(ExternalAddress((address)flag_addr), value); | |
9019 _masm->jcc(Assembler::equal, _label); | |
9020 } | |
9021 | |
9022 SkipIfEqual::~SkipIfEqual() { | |
9023 _masm->bind(_label); | |
9024 } |