1 /* 2 * Copyright (c) 1997, 2019, 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_NATIVEINST_SPARC_HPP 26 #define CPU_SPARC_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 class NativeCall; 315 316 inline NativeCall* nativeCall_at(address instr); 317 inline NativeCall* nativeCall_overwriting_at(address instr, 318 address destination = NULL); 319 inline NativeCall* nativeCall_before(address return_address); 320 class NativeCall: public NativeInstruction { 321 public: 322 enum Sparc_specific_constants { 323 instruction_size = 8, 324 return_address_offset = 8, 325 call_displacement_width = 30, 326 displacement_offset = 0, 327 instruction_offset = 0 328 }; 329 address instruction_address() const { return addr_at(0); } 330 address next_instruction_address() const { return addr_at(instruction_size); } 331 address return_address() const { return addr_at(return_address_offset); } 332 333 address destination() const { return inv_wdisp(long_at(0), call_displacement_width) + instruction_address(); } 334 address displacement_address() const { return addr_at(displacement_offset); } 335 void set_destination(address dest) { set_long_at(0, set_wdisp(long_at(0), dest - instruction_address(), call_displacement_width)); } 336 void set_destination_mt_safe(address dest); 337 338 void verify_alignment() {} // do nothing on sparc 339 void verify(); 340 void print(); 341 342 // unit test stuff 343 static void test(); 344 345 // Creation 346 friend inline NativeCall* nativeCall_at(address instr); 347 friend NativeCall* nativeCall_overwriting_at(address instr, address destination) { 348 // insert a "blank" call: 349 NativeCall* call = (NativeCall*)instr; 350 call->set_long_at(0 * BytesPerInstWord, call_instruction(destination, instr)); 351 call->set_long_at(1 * BytesPerInstWord, nop_instruction()); 352 assert(call->addr_at(2 * BytesPerInstWord) - instr == instruction_size, "instruction size"); 353 // check its structure now: 354 assert(nativeCall_at(instr)->destination() == destination, "correct call destination"); 355 return call; 356 } 357 358 friend inline NativeCall* nativeCall_before(address return_address) { 359 NativeCall* call = (NativeCall*)(return_address - return_address_offset); 360 #ifdef ASSERT 361 call->verify(); 362 #endif 363 return call; 364 } 365 366 static bool is_call_at(address instr) { 367 return nativeInstruction_at(instr)->is_call(); 368 } 369 370 static bool is_call_before(address instr) { 371 return nativeInstruction_at(instr - return_address_offset)->is_call(); 372 } 373 374 static bool is_call_to(address instr, address target) { 375 return nativeInstruction_at(instr)->is_call() && 376 nativeCall_at(instr)->destination() == target; 377 } 378 379 // MT-safe patching of a call instruction. 380 static void insert(address code_pos, address entry) { 381 (void)nativeCall_overwriting_at(code_pos, entry); 382 } 383 384 static void replace_mt_safe(address instr_addr, address code_buffer); 385 }; 386 inline NativeCall* nativeCall_at(address instr) { 387 NativeCall* call = (NativeCall*)instr; 388 #ifdef ASSERT 389 call->verify(); 390 #endif 391 return call; 392 } 393 394 class NativeCallReg: public NativeInstruction { 395 public: 396 enum Sparc_specific_constants { 397 instruction_size = 8, 398 return_address_offset = 8, 399 instruction_offset = 0 400 }; 401 402 address next_instruction_address() const { 403 return addr_at(instruction_size); 404 } 405 }; 406 407 // The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere 408 // instructions in the sparcv9 vm. Used to call native methods which may be loaded 409 // anywhere in the address space, possibly out of reach of a call instruction. 410 411 // The format of this extended-range call is: 412 // jumpl_to addr, lreg 413 // == sethi %hi54(addr), O7 ; jumpl O7, %lo10(addr), O7 ; <delay> 414 // That is, it is essentially the same as a NativeJump. 415 class NativeFarCall; 416 inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL); 417 inline NativeFarCall* nativeFarCall_at(address instr); 418 class NativeFarCall: public NativeInstruction { 419 public: 420 enum Sparc_specific_constants { 421 // instruction_size includes the delay slot instruction. 422 instruction_size = 9 * BytesPerInstWord, 423 return_address_offset = 9 * BytesPerInstWord, 424 jmpl_offset = 7 * BytesPerInstWord, 425 displacement_offset = 0, 426 instruction_offset = 0 427 }; 428 address instruction_address() const { return addr_at(0); } 429 address next_instruction_address() const { return addr_at(instruction_size); } 430 address return_address() const { return addr_at(return_address_offset); } 431 432 address destination() const { 433 return (address) data64(addr_at(0), long_at(jmpl_offset)); 434 } 435 address displacement_address() const { return addr_at(displacement_offset); } 436 void set_destination(address dest); 437 438 bool destination_is_compiled_verified_entry_point(); 439 440 void verify(); 441 void print(); 442 443 // unit test stuff 444 static void test(); 445 446 // Creation 447 friend inline NativeFarCall* nativeFarCall_at(address instr) { 448 NativeFarCall* call = (NativeFarCall*)instr; 449 #ifdef ASSERT 450 call->verify(); 451 #endif 452 return call; 453 } 454 455 friend inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination) { 456 Unimplemented(); 457 NativeFarCall* call = (NativeFarCall*)instr; 458 return call; 459 } 460 461 friend NativeFarCall* nativeFarCall_before(address return_address) { 462 NativeFarCall* call = (NativeFarCall*)(return_address - return_address_offset); 463 #ifdef ASSERT 464 call->verify(); 465 #endif 466 return call; 467 } 468 469 static bool is_call_at(address instr); 470 471 // MT-safe patching of a call instruction. 472 static void insert(address code_pos, address entry) { 473 (void)nativeFarCall_overwriting_at(code_pos, entry); 474 } 475 static void replace_mt_safe(address instr_addr, address code_buffer); 476 }; 477 478 479 // An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions 480 // (used to manipulate inlined data references, etc.) 481 // set_metadata imm, reg 482 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg 483 class NativeMovConstReg32; 484 inline NativeMovConstReg32* nativeMovConstReg32_at(address address); 485 class NativeMovConstReg32: public NativeInstruction { 486 public: 487 enum Sparc_specific_constants { 488 sethi_offset = 0, 489 add_offset = 4, 490 instruction_size = 8 491 }; 492 493 address instruction_address() const { return addr_at(0); } 494 address next_instruction_address() const { return addr_at(instruction_size); } 495 496 // (The [set_]data accessor respects oop_type relocs also.) 497 intptr_t data() const; 498 void set_data(intptr_t x); 499 500 // report the destination register 501 Register destination() { return inv_rd(long_at(sethi_offset)); } 502 503 void verify(); 504 void print(); 505 506 // unit test stuff 507 static void test(); 508 509 // Creation 510 friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) { 511 NativeMovConstReg32* test = (NativeMovConstReg32*)address; 512 #ifdef ASSERT 513 test->verify(); 514 #endif 515 return test; 516 } 517 }; 518 519 // An interface for accessing/manipulating native set_metadata imm, reg instructions. 520 // (used to manipulate inlined data references, etc.) 521 // set_metadata imm, reg 522 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg 523 class NativeMovConstReg; 524 inline NativeMovConstReg* nativeMovConstReg_at(address address); 525 class NativeMovConstReg: public NativeInstruction { 526 public: 527 enum Sparc_specific_constants { 528 sethi_offset = 0, 529 add_offset = 7 * BytesPerInstWord, 530 instruction_size = 8 * BytesPerInstWord 531 }; 532 533 address instruction_address() const { return addr_at(0); } 534 address next_instruction_address() const { return addr_at(instruction_size); } 535 536 // (The [set_]data accessor respects oop_type relocs also.) 537 intptr_t data() const; 538 void set_data(intptr_t x); 539 540 // report the destination register 541 Register destination() { return inv_rd(long_at(sethi_offset)); } 542 543 void verify(); 544 void print(); 545 546 // unit test stuff 547 static void test(); 548 549 // Creation 550 friend inline NativeMovConstReg* nativeMovConstReg_at(address address) { 551 NativeMovConstReg* test = (NativeMovConstReg*)address; 552 #ifdef ASSERT 553 test->verify(); 554 #endif 555 return test; 556 } 557 558 559 friend NativeMovConstReg* nativeMovConstReg_before(address address) { 560 NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size); 561 #ifdef ASSERT 562 test->verify(); 563 #endif 564 return test; 565 } 566 567 }; 568 569 570 // An interface for accessing/manipulating native set_metadata imm, reg instructions. 571 // (used to manipulate inlined data references, etc.) 572 // set_metadata imm, reg 573 // == sethi %hi22(imm), reg; nop; add reg, %lo10(imm), reg 574 // 575 // Note that it is identical to NativeMovConstReg with the exception of a nop between the 576 // sethi and the add. The nop is required to be in the delay slot of the call instruction 577 // which overwrites the sethi during patching. 578 class NativeMovConstRegPatching; 579 inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address); 580 class NativeMovConstRegPatching: public NativeInstruction { 581 public: 582 enum Sparc_specific_constants { 583 sethi_offset = 0, 584 nop_offset = 7 * BytesPerInstWord, 585 add_offset = nop_offset + BytesPerInstWord, 586 instruction_size = add_offset + BytesPerInstWord 587 }; 588 589 address instruction_address() const { return addr_at(0); } 590 address next_instruction_address() const { return addr_at(instruction_size); } 591 592 // (The [set_]data accessor respects oop_type relocs also.) 593 int data() const; 594 void set_data(int x); 595 596 // report the destination register 597 Register destination() { return inv_rd(long_at(sethi_offset)); } 598 599 void verify(); 600 void print(); 601 602 // unit test stuff 603 static void test(); 604 605 // Creation 606 friend inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) { 607 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)address; 608 #ifdef ASSERT 609 test->verify(); 610 #endif 611 return test; 612 } 613 614 615 friend NativeMovConstRegPatching* nativeMovConstRegPatching_before(address address) { 616 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_size); 617 #ifdef ASSERT 618 test->verify(); 619 #endif 620 return test; 621 } 622 623 }; 624 625 626 // An interface for accessing/manipulating native memory ops 627 // ld* [reg + offset], reg 628 // st* reg, [reg + offset] 629 // sethi %hi(imm), reg; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2 630 // sethi %hi(imm), reg; add reg, %lo(imm), reg; st* reg2, [reg1 + reg] 631 // Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x} 632 // 633 class NativeMovRegMem; 634 inline NativeMovRegMem* nativeMovRegMem_at (address address); 635 class NativeMovRegMem: public NativeInstruction { 636 public: 637 enum Sparc_specific_constants { 638 op3_mask_ld = 1 << Assembler::lduw_op3 | 639 1 << Assembler::ldub_op3 | 640 1 << Assembler::lduh_op3 | 641 1 << Assembler::ldd_op3 | 642 1 << Assembler::ldsw_op3 | 643 1 << Assembler::ldsb_op3 | 644 1 << Assembler::ldsh_op3 | 645 1 << Assembler::ldx_op3, 646 op3_mask_st = 1 << Assembler::stw_op3 | 647 1 << Assembler::stb_op3 | 648 1 << Assembler::sth_op3 | 649 1 << Assembler::std_op3 | 650 1 << Assembler::stx_op3, 651 op3_ldst_int_limit = Assembler::ldf_op3, 652 op3_mask_ldf = 1 << (Assembler::ldf_op3 - op3_ldst_int_limit) | 653 1 << (Assembler::lddf_op3 - op3_ldst_int_limit), 654 op3_mask_stf = 1 << (Assembler::stf_op3 - op3_ldst_int_limit) | 655 1 << (Assembler::stdf_op3 - op3_ldst_int_limit), 656 657 offset_width = 13, 658 sethi_offset = 0, 659 add_offset = 7 * BytesPerInstWord, 660 ldst_offset = add_offset + BytesPerInstWord 661 }; 662 bool is_immediate() const { 663 // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset] 664 int i0 = long_at(0); 665 return (is_op(i0, Assembler::ldst_op)); 666 } 667 668 address instruction_address() const { return addr_at(0); } 669 670 int num_bytes_to_end_of_patch() const { 671 return is_immediate()? BytesPerInstWord : 672 NativeMovConstReg::instruction_size; 673 } 674 675 intptr_t offset() const { 676 return is_immediate()? inv_simm(long_at(0), offset_width) : 677 nativeMovConstReg_at(addr_at(0))->data(); 678 } 679 void set_offset(intptr_t x) { 680 if (is_immediate()) { 681 guarantee(fits_in_simm(x, offset_width), "data block offset overflow"); 682 set_long_at(0, set_simm(long_at(0), x, offset_width)); 683 } else 684 nativeMovConstReg_at(addr_at(0))->set_data(x); 685 } 686 687 void add_offset_in_bytes(intptr_t radd_offset) { 688 set_offset (offset() + radd_offset); 689 } 690 691 void verify(); 692 void print (); 693 694 // unit test stuff 695 static void test(); 696 697 private: 698 friend inline NativeMovRegMem* nativeMovRegMem_at (address address) { 699 NativeMovRegMem* test = (NativeMovRegMem*)address; 700 #ifdef ASSERT 701 test->verify(); 702 #endif 703 return test; 704 } 705 }; 706 707 708 // An interface for accessing/manipulating native jumps 709 // jump_to addr 710 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), G0 ; <delay> 711 // jumpl_to addr, lreg 712 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), lreg ; <delay> 713 class NativeJump; 714 inline NativeJump* nativeJump_at(address address); 715 class NativeJump: public NativeInstruction { 716 private: 717 void guarantee_displacement(int disp, int width) { 718 guarantee(fits_in_simm(disp, width + 2), "branch displacement overflow"); 719 } 720 721 public: 722 enum Sparc_specific_constants { 723 sethi_offset = 0, 724 jmpl_offset = 7 * BytesPerInstWord, 725 instruction_size = 9 * BytesPerInstWord // includes delay slot 726 }; 727 728 address instruction_address() const { return addr_at(0); } 729 address next_instruction_address() const { return addr_at(instruction_size); } 730 731 address jump_destination() const { 732 return (address) data64(instruction_address(), long_at(jmpl_offset)); 733 } 734 void set_jump_destination(address dest) { 735 set_data64_sethi( instruction_address(), (intptr_t)dest); 736 set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); 737 } 738 739 // Creation 740 friend inline NativeJump* nativeJump_at(address address) { 741 NativeJump* jump = (NativeJump*)address; 742 #ifdef ASSERT 743 jump->verify(); 744 #endif 745 return jump; 746 } 747 748 void verify(); 749 void print(); 750 751 // Unit testing stuff 752 static void test(); 753 754 // Insertion of native jump instruction 755 static void insert(address code_pos, address entry); 756 // MT-safe insertion of native jump at verified method entry 757 static void check_verified_entry_alignment(address entry, address verified_entry) { 758 // nothing to do for sparc. 759 } 760 static void patch_verified_entry(address entry, address verified_entry, address dest); 761 }; 762 763 764 765 // Despite the name, handles only simple branches. 766 class NativeGeneralJump; 767 inline NativeGeneralJump* nativeGeneralJump_at(address address); 768 class NativeGeneralJump: public NativeInstruction { 769 public: 770 enum Sparc_specific_constants { 771 instruction_size = 8 772 }; 773 774 address instruction_address() const { return addr_at(0); } 775 address jump_destination() const { return addr_at(0) + branch_destination_offset(long_at(0)); } 776 void set_jump_destination(address dest) { 777 int patched_instr = patch_branch_destination_offset(dest - addr_at(0), long_at(0)); 778 set_long_at(0, patched_instr); 779 } 780 NativeInstruction *delay_slot_instr() { return nativeInstruction_at(addr_at(4));} 781 void fill_delay_slot(int instr) { set_long_at(4, instr);} 782 Assembler::Condition condition() { 783 int x = long_at(0); 784 return (Assembler::Condition) Assembler::inv_cond(x); 785 } 786 787 // Creation 788 friend inline NativeGeneralJump* nativeGeneralJump_at(address address) { 789 NativeGeneralJump* jump = (NativeGeneralJump*)(address); 790 #ifdef ASSERT 791 jump->verify(); 792 #endif 793 return jump; 794 } 795 796 // Insertion of native general jump instruction 797 static void insert_unconditional(address code_pos, address entry); 798 static void replace_mt_safe(address instr_addr, address code_buffer); 799 800 void verify(); 801 }; 802 803 804 class NativeIllegalInstruction: public NativeInstruction { 805 public: 806 enum Sparc_specific_constants { 807 instruction_size = 4 808 }; 809 810 // Insert illegal opcode as specific address 811 static void insert(address code_pos); 812 }; 813 814 #endif // CPU_SPARC_NATIVEINST_SPARC_HPP