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