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