1 /*
  2  * Copyright (c) 1997, 2023, 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_NATIVEINST_X86_HPP
 26 #define CPU_X86_NATIVEINST_X86_HPP
 27 
 28 #include "asm/assembler.hpp"
 29 #include "runtime/icache.hpp"
 30 #include "runtime/safepointMechanism.hpp"
 31 
 32 // We have interfaces for the following instructions:
 33 // - NativeInstruction
 34 // - - NativeCall
 35 // - - NativeMovConstReg
 36 // - - NativeMovConstRegPatching
 37 // - - NativeMovRegMem
 38 // - - NativeMovRegMemPatching
 39 // - - NativeJump
 40 // - - NativeFarJump
 41 // - - NativeIllegalOpCode
 42 // - - NativeGeneralJump
 43 // - - NativeReturn
 44 // - - NativeReturnX (return with argument)
 45 // - - NativePushConst
 46 // - - NativeTstRegMem
 47 
 48 // The base class for different kinds of native instruction abstractions.
 49 // Provides the primitive operations to manipulate code relative to this.
 50 
 51 class NativeInstruction {
 52   friend class Relocation;
 53 
 54  public:
 55   enum Intel_specific_constants {
 56     nop_instruction_code        = 0x90,
 57     nop_instruction_size        =    1
 58   };
 59 
 60   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
 61   inline bool is_call();
 62   inline bool is_call_reg();
 63   inline bool is_illegal();
 64   inline bool is_return();
 65   inline bool is_jump();
 66   inline bool is_jump_reg();
 67   inline bool is_far_jump();
 68   inline bool is_cond_jump();
 69   inline bool is_safepoint_poll();
 70   inline bool is_mov_literal64();
 71 
 72  protected:
 73   address addr_at(int offset) const    { return address(this) + offset; }
 74 
 75   s_char sbyte_at(int offset) const    { return *(s_char*) addr_at(offset); }
 76   u_char ubyte_at(int offset) const    { return *(u_char*) addr_at(offset); }
 77 
 78   jint int_at(int offset) const         { return *(jint*) addr_at(offset); }
 79 
 80   intptr_t ptr_at(int offset) const    { return *(intptr_t*) addr_at(offset); }
 81 
 82   oop  oop_at (int offset) const       { return *(oop*) addr_at(offset); }
 83 
 84 
 85   void set_char_at(int offset, u_char c)        { *addr_at(offset) = c; wrote(offset); }
 86   void set_int_at(int offset, jint  i)        { *(jint*)addr_at(offset) = i;  wrote(offset); }
 87   void set_ptr_at (int offset, intptr_t  ptr) { *(intptr_t*) addr_at(offset) = ptr;  wrote(offset); }
 88   void set_oop_at (int offset, oop  o)        { *(oop*) addr_at(offset) = o;  wrote(offset); }
 89 
 90   // This doesn't really do anything on Intel, but it is the place where
 91   // cache invalidation belongs, generically:
 92   void wrote(int offset);
 93 
 94  public:
 95 
 96   inline friend NativeInstruction* nativeInstruction_at(address address);
 97 };
 98 
 99 inline NativeInstruction* nativeInstruction_at(address address) {
100   NativeInstruction* inst = (NativeInstruction*)address;
101 #ifdef ASSERT
102   //inst->verify();
103 #endif
104   return inst;
105 }
106 
107 class NativePltCall: public NativeInstruction {
108 public:
109   enum Intel_specific_constants {
110     instruction_code           = 0xE8,
111     instruction_size           =    5,
112     instruction_offset         =    0,
113     displacement_offset        =    1,
114     return_address_offset      =    5
115   };
116   address instruction_address() const { return addr_at(instruction_offset); }
117   address next_instruction_address() const { return addr_at(return_address_offset); }
118   address displacement_address() const { return addr_at(displacement_offset); }
119   int displacement() const { return (jint) int_at(displacement_offset); }
120   address return_address() const { return addr_at(return_address_offset); }
121   address destination() const;
122   address plt_entry() const;
123   address plt_jump() const;
124   address plt_load_got() const;
125   address plt_resolve_call() const;
126   address plt_c2i_stub() const;
127   void set_stub_to_clean();
128 
129   void  reset_to_plt_resolve_call();
130   void  set_destination_mt_safe(address dest);
131 
132   void verify() const;
133 };
134 
135 inline NativePltCall* nativePltCall_at(address address) {
136   NativePltCall* call = (NativePltCall*) address;
137 #ifdef ASSERT
138   call->verify();
139 #endif
140   return call;
141 }
142 
143 inline NativePltCall* nativePltCall_before(address addr) {
144   address at = addr - NativePltCall::instruction_size;
145   return nativePltCall_at(at);
146 }
147 
148 class NativeCall;
149 inline NativeCall* nativeCall_at(address address);
150 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
151 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
152 
153 class NativeCall: public NativeInstruction {
154  public:
155   enum Intel_specific_constants {
156     instruction_code            = 0xE8,
157     instruction_size            =    5,
158     instruction_offset          =    0,
159     displacement_offset         =    1,
160     return_address_offset       =    5
161   };
162 
163   address instruction_address() const       { return addr_at(instruction_offset); }
164   address next_instruction_address() const  { return addr_at(return_address_offset); }
165   int   displacement() const                { return (jint) int_at(displacement_offset); }
166   address displacement_address() const      { return addr_at(displacement_offset); }
167   address return_address() const            { return addr_at(return_address_offset); }
168   address destination() const;
169   void  set_destination(address dest)       {
170 #ifdef AMD64
171     intptr_t disp = dest - return_address();
172     guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset: " INTPTR_FORMAT ", dest: " INTPTR_FORMAT ", ret_pc: " INTPTR_FORMAT, disp, p2i(dest), p2i(return_address()));
173 #endif // AMD64
174     set_int_at(displacement_offset, (int)(dest - return_address()));
175   }
176   // Returns whether the 4-byte displacement operand is 4-byte aligned.
177   bool  is_displacement_aligned();
178   void  set_destination_mt_safe(address dest);
179 
180   void  verify_alignment() { assert(is_displacement_aligned(), "displacement of call is not aligned"); }
181   void  verify();
182   void  print();
183 
184   // Creation
185   inline friend NativeCall* nativeCall_at(address address);
186   inline friend NativeCall* nativeCall_before(address return_address);
187 
188   static bool is_call_at(address instr) {
189     return ((*instr) & 0xFF) == NativeCall::instruction_code;
190   }
191 
192   static bool is_call_before(address return_address) {
193     return is_call_at(return_address - NativeCall::return_address_offset);
194   }
195 
196   static bool is_call_to(address instr, address target) {
197     return nativeInstruction_at(instr)->is_call() &&
198       nativeCall_at(instr)->destination() == target;
199   }
200 
201   // MT-safe patching of a call instruction.
202   static void insert(address code_pos, address entry);
203 
204   static void replace_mt_safe(address instr_addr, address code_buffer);
205 };
206 
207 inline NativeCall* nativeCall_at(address address) {
208   NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
209 #ifdef ASSERT
210   call->verify();
211 #endif
212   return call;
213 }
214 
215 inline NativeCall* nativeCall_before(address return_address) {
216   NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
217 #ifdef ASSERT
218   call->verify();
219 #endif
220   return call;
221 }
222 
223 class NativeCallReg: public NativeInstruction {
224  public:
225   enum Intel_specific_constants {
226     instruction_code            = 0xFF,
227     instruction_offset          =    0,
228     return_address_offset_norex =    2,
229     return_address_offset_rex   =    3
230   };
231 
232   int next_instruction_offset() const  {
233     if (ubyte_at(0) == NativeCallReg::instruction_code) {
234       return return_address_offset_norex;
235     } else {
236       return return_address_offset_rex;
237     }
238   }
239 };
240 
241 // An interface for accessing/manipulating native mov reg, imm32 instructions.
242 // (used to manipulate inlined 32bit data dll calls, etc.)
243 class NativeMovConstReg: public NativeInstruction {
244 #ifdef AMD64
245   static const bool has_rex = true;
246   static const int rex_size = 1;
247 #else
248   static const bool has_rex = false;
249   static const int rex_size = 0;
250 #endif // AMD64
251  public:
252   enum Intel_specific_constants {
253     instruction_code            = 0xB8,
254     instruction_size            =    1 + rex_size + wordSize,
255     instruction_offset          =    0,
256     data_offset                 =    1 + rex_size,
257     next_instruction_offset     =    instruction_size,
258     register_mask               = 0x07
259   };
260 
261   address instruction_address() const       { return addr_at(instruction_offset); }
262   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
263   intptr_t data() const                     { return ptr_at(data_offset); }
264   void  set_data(intptr_t x)                { set_ptr_at(data_offset, x); }
265 
266   void  verify();
267   void  print();
268 
269   // Creation
270   inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
271   inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
272 };
273 
274 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
275   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
276 #ifdef ASSERT
277   test->verify();
278 #endif
279   return test;
280 }
281 
282 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
283   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
284 #ifdef ASSERT
285   test->verify();
286 #endif
287   return test;
288 }
289 
290 class NativeMovConstRegPatching: public NativeMovConstReg {
291  private:
292     friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
293     NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
294     #ifdef ASSERT
295       test->verify();
296     #endif
297     return test;
298   }
299 };
300 
301 // An interface for accessing/manipulating native moves of the form:
302 //      mov[b/w/l/q] [reg + offset], reg   (instruction_code_reg2mem)
303 //      mov[b/w/l/q] reg, [reg+offset]     (instruction_code_mem2reg
304 //      mov[s/z]x[w/b/q] [reg + offset], reg
305 //      fld_s  [reg+offset]
306 //      fld_d  [reg+offset]
307 //      fstp_s [reg + offset]
308 //      fstp_d [reg + offset]
309 //      mov_literal64  scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
310 //
311 // Warning: These routines must be able to handle any instruction sequences
312 // that are generated as a result of the load/store byte,word,long
313 // macros.  For example: The load_unsigned_byte instruction generates
314 // an xor reg,reg inst prior to generating the movb instruction.  This
315 // class must skip the xor instruction.
316 
317 class NativeMovRegMem: public NativeInstruction {
318  public:
319   enum Intel_specific_constants {
320     instruction_prefix_wide_lo          = Assembler::REX,
321     instruction_prefix_wide_hi          = Assembler::REX_WRXB,
322     instruction_code_xor                = 0x33,
323     instruction_extended_prefix         = 0x0F,
324     instruction_code_mem2reg_movslq     = 0x63,
325     instruction_code_mem2reg_movzxb     = 0xB6,
326     instruction_code_mem2reg_movsxb     = 0xBE,
327     instruction_code_mem2reg_movzxw     = 0xB7,
328     instruction_code_mem2reg_movsxw     = 0xBF,
329     instruction_operandsize_prefix      = 0x66,
330     instruction_code_reg2mem            = 0x89,
331     instruction_code_mem2reg            = 0x8b,
332     instruction_code_reg2memb           = 0x88,
333     instruction_code_mem2regb           = 0x8a,
334     instruction_code_float_s            = 0xd9,
335     instruction_code_float_d            = 0xdd,
336     instruction_code_long_volatile      = 0xdf,
337     instruction_code_xmm_ss_prefix      = 0xf3,
338     instruction_code_xmm_sd_prefix      = 0xf2,
339     instruction_code_xmm_code           = 0x0f,
340     instruction_code_xmm_load           = 0x10,
341     instruction_code_xmm_store          = 0x11,
342     instruction_code_xmm_lpd            = 0x12,
343 
344     instruction_code_lea                = 0x8d,
345 
346     instruction_VEX_prefix_2bytes       = Assembler::VEX_2bytes,
347     instruction_VEX_prefix_3bytes       = Assembler::VEX_3bytes,
348     instruction_EVEX_prefix_4bytes      = Assembler::EVEX_4bytes,
349 
350     instruction_offset                  = 0,
351     data_offset                         = 2,
352     next_instruction_offset             = 4
353   };
354 
355   // helper
356   int instruction_start() const;
357 
358   address instruction_address() const {
359     return addr_at(instruction_start());
360   }
361 
362   int num_bytes_to_end_of_patch() const {
363     return patch_offset() + sizeof(jint);
364   }
365 
366   int offset() const {
367     return int_at(patch_offset());
368   }
369 
370   void set_offset(int x) {
371     set_int_at(patch_offset(), x);
372   }
373 
374   void add_offset_in_bytes(int add_offset) {
375     int patch_off = patch_offset();
376     set_int_at(patch_off, int_at(patch_off) + add_offset);
377   }
378 
379   void verify();
380   void print ();
381 
382  private:
383   int patch_offset() const;
384   inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
385 };
386 
387 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
388   NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
389 #ifdef ASSERT
390   test->verify();
391 #endif
392   return test;
393 }
394 
395 
396 // An interface for accessing/manipulating native leal instruction of form:
397 //        leal reg, [reg + offset]
398 
399 class NativeLoadAddress: public NativeMovRegMem {
400 #ifdef AMD64
401   static const bool has_rex = true;
402   static const int rex_size = 1;
403 #else
404   static const bool has_rex = false;
405   static const int rex_size = 0;
406 #endif // AMD64
407  public:
408   enum Intel_specific_constants {
409     instruction_prefix_wide             = Assembler::REX_W,
410     instruction_prefix_wide_extended    = Assembler::REX_WB,
411     lea_instruction_code                = 0x8D,
412     mov64_instruction_code              = 0xB8
413   };
414 
415   void verify();
416   void print ();
417 
418  private:
419   friend NativeLoadAddress* nativeLoadAddress_at (address address) {
420     NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
421     #ifdef ASSERT
422       test->verify();
423     #endif
424     return test;
425   }
426 };
427 
428 // destination is rbx or rax
429 // mov rbx, [rip + offset]
430 class NativeLoadGot: public NativeInstruction {
431 #ifdef AMD64
432   static const bool has_rex = true;
433   static const int rex_size = 1;
434 #else
435   static const bool has_rex = false;
436   static const int rex_size = 0;
437 #endif
438 
439   enum Intel_specific_constants {
440     rex_prefix = 0x48,
441     rex_b_prefix = 0x49,
442     instruction_code = 0x8b,
443     modrm_rbx_code = 0x1d,
444     modrm_rax_code = 0x05,
445     instruction_length = 6 + rex_size,
446     offset_offset = 2 + rex_size
447   };
448 
449   int rip_offset() const { return int_at(offset_offset); }
450   address return_address() const { return addr_at(instruction_length); }
451   address got_address() const { return return_address() + rip_offset(); }
452 
453 #ifdef ASSERT
454   void report_and_fail() const;
455   address instruction_address() const { return addr_at(0); }
456 #endif
457 
458 public:
459   address next_instruction_address() const { return return_address(); }
460   intptr_t data() const;
461   void set_data(intptr_t data) {
462     intptr_t *addr = (intptr_t *) got_address();
463     *addr = data;
464   }
465 
466   DEBUG_ONLY( void verify() const );
467 };
468 
469 inline NativeLoadGot* nativeLoadGot_at(address addr) {
470   NativeLoadGot* load = (NativeLoadGot*) addr;
471 #ifdef ASSERT
472   load->verify();
473 #endif
474   return load;
475 }
476 
477 // jump rel32off
478 
479 class NativeJump: public NativeInstruction {
480  public:
481   enum Intel_specific_constants {
482     instruction_code            = 0xe9,
483     instruction_size            =    5,
484     instruction_offset          =    0,
485     data_offset                 =    1,
486     next_instruction_offset     =    5
487   };
488 
489   address instruction_address() const       { return addr_at(instruction_offset); }
490   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
491   address jump_destination() const          {
492      address dest = (int_at(data_offset)+next_instruction_address());
493      // 32bit used to encode unresolved jmp as jmp -1
494      // 64bit can't produce this so it used jump to self.
495      // Now 32bit and 64bit use jump to self as the unresolved address
496      // which the inline cache code (and relocs) know about
497 
498      // return -1 if jump to self
499     dest = (dest == (address) this) ? (address) -1 : dest;
500     return dest;
501   }
502 
503   void  set_jump_destination(address dest)  {
504     intptr_t val = dest - next_instruction_address();
505     if (dest == (address) -1) {
506       val = -5; // jump to self
507     }
508 #ifdef AMD64
509     assert((labs(val)  & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
510 #endif // AMD64
511     set_int_at(data_offset, (jint)val);
512   }
513 
514   // Creation
515   inline friend NativeJump* nativeJump_at(address address);
516 
517   void verify();
518 
519   // Insertion of native jump instruction
520   static void insert(address code_pos, address entry);
521   // MT-safe insertion of native jump at verified method entry
522   static void check_verified_entry_alignment(address entry, address verified_entry);
523   static void patch_verified_entry(address entry, address verified_entry, address dest);
524 };
525 
526 inline NativeJump* nativeJump_at(address address) {
527   NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
528 #ifdef ASSERT
529   jump->verify();
530 #endif
531   return jump;
532 }
533 
534 // far jump reg
535 class NativeFarJump: public NativeInstruction {
536  public:
537   address jump_destination() const;
538 
539   // Creation
540   inline friend NativeFarJump* nativeFarJump_at(address address);
541 
542   void verify();
543 
544 };
545 
546 inline NativeFarJump* nativeFarJump_at(address address) {
547   NativeFarJump* jump = (NativeFarJump*)(address);
548 #ifdef ASSERT
549   jump->verify();
550 #endif
551   return jump;
552 }
553 
554 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional
555 class NativeGeneralJump: public NativeInstruction {
556  public:
557   enum Intel_specific_constants {
558     // Constants does not apply, since the lengths and offsets depends on the actual jump
559     // used
560     // Instruction codes:
561     //   Unconditional jumps: 0xE9    (rel32off), 0xEB (rel8off)
562     //   Conditional jumps:   0x0F8x  (rel32off), 0x7x (rel8off)
563     unconditional_long_jump  = 0xe9,
564     unconditional_short_jump = 0xeb,
565     instruction_size = 5
566   };
567 
568   address instruction_address() const       { return addr_at(0); }
569   address jump_destination()    const;
570 
571   // Creation
572   inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
573 
574   // Insertion of native general jump instruction
575   static void insert_unconditional(address code_pos, address entry);
576   static void replace_mt_safe(address instr_addr, address code_buffer);
577 
578   void verify();
579 };
580 
581 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
582   NativeGeneralJump* jump = (NativeGeneralJump*)(address);
583   debug_only(jump->verify();)
584   return jump;
585 }
586 
587 class NativeGotJump: public NativeInstruction {
588   enum Intel_specific_constants {
589     rex_prefix = 0x41,
590     instruction_code = 0xff,
591     modrm_code = 0x25,
592     instruction_size = 6,
593     rip_offset = 2
594   };
595 
596   bool has_rex() const { return ubyte_at(0) == rex_prefix; }
597   int rex_size() const { return has_rex() ? 1 : 0; }
598 
599   address return_address() const { return addr_at(instruction_size + rex_size()); }
600   int got_offset() const { return (jint) int_at(rip_offset + rex_size()); }
601 
602 #ifdef ASSERT
603   void report_and_fail() const;
604   address instruction_address() const { return addr_at(0); }
605 #endif
606 
607 public:
608   address got_address() const { return return_address() + got_offset(); }
609   address next_instruction_address() const { return return_address(); }
610   bool is_GotJump() const { return ubyte_at(rex_size()) == instruction_code; }
611 
612   address destination() const;
613   void set_jump_destination(address dest)  {
614     address *got_entry = (address *) got_address();
615     *got_entry = dest;
616   }
617 
618   DEBUG_ONLY( void verify() const; )
619 };
620 
621 inline NativeGotJump* nativeGotJump_at(address addr) {
622   NativeGotJump* jump = (NativeGotJump*)(addr);
623   debug_only(jump->verify());
624   return jump;
625 }
626 
627 class NativePopReg : public NativeInstruction {
628  public:
629   enum Intel_specific_constants {
630     instruction_code            = 0x58,
631     instruction_size            =    1,
632     instruction_offset          =    0,
633     data_offset                 =    1,
634     next_instruction_offset     =    1
635   };
636 
637   // Insert a pop instruction
638   static void insert(address code_pos, Register reg);
639 };
640 
641 
642 class NativeIllegalInstruction: public NativeInstruction {
643  public:
644   enum Intel_specific_constants {
645     instruction_code            = 0x0B0F,    // Real byte order is: 0x0F, 0x0B
646     instruction_size            =    2,
647     instruction_offset          =    0,
648     next_instruction_offset     =    2
649   };
650 
651   // Insert illegal opcode as specific address
652   static void insert(address code_pos);
653 };
654 
655 // return instruction that does not pop values of the stack
656 class NativeReturn: public NativeInstruction {
657  public:
658   enum Intel_specific_constants {
659     instruction_code            = 0xC3,
660     instruction_size            =    1,
661     instruction_offset          =    0,
662     next_instruction_offset     =    1
663   };
664 };
665 
666 // return instruction that does pop values of the stack
667 class NativeReturnX: public NativeInstruction {
668  public:
669   enum Intel_specific_constants {
670     instruction_code            = 0xC2,
671     instruction_size            =    2,
672     instruction_offset          =    0,
673     next_instruction_offset     =    2
674   };
675 };
676 
677 // Simple test vs memory
678 class NativeTstRegMem: public NativeInstruction {
679  public:
680   enum Intel_specific_constants {
681     instruction_rex_prefix_mask = 0xF0,
682     instruction_rex_prefix      = Assembler::REX,
683     instruction_rex_b_prefix    = Assembler::REX_B,
684     instruction_code_memXregl   = 0x85,
685     modrm_mask                  = 0x38, // select reg from the ModRM byte
686     modrm_reg                   = 0x00  // rax
687   };
688 };
689 
690 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
691 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
692 inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code ||
693                                                           (ubyte_at(1) == NativeCallReg::instruction_code &&
694                                                            (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
695 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
696                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
697 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
698                                                           ubyte_at(0) == 0xEB; /* short jump */ }
699 inline bool NativeInstruction::is_jump_reg()     {
700   int pos = 0;
701   if (ubyte_at(0) == Assembler::REX_B) pos = 1;
702   return ubyte_at(pos) == 0xFF && (ubyte_at(pos + 1) & 0xF0) == 0xE0;
703 }
704 inline bool NativeInstruction::is_far_jump()     { return is_mov_literal64(); }
705 inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
706                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
707 inline bool NativeInstruction::is_safepoint_poll() {
708 #ifdef AMD64
709   const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
710   const int test_offset = has_rex_prefix ? 1 : 0;
711 #else
712   const int test_offset = 0;
713 #endif
714   const bool is_test_opcode = ubyte_at(test_offset) == NativeTstRegMem::instruction_code_memXregl;
715   const bool is_rax_target = (ubyte_at(test_offset + 1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
716   return is_test_opcode && is_rax_target;
717 }
718 
719 inline bool NativeInstruction::is_mov_literal64() {
720 #ifdef AMD64
721   return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
722           (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
723 #else
724   return false;
725 #endif // AMD64
726 }
727 
728 class NativePostCallNop: public NativeInstruction {
729 public:
730   enum Intel_specific_constants {
731     instruction_code = 0x0f,
732     instruction_size = 8,
733     instruction_offset = 0,
734     displacement_offset = 4
735   };
736 
737   bool check() const { return int_at(0) == 0x841f0f; }
738   bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const {
739     int32_t data = int_at(displacement_offset);
740     if (data == 0) {
741       return false; // no information encoded
742     }
743     cb_offset = (data & 0xffffff);
744     oopmap_slot = (data >> 24) & 0xff;
745     return true; // decoding succeeded
746   }
747   bool patch(int32_t oopmap_slot, int32_t cb_offset);
748   void make_deopt();
749 };
750 
751 inline NativePostCallNop* nativePostCallNop_at(address address) {
752   NativePostCallNop* nop = (NativePostCallNop*) address;
753   if (nop->check()) {
754     return nop;
755   }
756   return nullptr;
757 }
758 
759 inline NativePostCallNop* nativePostCallNop_unsafe_at(address address) {
760   NativePostCallNop* nop = (NativePostCallNop*) address;
761   assert(nop->check(), "");
762   return nop;
763 }
764 
765 class NativeDeoptInstruction: public NativeInstruction {
766  public:
767   enum Intel_specific_constants {
768     instruction_prefix          = 0x0F,
769     instruction_code            = 0xFF,
770     instruction_size            =    3,
771     instruction_offset          =    0,
772   };
773 
774   address instruction_address() const       { return addr_at(instruction_offset); }
775   address next_instruction_address() const  { return addr_at(instruction_size); }
776 
777   void  verify();
778 
779   static bool is_deopt_at(address instr) {
780     return ((*instr) & 0xFF) == NativeDeoptInstruction::instruction_prefix &&
781       ((*(instr+1)) & 0xFF) == NativeDeoptInstruction::instruction_code;
782   }
783 
784   // MT-safe patching
785   static void insert(address code_pos, bool invalidate = true);
786 };
787 
788 #endif // CPU_X86_NATIVEINST_X86_HPP