1 /*
   2  * Copyright (c) 1997, 2011, 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_X86_VM_NATIVEINST_X86_HPP
  26 #define CPU_X86_VM_NATIVEINST_X86_HPP
  27 
  28 #include "asm/assembler.hpp"
  29 #include "memory/allocation.hpp"
  30 #include "runtime/icache.hpp"
  31 #include "runtime/os.hpp"
  32 #include "utilities/top.hpp"
  33 
  34 // We have interfaces for the following instructions:
  35 // - NativeInstruction
  36 // - - NativeCall
  37 // - - NativeMovConstReg
  38 // - - NativeMovConstRegPatching
  39 // - - NativeMovRegMem
  40 // - - NativeMovRegMemPatching
  41 // - - NativeJump
  42 // - - NativeIllegalOpCode
  43 // - - NativeGeneralJump
  44 // - - NativeReturn
  45 // - - NativeReturnX (return with argument)
  46 // - - NativePushConst
  47 // - - NativeTstRegMem
  48 
  49 // The base class for different kinds of native instruction abstractions.
  50 // Provides the primitive operations to manipulate code relative to this.
  51 
  52 class NativeInstruction VALUE_OBJ_CLASS_SPEC {
  53   friend class Relocation;
  54 
  55  public:
  56   enum Intel_specific_constants {
  57     nop_instruction_code        = 0x90,
  58     nop_instruction_size        =    1
  59   };
  60 
  61   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
  62   inline bool is_call();

  63   inline bool is_illegal();
  64   inline bool is_return();
  65   inline bool is_jump();
  66   inline bool is_cond_jump();
  67   inline bool is_safepoint_poll();
  68   inline bool is_mov_literal64();
  69 
  70  protected:
  71   address addr_at(int offset) const    { return address(this) + offset; }
  72 
  73   s_char sbyte_at(int offset) const    { return *(s_char*) addr_at(offset); }
  74   u_char ubyte_at(int offset) const    { return *(u_char*) addr_at(offset); }
  75 
  76   jint int_at(int offset) const         { return *(jint*) addr_at(offset); }
  77 
  78   intptr_t ptr_at(int offset) const    { return *(intptr_t*) addr_at(offset); }
  79 
  80   oop  oop_at (int offset) const       { return *(oop*) addr_at(offset); }
  81 
  82 
  83   void set_char_at(int offset, char c)        { *addr_at(offset) = (u_char)c; wrote(offset); }
  84   void set_int_at(int offset, jint  i)        { *(jint*)addr_at(offset) = i;  wrote(offset); }
  85   void set_ptr_at (int offset, intptr_t  ptr) { *(intptr_t*) addr_at(offset) = ptr;  wrote(offset); }
  86   void set_oop_at (int offset, oop  o)        { *(oop*) addr_at(offset) = o;  wrote(offset); }
  87 
  88   // This doesn't really do anything on Intel, but it is the place where
  89   // cache invalidation belongs, generically:
  90   void wrote(int offset);
  91 
  92  public:
  93 
  94   // unit test stuff
  95   static void test() {}                 // override for testing
  96 
  97   inline friend NativeInstruction* nativeInstruction_at(address address);
  98 };
  99 
 100 inline NativeInstruction* nativeInstruction_at(address address) {
 101   NativeInstruction* inst = (NativeInstruction*)address;
 102 #ifdef ASSERT
 103   //inst->verify();
 104 #endif
 105   return inst;
 106 }
 107 
 108 inline NativeCall* nativeCall_at(address address);
 109 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
 110 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
 111 
 112 class NativeCall: public NativeInstruction {
 113  public:
 114   enum Intel_specific_constants {
 115     instruction_code            = 0xE8,
 116     instruction_size            =    5,
 117     instruction_offset          =    0,
 118     displacement_offset         =    1,
 119     return_address_offset       =    5
 120   };
 121 
 122   enum { cache_line_size = BytesPerWord };  // conservative estimate!
 123 
 124   address instruction_address() const       { return addr_at(instruction_offset); }
 125   address next_instruction_address() const  { return addr_at(return_address_offset); }
 126   int   displacement() const                { return (jint) int_at(displacement_offset); }
 127   address displacement_address() const      { return addr_at(displacement_offset); }
 128   address return_address() const            { return addr_at(return_address_offset); }
 129   address destination() const;
 130   void  set_destination(address dest)       {
 131 #ifdef AMD64
 132     assert((labs((intptr_t) dest - (intptr_t) return_address())  &
 133             0xFFFFFFFF00000000) == 0,
 134            "must be 32bit offset");
 135 #endif // AMD64
 136     set_int_at(displacement_offset, dest - return_address());
 137   }
 138   void  set_destination_mt_safe(address dest);
 139 
 140   void  verify_alignment() { assert((intptr_t)addr_at(displacement_offset) % BytesPerInt == 0, "must be aligned"); }
 141   void  verify();
 142   void  print();
 143 
 144   // Creation
 145   inline friend NativeCall* nativeCall_at(address address);
 146   inline friend NativeCall* nativeCall_before(address return_address);
 147 
 148   static bool is_call_at(address instr) {
 149     return ((*instr) & 0xFF) == NativeCall::instruction_code;
 150   }
 151 
 152   static bool is_call_before(address return_address) {
 153     return is_call_at(return_address - NativeCall::return_address_offset);
 154   }
 155 
 156   static bool is_call_to(address instr, address target) {
 157     return nativeInstruction_at(instr)->is_call() &&
 158       nativeCall_at(instr)->destination() == target;
 159   }
 160 
 161   // MT-safe patching of a call instruction.
 162   static void insert(address code_pos, address entry);
 163 
 164   static void replace_mt_safe(address instr_addr, address code_buffer);
 165 };
 166 
 167 inline NativeCall* nativeCall_at(address address) {
 168   NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
 169 #ifdef ASSERT
 170   call->verify();
 171 #endif
 172   return call;
 173 }
 174 
 175 inline NativeCall* nativeCall_before(address return_address) {
 176   NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
 177 #ifdef ASSERT
 178   call->verify();
 179 #endif
 180   return call;
 181 }
 182 


















 183 // An interface for accessing/manipulating native mov reg, imm32 instructions.
 184 // (used to manipulate inlined 32bit data dll calls, etc.)
 185 class NativeMovConstReg: public NativeInstruction {
 186 #ifdef AMD64
 187   static const bool has_rex = true;
 188   static const int rex_size = 1;
 189 #else
 190   static const bool has_rex = false;
 191   static const int rex_size = 0;
 192 #endif // AMD64
 193  public:
 194   enum Intel_specific_constants {
 195     instruction_code            = 0xB8,
 196     instruction_size            =    1 + rex_size + wordSize,
 197     instruction_offset          =    0,
 198     data_offset                 =    1 + rex_size,
 199     next_instruction_offset     =    instruction_size,
 200     register_mask               = 0x07
 201   };
 202 
 203   address instruction_address() const       { return addr_at(instruction_offset); }
 204   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
 205   intptr_t data() const                     { return ptr_at(data_offset); }
 206   void  set_data(intptr_t x)                { set_ptr_at(data_offset, x); }
 207 
 208   void  verify();
 209   void  print();
 210 
 211   // unit test stuff
 212   static void test() {}
 213 
 214   // Creation
 215   inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
 216   inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
 217 };
 218 
 219 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
 220   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
 221 #ifdef ASSERT
 222   test->verify();
 223 #endif
 224   return test;
 225 }
 226 
 227 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
 228   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
 229 #ifdef ASSERT
 230   test->verify();
 231 #endif
 232   return test;
 233 }
 234 
 235 class NativeMovConstRegPatching: public NativeMovConstReg {
 236  private:
 237     friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
 238     NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
 239     #ifdef ASSERT
 240       test->verify();
 241     #endif
 242     return test;
 243   }
 244 };
 245 
 246 // An interface for accessing/manipulating native moves of the form:
 247 //      mov[b/w/l/q] [reg + offset], reg   (instruction_code_reg2mem)
 248 //      mov[b/w/l/q] reg, [reg+offset]     (instruction_code_mem2reg
 249 //      mov[s/z]x[w/b/q] [reg + offset], reg
 250 //      fld_s  [reg+offset]
 251 //      fld_d  [reg+offset]
 252 //      fstp_s [reg + offset]
 253 //      fstp_d [reg + offset]
 254 //      mov_literal64  scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
 255 //
 256 // Warning: These routines must be able to handle any instruction sequences
 257 // that are generated as a result of the load/store byte,word,long
 258 // macros.  For example: The load_unsigned_byte instruction generates
 259 // an xor reg,reg inst prior to generating the movb instruction.  This
 260 // class must skip the xor instruction.
 261 
 262 class NativeMovRegMem: public NativeInstruction {
 263  public:
 264   enum Intel_specific_constants {
 265     instruction_prefix_wide_lo          = Assembler::REX,
 266     instruction_prefix_wide_hi          = Assembler::REX_WRXB,
 267     instruction_code_xor                = 0x33,
 268     instruction_extended_prefix         = 0x0F,
 269     instruction_code_mem2reg_movslq     = 0x63,
 270     instruction_code_mem2reg_movzxb     = 0xB6,
 271     instruction_code_mem2reg_movsxb     = 0xBE,
 272     instruction_code_mem2reg_movzxw     = 0xB7,
 273     instruction_code_mem2reg_movsxw     = 0xBF,
 274     instruction_operandsize_prefix      = 0x66,
 275     instruction_code_reg2mem            = 0x89,
 276     instruction_code_mem2reg            = 0x8b,
 277     instruction_code_reg2memb           = 0x88,
 278     instruction_code_mem2regb           = 0x8a,
 279     instruction_code_float_s            = 0xd9,
 280     instruction_code_float_d            = 0xdd,
 281     instruction_code_long_volatile      = 0xdf,
 282     instruction_code_xmm_ss_prefix      = 0xf3,
 283     instruction_code_xmm_sd_prefix      = 0xf2,
 284     instruction_code_xmm_code           = 0x0f,
 285     instruction_code_xmm_load           = 0x10,
 286     instruction_code_xmm_store          = 0x11,
 287     instruction_code_xmm_lpd            = 0x12,
 288 
 289     instruction_VEX_prefix_2bytes       = Assembler::VEX_2bytes,
 290     instruction_VEX_prefix_3bytes       = Assembler::VEX_3bytes,
 291 
 292     instruction_size                    = 4,
 293     instruction_offset                  = 0,
 294     data_offset                         = 2,
 295     next_instruction_offset             = 4
 296   };
 297 
 298   // helper
 299   int instruction_start() const;
 300 
 301   address instruction_address() const;
 302 
 303   address next_instruction_address() const;
 304 
 305   int   offset() const;
 306 
 307   void  set_offset(int x);
 308 
 309   void  add_offset_in_bytes(int add_offset)     { set_offset ( ( offset() + add_offset ) ); }
 310 
 311   void verify();
 312   void print ();
 313 
 314   // unit test stuff
 315   static void test() {}
 316 
 317  private:
 318   inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
 319 };
 320 
 321 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
 322   NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
 323 #ifdef ASSERT
 324   test->verify();
 325 #endif
 326   return test;
 327 }
 328 
 329 
 330 // An interface for accessing/manipulating native leal instruction of form:
 331 //        leal reg, [reg + offset]
 332 
 333 class NativeLoadAddress: public NativeMovRegMem {
 334 #ifdef AMD64
 335   static const bool has_rex = true;
 336   static const int rex_size = 1;
 337 #else
 338   static const bool has_rex = false;
 339   static const int rex_size = 0;
 340 #endif // AMD64
 341  public:
 342   enum Intel_specific_constants {
 343     instruction_prefix_wide             = Assembler::REX_W,
 344     instruction_prefix_wide_extended    = Assembler::REX_WB,
 345     lea_instruction_code                = 0x8D,
 346     mov64_instruction_code              = 0xB8
 347   };
 348 
 349   void verify();
 350   void print ();
 351 
 352   // unit test stuff
 353   static void test() {}
 354 
 355  private:
 356   friend NativeLoadAddress* nativeLoadAddress_at (address address) {
 357     NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
 358     #ifdef ASSERT
 359       test->verify();
 360     #endif
 361     return test;
 362   }
 363 };
 364 
 365 // jump rel32off
 366 
 367 class NativeJump: public NativeInstruction {
 368  public:
 369   enum Intel_specific_constants {
 370     instruction_code            = 0xe9,
 371     instruction_size            =    5,
 372     instruction_offset          =    0,
 373     data_offset                 =    1,
 374     next_instruction_offset     =    5
 375   };
 376 
 377   address instruction_address() const       { return addr_at(instruction_offset); }
 378   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
 379   address jump_destination() const          {
 380      address dest = (int_at(data_offset)+next_instruction_address());
 381      // 32bit used to encode unresolved jmp as jmp -1
 382      // 64bit can't produce this so it used jump to self.
 383      // Now 32bit and 64bit use jump to self as the unresolved address
 384      // which the inline cache code (and relocs) know about
 385 
 386      // return -1 if jump to self
 387     dest = (dest == (address) this) ? (address) -1 : dest;
 388     return dest;
 389   }
 390 
 391   void  set_jump_destination(address dest)  {
 392     intptr_t val = dest - next_instruction_address();
 393     if (dest == (address) -1) {
 394       val = -5; // jump to self
 395     }
 396 #ifdef AMD64
 397     assert((labs(val)  & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
 398 #endif // AMD64
 399     set_int_at(data_offset, (jint)val);
 400   }
 401 
 402   // Creation
 403   inline friend NativeJump* nativeJump_at(address address);
 404 
 405   void verify();
 406 
 407   // Unit testing stuff
 408   static void test() {}
 409 
 410   // Insertion of native jump instruction
 411   static void insert(address code_pos, address entry);
 412   // MT-safe insertion of native jump at verified method entry
 413   static void check_verified_entry_alignment(address entry, address verified_entry);
 414   static void patch_verified_entry(address entry, address verified_entry, address dest);
 415 };
 416 
 417 inline NativeJump* nativeJump_at(address address) {
 418   NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
 419 #ifdef ASSERT
 420   jump->verify();
 421 #endif
 422   return jump;
 423 }
 424 
 425 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional
 426 class NativeGeneralJump: public NativeInstruction {
 427  public:
 428   enum Intel_specific_constants {
 429     // Constants does not apply, since the lengths and offsets depends on the actual jump
 430     // used
 431     // Instruction codes:
 432     //   Unconditional jumps: 0xE9    (rel32off), 0xEB (rel8off)
 433     //   Conditional jumps:   0x0F8x  (rel32off), 0x7x (rel8off)
 434     unconditional_long_jump  = 0xe9,
 435     unconditional_short_jump = 0xeb,
 436     instruction_size = 5
 437   };
 438 
 439   address instruction_address() const       { return addr_at(0); }
 440   address jump_destination()    const;
 441 
 442   // Creation
 443   inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
 444 
 445   // Insertion of native general jump instruction
 446   static void insert_unconditional(address code_pos, address entry);
 447   static void replace_mt_safe(address instr_addr, address code_buffer);
 448 
 449   void verify();
 450 };
 451 
 452 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
 453   NativeGeneralJump* jump = (NativeGeneralJump*)(address);
 454   debug_only(jump->verify();)
 455   return jump;
 456 }
 457 
 458 class NativePopReg : public NativeInstruction {
 459  public:
 460   enum Intel_specific_constants {
 461     instruction_code            = 0x58,
 462     instruction_size            =    1,
 463     instruction_offset          =    0,
 464     data_offset                 =    1,
 465     next_instruction_offset     =    1
 466   };
 467 
 468   // Insert a pop instruction
 469   static void insert(address code_pos, Register reg);
 470 };
 471 
 472 
 473 class NativeIllegalInstruction: public NativeInstruction {
 474  public:
 475   enum Intel_specific_constants {
 476     instruction_code            = 0x0B0F,    // Real byte order is: 0x0F, 0x0B
 477     instruction_size            =    2,
 478     instruction_offset          =    0,
 479     next_instruction_offset     =    2
 480   };
 481 
 482   // Insert illegal opcode as specific address
 483   static void insert(address code_pos);
 484 };
 485 
 486 // return instruction that does not pop values of the stack
 487 class NativeReturn: public NativeInstruction {
 488  public:
 489   enum Intel_specific_constants {
 490     instruction_code            = 0xC3,
 491     instruction_size            =    1,
 492     instruction_offset          =    0,
 493     next_instruction_offset     =    1
 494   };
 495 };
 496 
 497 // return instruction that does pop values of the stack
 498 class NativeReturnX: public NativeInstruction {
 499  public:
 500   enum Intel_specific_constants {
 501     instruction_code            = 0xC2,
 502     instruction_size            =    2,
 503     instruction_offset          =    0,
 504     next_instruction_offset     =    2
 505   };
 506 };
 507 
 508 // Simple test vs memory
 509 class NativeTstRegMem: public NativeInstruction {
 510  public:
 511   enum Intel_specific_constants {
 512     instruction_rex_prefix_mask = 0xF0,
 513     instruction_rex_prefix      = Assembler::REX,
 514     instruction_code_memXregl   = 0x85,
 515     modrm_mask                  = 0x38, // select reg from the ModRM byte
 516     modrm_reg                   = 0x00  // rax
 517   };
 518 };
 519 
 520 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
 521 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }



 522 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
 523                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
 524 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
 525                                                           ubyte_at(0) == 0xEB; /* short jump */ }
 526 inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
 527                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
 528 inline bool NativeInstruction::is_safepoint_poll() {
 529 #ifdef AMD64
 530   if (Assembler::is_polling_page_far()) {







 531     // two cases, depending on the choice of the base register in the address.
 532     if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
 533          ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
 534          (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
 535         ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
 536         (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {

 537       return true;
 538     } else {
 539       return false;
 540     }
 541   } else {
 542     if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
 543         ubyte_at(1) == 0x05) { // 00 rax 101
 544       address fault = addr_at(6) + int_at(2);
 545       return os::is_poll_address(fault);
 546     } else {
 547       return false;
 548     }
 549   }
 550 #else
 551   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
 552            ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
 553            (ubyte_at(1)&0xC7) == 0x05 && /* Mod R/M == disp32 */
 554            (os::is_poll_address((address)int_at(2)));
 555 #endif // AMD64
 556 }
 557 
 558 inline bool NativeInstruction::is_mov_literal64() {
 559 #ifdef AMD64
 560   return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
 561           (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
 562 #else
 563   return false;
 564 #endif // AMD64
 565 }
 566 
 567 #endif // CPU_X86_VM_NATIVEINST_X86_HPP
--- EOF ---