1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef CPU_SPARC_VM_NATIVEINST_SPARC_HPP 26 #define CPU_SPARC_VM_NATIVEINST_SPARC_HPP 27 28 #include "asm/macroAssembler.hpp" 29 #include "memory/allocation.hpp" 30 #include "runtime/icache.hpp" 31 #include "runtime/os.hpp" 32 33 // We have interface for the following instructions: 34 // - NativeInstruction 35 // - - NativeCall 36 // - - NativeFarCall 37 // - - NativeMovConstReg 38 // - - NativeMovConstRegPatching 39 // - - NativeMovRegMem 40 // - - NativeJump 41 // - - NativeGeneralJump 42 // - - NativeIllegalInstruction 43 // The base class for different kinds of native instruction abstractions. 44 // Provides the primitive operations to manipulate code relative to this. 45 class NativeInstruction VALUE_OBJ_CLASS_SPEC { 46 friend class Relocation; 47 48 public: 49 enum Sparc_specific_constants { 50 nop_instruction_size = 4 51 }; 52 53 bool is_nop() { return long_at(0) == nop_instruction(); } 54 bool is_call() { return is_op(long_at(0), Assembler::call_op); } 55 bool is_call_reg() { return is_op(long_at(0), Assembler::arith_op); } 56 bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2) 57 && inv_rd(long_at(0)) != G0); } 58 59 bool sets_cc() { 60 // conservative (returns true for some instructions that do not set the 61 // the condition code, such as, "save". 62 // Does not return true for the deprecated tagged instructions, such as, TADDcc 63 int x = long_at(0); 64 return (is_op(x, Assembler::arith_op) && 65 (inv_op3(x) & Assembler::cc_bit_op3) == Assembler::cc_bit_op3); 66 } 67 bool is_illegal(); 68 bool is_zombie() { 69 int x = long_at(0); 70 return is_op3(x, 71 Assembler::ldsw_op3, 72 Assembler::ldst_op) 73 && Assembler::inv_rs1(x) == G0 74 && Assembler::inv_rd(x) == O7; 75 } 76 bool is_ic_miss_trap(); // Inline-cache uses a trap to detect a miss 77 bool is_return() { 78 // is it the output of MacroAssembler::ret or MacroAssembler::retl? 79 int x = long_at(0); 80 const int pc_return_offset = 8; // see frame_sparc.hpp 81 return is_op3(x, Assembler::jmpl_op3, Assembler::arith_op) 82 && (inv_rs1(x) == I7 || inv_rs1(x) == O7) 83 && inv_immed(x) && inv_simm(x, 13) == pc_return_offset 84 && inv_rd(x) == G0; 85 } 86 bool is_int_jump() { 87 // is it the output of MacroAssembler::b? 88 int x = long_at(0); 89 return is_op2(x, Assembler::bp_op2) || is_op2(x, Assembler::br_op2); 90 } 91 bool is_float_jump() { 92 // is it the output of MacroAssembler::fb? 93 int x = long_at(0); 94 return is_op2(x, Assembler::fbp_op2) || is_op2(x, Assembler::fb_op2); 95 } 96 bool is_jump() { 97 return is_int_jump() || is_float_jump(); 98 } 99 bool is_cond_jump() { 100 int x = long_at(0); 101 return (is_int_jump() && Assembler::inv_cond(x) != Assembler::always) || 102 (is_float_jump() && Assembler::inv_cond(x) != Assembler::f_always); 103 } 104 105 bool is_stack_bang() { 106 int x = long_at(0); 107 return is_op3(x, Assembler::stw_op3, Assembler::ldst_op) && 108 (inv_rd(x) == G0) && (inv_rs1(x) == SP) && (inv_rs2(x) == G3_scratch); 109 } 110 111 bool is_prefetch() { 112 int x = long_at(0); 113 return is_op3(x, Assembler::prefetch_op3, Assembler::ldst_op); 114 } 115 116 bool is_membar() { 117 int x = long_at(0); 118 return is_op3(x, Assembler::membar_op3, Assembler::arith_op) && 119 (inv_rd(x) == G0) && (inv_rs1(x) == O7); 120 } 121 122 bool is_safepoint_poll() { 123 int x = long_at(0); 124 return is_op3(x, Assembler::ldx_op3, Assembler::ldst_op) && 125 (inv_rd(x) == G0) && (inv_immed(x) ? Assembler::inv_simm13(x) == 0 : inv_rs2(x) == G0); 126 } 127 128 bool is_zero_test(Register ®); 129 bool is_load_store_with_small_offset(Register reg); 130 131 public: 132 #ifdef ASSERT 133 static int rdpc_instruction() { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | Assembler::u_field(5, 18, 14) | Assembler::rd(O7); } 134 #else 135 // Temporary fix: in optimized mode, u_field is a macro for efficiency reasons (see Assembler::u_field) - needs to be fixed 136 static int rdpc_instruction() { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | u_field(5, 18, 14) | Assembler::rd(O7); } 137 #endif 138 static int nop_instruction() { return Assembler::op(Assembler::branch_op) | Assembler::op2(Assembler::sethi_op2); } 139 static int illegal_instruction(); // the output of __ breakpoint_trap() 140 static int call_instruction(address destination, address pc) { return Assembler::op(Assembler::call_op) | Assembler::wdisp((intptr_t)destination, (intptr_t)pc, 30); } 141 142 static int branch_instruction(Assembler::op2s op2val, Assembler::Condition c, bool a) { 143 return Assembler::op(Assembler::branch_op) | Assembler::op2(op2val) | Assembler::annul(a) | Assembler::cond(c); 144 } 145 146 static int op3_instruction(Assembler::ops opval, Register rd, Assembler::op3s op3val, Register rs1, int simm13a) { 147 return Assembler::op(opval) | Assembler::rd(rd) | Assembler::op3(op3val) | Assembler::rs1(rs1) | Assembler::immed(true) | Assembler::simm(simm13a, 13); 148 } 149 150 static int sethi_instruction(Register rd, int imm22a) { 151 return Assembler::op(Assembler::branch_op) | Assembler::rd(rd) | Assembler::op2(Assembler::sethi_op2) | Assembler::hi22(imm22a); 152 } 153 154 protected: 155 address addr_at(int offset) const { return address(this) + offset; } 156 int long_at(int offset) const { return *(int*)addr_at(offset); } 157 void set_long_at(int offset, int i); /* deals with I-cache */ 158 void set_jlong_at(int offset, jlong i); /* deals with I-cache */ 159 void set_addr_at(int offset, address x); /* deals with I-cache */ 160 161 address instruction_address() const { return addr_at(0); } 162 address next_instruction_address() const { return addr_at(BytesPerInstWord); } 163 164 static bool is_op( int x, Assembler::ops opval) { 165 return Assembler::inv_op(x) == opval; 166 } 167 static bool is_op2(int x, Assembler::op2s op2val) { 168 return Assembler::inv_op(x) == Assembler::branch_op && Assembler::inv_op2(x) == op2val; 169 } 170 static bool is_op3(int x, Assembler::op3s op3val, Assembler::ops opval) { 171 return Assembler::inv_op(x) == opval && Assembler::inv_op3(x) == op3val; 172 } 173 174 // utilities to help subclasses decode: 175 static Register inv_rd( int x ) { return Assembler::inv_rd( x); } 176 static Register inv_rs1( int x ) { return Assembler::inv_rs1(x); } 177 static Register inv_rs2( int x ) { return Assembler::inv_rs2(x); } 178 179 static bool inv_immed( int x ) { return Assembler::inv_immed(x); } 180 static bool inv_annul( int x ) { return (Assembler::annul(true) & x) != 0; } 181 static int inv_cond( int x ) { return Assembler::inv_cond(x); } 182 183 static int inv_op( int x ) { return Assembler::inv_op( x); } 184 static int inv_op2( int x ) { return Assembler::inv_op2(x); } 185 static int inv_op3( int x ) { return Assembler::inv_op3(x); } 186 187 static int inv_simm( int x, int nbits ) { return Assembler::inv_simm(x, nbits); } 188 static intptr_t inv_wdisp( int x, int nbits ) { return Assembler::inv_wdisp( x, 0, nbits); } 189 static intptr_t inv_wdisp16( int x ) { return Assembler::inv_wdisp16(x, 0); } 190 static int branch_destination_offset(int x) { return MacroAssembler::branch_destination(x, 0); } 191 static int patch_branch_destination_offset(int dest_offset, int x) { 192 return MacroAssembler::patched_branch(dest_offset, x, 0); 193 } 194 195 // utility for checking if x is either of 2 small constants 196 static bool is_either(int x, int k1, int k2) { 197 // return x == k1 || x == k2; 198 return (1 << x) & (1 << k1 | 1 << k2); 199 } 200 201 // utility for checking overflow of signed instruction fields 202 static bool fits_in_simm(int x, int nbits) { 203 // cf. Assembler::assert_signed_range() 204 // return -(1 << nbits-1) <= x && x < ( 1 << nbits-1), 205 return (unsigned)(x + (1 << nbits-1)) < (unsigned)(1 << nbits); 206 } 207 208 // set a signed immediate field 209 static int set_simm(int insn, int imm, int nbits) { 210 return (insn &~ Assembler::simm(-1, nbits)) | Assembler::simm(imm, nbits); 211 } 212 213 // set a wdisp field (disp should be the difference of two addresses) 214 static int set_wdisp(int insn, intptr_t disp, int nbits) { 215 return (insn &~ Assembler::wdisp((intptr_t)-4, (intptr_t)0, nbits)) | Assembler::wdisp(disp, 0, nbits); 216 } 217 218 static int set_wdisp16(int insn, intptr_t disp) { 219 return (insn &~ Assembler::wdisp16((intptr_t)-4, 0)) | Assembler::wdisp16(disp, 0); 220 } 221 222 // get a simm13 field from an arithmetic or memory instruction 223 static int get_simm13(int insn) { 224 assert(is_either(Assembler::inv_op(insn), 225 Assembler::arith_op, Assembler::ldst_op) && 226 (insn & Assembler::immed(true)), "must have a simm13 field"); 227 return Assembler::inv_simm(insn, 13); 228 } 229 230 // set the simm13 field of an arithmetic or memory instruction 231 static bool set_simm13(int insn, int imm) { 232 get_simm13(insn); // tickle the assertion check 233 return set_simm(insn, imm, 13); 234 } 235 236 // combine the fields of a sethi stream (7 instructions ) and an add, jmp or ld/st 237 static intptr_t data64( address pc, int arith_insn ) { 238 assert(is_op2(*(unsigned int *)pc, Assembler::sethi_op2), "must be sethi"); 239 intptr_t hi = (intptr_t)gethi( (unsigned int *)pc ); 240 intptr_t lo = (intptr_t)get_simm13(arith_insn); 241 assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits"); 242 return hi | lo; 243 } 244 245 // Regenerate the instruction sequence that performs the 64 bit 246 // sethi. This only does the sethi. The disp field (bottom 10 bits) 247 // must be handled separately. 248 static void set_data64_sethi(address instaddr, intptr_t x); 249 static void verify_data64_sethi(address instaddr, intptr_t x); 250 251 // combine the fields of a sethi/simm13 pair (simm13 = or, add, jmpl, ld/st) 252 static int data32(int sethi_insn, int arith_insn) { 253 assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi"); 254 int hi = Assembler::inv_hi22(sethi_insn); 255 int lo = get_simm13(arith_insn); 256 assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits"); 257 return hi | lo; 258 } 259 260 static int set_data32_sethi(int sethi_insn, int imm) { 261 // note that Assembler::hi22 clips the low 10 bits for us 262 assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi"); 263 return (sethi_insn &~ Assembler::hi22(-1)) | Assembler::hi22(imm); 264 } 265 266 static int set_data32_simm13(int arith_insn, int imm) { 267 get_simm13(arith_insn); // tickle the assertion check 268 int imm10 = Assembler::low10(imm); 269 return (arith_insn &~ Assembler::simm(-1, 13)) | Assembler::simm(imm10, 13); 270 } 271 272 static int low10(int imm) { 273 return Assembler::low10(imm); 274 } 275 276 // Perform the inverse of the LP64 Macroassembler::sethi 277 // routine. Extracts the 54 bits of address from the instruction 278 // stream. This routine must agree with the sethi routine in 279 // assembler_inline_sparc.hpp 280 static address gethi( unsigned int *pc ) { 281 int i = 0; 282 uintptr_t adr; 283 // We first start out with the real sethi instruction 284 assert(is_op2(*pc, Assembler::sethi_op2), "in gethi - must be sethi"); 285 adr = (unsigned int)Assembler::inv_hi22( *(pc++) ); 286 i++; 287 while ( i < 7 ) { 288 // We're done if we hit a nop 289 if ( (int)*pc == nop_instruction() ) break; 290 assert ( Assembler::inv_op(*pc) == Assembler::arith_op, "in gethi - must be arith_op" ); 291 switch ( Assembler::inv_op3(*pc) ) { 292 case Assembler::xor_op3: 293 adr ^= (intptr_t)get_simm13( *pc ); 294 return ( (address)adr ); 295 break; 296 case Assembler::sll_op3: 297 adr <<= ( *pc & 0x3f ); 298 break; 299 case Assembler::or_op3: 300 adr |= (intptr_t)get_simm13( *pc ); 301 break; 302 default: 303 assert ( 0, "in gethi - Should not reach here" ); 304 break; 305 } 306 pc++; 307 i++; 308 } 309 return ( (address)adr ); 310 } 311 312 public: 313 void verify(); 314 void print(); 315 316 // unit test stuff 317 static void test() {} // override for testing 318 319 inline friend NativeInstruction* nativeInstruction_at(address address); 320 }; 321 322 inline NativeInstruction* nativeInstruction_at(address address) { 323 NativeInstruction* inst = (NativeInstruction*)address; 324 #ifdef ASSERT 325 inst->verify(); 326 #endif 327 return inst; 328 } 329 330 331 332 //----------------------------------------------------------------------------- 333 334 // The NativeCall is an abstraction for accessing/manipulating native call imm32 instructions. 335 // (used to manipulate inline caches, primitive & dll calls, etc.) 336 inline NativeCall* nativeCall_at(address instr); 337 inline NativeCall* nativeCall_overwriting_at(address instr, 338 address destination); 339 inline NativeCall* nativeCall_before(address return_address); 340 class NativeCall: public NativeInstruction { 341 public: 342 enum Sparc_specific_constants { 343 instruction_size = 8, 344 return_address_offset = 8, 345 call_displacement_width = 30, 346 displacement_offset = 0, 347 instruction_offset = 0 348 }; 349 address instruction_address() const { return addr_at(0); } 350 address next_instruction_address() const { return addr_at(instruction_size); } 351 address return_address() const { return addr_at(return_address_offset); } 352 353 address destination() const { return inv_wdisp(long_at(0), call_displacement_width) + instruction_address(); } 354 address displacement_address() const { return addr_at(displacement_offset); } 355 void set_destination(address dest) { set_long_at(0, set_wdisp(long_at(0), dest - instruction_address(), call_displacement_width)); } 356 void set_destination_mt_safe(address dest); 357 358 void verify_alignment() {} // do nothing on sparc 359 void verify(); 360 void print(); 361 362 // unit test stuff 363 static void test(); 364 365 // Creation 366 friend inline NativeCall* nativeCall_at(address instr); 367 friend NativeCall* nativeCall_overwriting_at(address instr, address destination = NULL) { 368 // insert a "blank" call: 369 NativeCall* call = (NativeCall*)instr; 370 call->set_long_at(0 * BytesPerInstWord, call_instruction(destination, instr)); 371 call->set_long_at(1 * BytesPerInstWord, nop_instruction()); 372 assert(call->addr_at(2 * BytesPerInstWord) - instr == instruction_size, "instruction size"); 373 // check its structure now: 374 assert(nativeCall_at(instr)->destination() == destination, "correct call destination"); 375 return call; 376 } 377 378 friend inline NativeCall* nativeCall_before(address return_address) { 379 NativeCall* call = (NativeCall*)(return_address - return_address_offset); 380 #ifdef ASSERT 381 call->verify(); 382 #endif 383 return call; 384 } 385 386 static bool is_call_at(address instr) { 387 return nativeInstruction_at(instr)->is_call(); 388 } 389 390 static bool is_call_before(address instr) { 391 return nativeInstruction_at(instr - return_address_offset)->is_call(); 392 } 393 394 static bool is_call_to(address instr, address target) { 395 return nativeInstruction_at(instr)->is_call() && 396 nativeCall_at(instr)->destination() == target; 397 } 398 399 // MT-safe patching of a call instruction. 400 static void insert(address code_pos, address entry) { 401 (void)nativeCall_overwriting_at(code_pos, entry); 402 } 403 404 static void replace_mt_safe(address instr_addr, address code_buffer); 405 }; 406 inline NativeCall* nativeCall_at(address instr) { 407 NativeCall* call = (NativeCall*)instr; 408 #ifdef ASSERT 409 call->verify(); 410 #endif 411 return call; 412 } 413 414 class NativeCallReg: public NativeInstruction { 415 public: 416 enum Sparc_specific_constants { 417 instruction_size = 8, 418 return_address_offset = 8, 419 instruction_offset = 0 420 }; 421 422 address next_instruction_address() const { 423 return addr_at(instruction_size); 424 } 425 }; 426 427 // The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere 428 // instructions in the sparcv9 vm. Used to call native methods which may be loaded 429 // anywhere in the address space, possibly out of reach of a call instruction. 430 431 // The format of this extended-range call is: 432 // jumpl_to addr, lreg 433 // == sethi %hi54(addr), O7 ; jumpl O7, %lo10(addr), O7 ; <delay> 434 // That is, it is essentially the same as a NativeJump. 435 class NativeFarCall; 436 inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination); 437 inline NativeFarCall* nativeFarCall_at(address instr); 438 class NativeFarCall: public NativeInstruction { 439 public: 440 enum Sparc_specific_constants { 441 // instruction_size includes the delay slot instruction. 442 instruction_size = 9 * BytesPerInstWord, 443 return_address_offset = 9 * BytesPerInstWord, 444 jmpl_offset = 7 * BytesPerInstWord, 445 displacement_offset = 0, 446 instruction_offset = 0 447 }; 448 address instruction_address() const { return addr_at(0); } 449 address next_instruction_address() const { return addr_at(instruction_size); } 450 address return_address() const { return addr_at(return_address_offset); } 451 452 address destination() const { 453 return (address) data64(addr_at(0), long_at(jmpl_offset)); 454 } 455 address displacement_address() const { return addr_at(displacement_offset); } 456 void set_destination(address dest); 457 458 bool destination_is_compiled_verified_entry_point(); 459 460 void verify(); 461 void print(); 462 463 // unit test stuff 464 static void test(); 465 466 // Creation 467 friend inline NativeFarCall* nativeFarCall_at(address instr) { 468 NativeFarCall* call = (NativeFarCall*)instr; 469 #ifdef ASSERT 470 call->verify(); 471 #endif 472 return call; 473 } 474 475 friend inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) { 476 Unimplemented(); 477 NativeFarCall* call = (NativeFarCall*)instr; 478 return call; 479 } 480 481 friend NativeFarCall* nativeFarCall_before(address return_address) { 482 NativeFarCall* call = (NativeFarCall*)(return_address - return_address_offset); 483 #ifdef ASSERT 484 call->verify(); 485 #endif 486 return call; 487 } 488 489 static bool is_call_at(address instr); 490 491 // MT-safe patching of a call instruction. 492 static void insert(address code_pos, address entry) { 493 (void)nativeFarCall_overwriting_at(code_pos, entry); 494 } 495 static void replace_mt_safe(address instr_addr, address code_buffer); 496 }; 497 498 499 // An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions 500 // (used to manipulate inlined data references, etc.) 501 // set_metadata imm, reg 502 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg 503 class NativeMovConstReg32; 504 inline NativeMovConstReg32* nativeMovConstReg32_at(address address); 505 class NativeMovConstReg32: public NativeInstruction { 506 public: 507 enum Sparc_specific_constants { 508 sethi_offset = 0, 509 add_offset = 4, 510 instruction_size = 8 511 }; 512 513 address instruction_address() const { return addr_at(0); } 514 address next_instruction_address() const { return addr_at(instruction_size); } 515 516 // (The [set_]data accessor respects oop_type relocs also.) 517 intptr_t data() const; 518 void set_data(intptr_t x); 519 520 // report the destination register 521 Register destination() { return inv_rd(long_at(sethi_offset)); } 522 523 void verify(); 524 void print(); 525 526 // unit test stuff 527 static void test(); 528 529 // Creation 530 friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) { 531 NativeMovConstReg32* test = (NativeMovConstReg32*)address; 532 #ifdef ASSERT 533 test->verify(); 534 #endif 535 return test; 536 } 537 }; 538 539 // An interface for accessing/manipulating native set_metadata imm, reg instructions. 540 // (used to manipulate inlined data references, etc.) 541 // set_metadata imm, reg 542 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg 543 class NativeMovConstReg; 544 inline NativeMovConstReg* nativeMovConstReg_at(address address); 545 class NativeMovConstReg: public NativeInstruction { 546 public: 547 enum Sparc_specific_constants { 548 sethi_offset = 0, 549 add_offset = 7 * BytesPerInstWord, 550 instruction_size = 8 * BytesPerInstWord 551 }; 552 553 address instruction_address() const { return addr_at(0); } 554 address next_instruction_address() const { return addr_at(instruction_size); } 555 556 // (The [set_]data accessor respects oop_type relocs also.) 557 intptr_t data() const; 558 void set_data(intptr_t x); 559 560 // report the destination register 561 Register destination() { return inv_rd(long_at(sethi_offset)); } 562 563 void verify(); 564 void print(); 565 566 // unit test stuff 567 static void test(); 568 569 // Creation 570 friend inline NativeMovConstReg* nativeMovConstReg_at(address address) { 571 NativeMovConstReg* test = (NativeMovConstReg*)address; 572 #ifdef ASSERT 573 test->verify(); 574 #endif 575 return test; 576 } 577 578 579 friend NativeMovConstReg* nativeMovConstReg_before(address address) { 580 NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size); 581 #ifdef ASSERT 582 test->verify(); 583 #endif 584 return test; 585 } 586 587 }; 588 589 590 // An interface for accessing/manipulating native set_metadata imm, reg instructions. 591 // (used to manipulate inlined data references, etc.) 592 // set_metadata imm, reg 593 // == sethi %hi22(imm), reg; nop; add reg, %lo10(imm), reg 594 // 595 // Note that it is identical to NativeMovConstReg with the exception of a nop between the 596 // sethi and the add. The nop is required to be in the delay slot of the call instruction 597 // which overwrites the sethi during patching. 598 class NativeMovConstRegPatching; 599 inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address);class NativeMovConstRegPatching: public NativeInstruction { 600 public: 601 enum Sparc_specific_constants { 602 sethi_offset = 0, 603 nop_offset = 7 * BytesPerInstWord, 604 add_offset = nop_offset + BytesPerInstWord, 605 instruction_size = add_offset + BytesPerInstWord 606 }; 607 608 address instruction_address() const { return addr_at(0); } 609 address next_instruction_address() const { return addr_at(instruction_size); } 610 611 // (The [set_]data accessor respects oop_type relocs also.) 612 int data() const; 613 void set_data(int x); 614 615 // report the destination register 616 Register destination() { return inv_rd(long_at(sethi_offset)); } 617 618 void verify(); 619 void print(); 620 621 // unit test stuff 622 static void test(); 623 624 // Creation 625 friend inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) { 626 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)address; 627 #ifdef ASSERT 628 test->verify(); 629 #endif 630 return test; 631 } 632 633 634 friend NativeMovConstRegPatching* nativeMovConstRegPatching_before(address address) { 635 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_size); 636 #ifdef ASSERT 637 test->verify(); 638 #endif 639 return test; 640 } 641 642 }; 643 644 645 // An interface for accessing/manipulating native memory ops 646 // ld* [reg + offset], reg 647 // st* reg, [reg + offset] 648 // sethi %hi(imm), reg; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2 649 // sethi %hi(imm), reg; add reg, %lo(imm), reg; st* reg2, [reg1 + reg] 650 // Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x} 651 // 652 class NativeMovRegMem; 653 inline NativeMovRegMem* nativeMovRegMem_at (address address); 654 class NativeMovRegMem: public NativeInstruction { 655 public: 656 enum Sparc_specific_constants { 657 op3_mask_ld = 1 << Assembler::lduw_op3 | 658 1 << Assembler::ldub_op3 | 659 1 << Assembler::lduh_op3 | 660 1 << Assembler::ldd_op3 | 661 1 << Assembler::ldsw_op3 | 662 1 << Assembler::ldsb_op3 | 663 1 << Assembler::ldsh_op3 | 664 1 << Assembler::ldx_op3, 665 op3_mask_st = 1 << Assembler::stw_op3 | 666 1 << Assembler::stb_op3 | 667 1 << Assembler::sth_op3 | 668 1 << Assembler::std_op3 | 669 1 << Assembler::stx_op3, 670 op3_ldst_int_limit = Assembler::ldf_op3, 671 op3_mask_ldf = 1 << (Assembler::ldf_op3 - op3_ldst_int_limit) | 672 1 << (Assembler::lddf_op3 - op3_ldst_int_limit), 673 op3_mask_stf = 1 << (Assembler::stf_op3 - op3_ldst_int_limit) | 674 1 << (Assembler::stdf_op3 - op3_ldst_int_limit), 675 676 offset_width = 13, 677 sethi_offset = 0, 678 add_offset = 7 * BytesPerInstWord, 679 ldst_offset = add_offset + BytesPerInstWord 680 }; 681 bool is_immediate() const { 682 // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset] 683 int i0 = long_at(0); 684 return (is_op(i0, Assembler::ldst_op)); 685 } 686 687 address instruction_address() const { return addr_at(0); } 688 address next_instruction_address() const { 689 return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord)); 690 } 691 intptr_t offset() const { 692 return is_immediate()? inv_simm(long_at(0), offset_width) : 693 nativeMovConstReg_at(addr_at(0))->data(); 694 } 695 void set_offset(intptr_t x) { 696 if (is_immediate()) { 697 guarantee(fits_in_simm(x, offset_width), "data block offset overflow"); 698 set_long_at(0, set_simm(long_at(0), x, offset_width)); 699 } else 700 nativeMovConstReg_at(addr_at(0))->set_data(x); 701 } 702 703 void add_offset_in_bytes(intptr_t radd_offset) { 704 set_offset (offset() + radd_offset); 705 } 706 707 void copy_instruction_to(address new_instruction_address); 708 709 void verify(); 710 void print (); 711 712 // unit test stuff 713 static void test(); 714 715 private: 716 friend inline NativeMovRegMem* nativeMovRegMem_at (address address) { 717 NativeMovRegMem* test = (NativeMovRegMem*)address; 718 #ifdef ASSERT 719 test->verify(); 720 #endif 721 return test; 722 } 723 }; 724 725 726 // An interface for accessing/manipulating native jumps 727 // jump_to addr 728 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), G0 ; <delay> 729 // jumpl_to addr, lreg 730 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), lreg ; <delay> 731 class NativeJump; 732 inline NativeJump* nativeJump_at(address address); 733 class NativeJump: public NativeInstruction { 734 private: 735 void guarantee_displacement(int disp, int width) { 736 guarantee(fits_in_simm(disp, width + 2), "branch displacement overflow"); 737 } 738 739 public: 740 enum Sparc_specific_constants { 741 sethi_offset = 0, 742 jmpl_offset = 7 * BytesPerInstWord, 743 instruction_size = 9 * BytesPerInstWord // includes delay slot 744 }; 745 746 address instruction_address() const { return addr_at(0); } 747 address next_instruction_address() const { return addr_at(instruction_size); } 748 749 address jump_destination() const { 750 return (address) data64(instruction_address(), long_at(jmpl_offset)); 751 } 752 void set_jump_destination(address dest) { 753 set_data64_sethi( instruction_address(), (intptr_t)dest); 754 set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); 755 } 756 757 // Creation 758 friend inline NativeJump* nativeJump_at(address address) { 759 NativeJump* jump = (NativeJump*)address; 760 #ifdef ASSERT 761 jump->verify(); 762 #endif 763 return jump; 764 } 765 766 void verify(); 767 void print(); 768 769 // Unit testing stuff 770 static void test(); 771 772 // Insertion of native jump instruction 773 static void insert(address code_pos, address entry); 774 // MT-safe insertion of native jump at verified method entry 775 static void check_verified_entry_alignment(address entry, address verified_entry) { 776 // nothing to do for sparc. 777 } 778 static void patch_verified_entry(address entry, address verified_entry, address dest); 779 }; 780 781 782 783 // Despite the name, handles only simple branches. 784 class NativeGeneralJump; 785 inline NativeGeneralJump* nativeGeneralJump_at(address address); 786 class NativeGeneralJump: public NativeInstruction { 787 public: 788 enum Sparc_specific_constants { 789 instruction_size = 8 790 }; 791 792 address instruction_address() const { return addr_at(0); } 793 address jump_destination() const { return addr_at(0) + branch_destination_offset(long_at(0)); } 794 void set_jump_destination(address dest) { 795 int patched_instr = patch_branch_destination_offset(dest - addr_at(0), long_at(0)); 796 set_long_at(0, patched_instr); 797 } 798 NativeInstruction *delay_slot_instr() { return nativeInstruction_at(addr_at(4));} 799 void fill_delay_slot(int instr) { set_long_at(4, instr);} 800 Assembler::Condition condition() { 801 int x = long_at(0); 802 return (Assembler::Condition) Assembler::inv_cond(x); 803 } 804 805 // Creation 806 friend inline NativeGeneralJump* nativeGeneralJump_at(address address) { 807 NativeGeneralJump* jump = (NativeGeneralJump*)(address); 808 #ifdef ASSERT 809 jump->verify(); 810 #endif 811 return jump; 812 } 813 814 // Insertion of native general jump instruction 815 static void insert_unconditional(address code_pos, address entry); 816 static void replace_mt_safe(address instr_addr, address code_buffer); 817 818 void verify(); 819 }; 820 821 822 class NativeIllegalInstruction: public NativeInstruction { 823 public: 824 enum Sparc_specific_constants { 825 instruction_size = 4 826 }; 827 828 // Insert illegal opcode as specific address 829 static void insert(address code_pos); 830 }; 831 832 #endif // CPU_SPARC_VM_NATIVEINST_SPARC_HPP