1 /*
  2  * Copyright (c) 1997, 2025, 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 // - - NativeIllegalOpCode
 41 // - - NativeGeneralJump
 42 // - - NativeReturn
 43 // - - NativeReturnX (return with argument)
 44 // - - NativePushConst
 45 // - - NativeTstRegMem
 46 
 47 // The base class for different kinds of native instruction abstractions.
 48 // Provides the primitive operations to manipulate code relative to this.
 49 
 50 class NativeInstruction {
 51   friend class Relocation;
 52 
 53  public:
 54   enum Intel_specific_constants {
 55     nop_instruction_code        = 0x90,
 56     nop_instruction_size        =    1
 57   };
 58 
 59   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
 60   inline bool is_call();
 61   inline bool is_call_reg();
 62   inline bool is_illegal();
 63   inline bool is_return();
 64   inline bool is_jump();
 65   inline bool is_jump_reg();
 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   jshort short_at(int offset) const    { return *(jshort*) addr_at(offset); }
 77   jint int_at(int offset) const         { return *(jint*) addr_at(offset); }
 78 
 79   intptr_t ptr_at(int offset) const    { return *(intptr_t*) addr_at(offset); }
 80 
 81   oop  oop_at (int offset) const       { return *(oop*) addr_at(offset); }
 82 
 83 
 84   void set_char_at(int offset, u_char c)        { *addr_at(offset) = c; wrote(offset); }
 85   void set_int_at(int offset, jint  i)        { *(jint*)addr_at(offset) = i;  wrote(offset); }
 86   void set_ptr_at (int offset, intptr_t  ptr) { *(intptr_t*) addr_at(offset) = ptr;  wrote(offset); }
 87   void set_oop_at (int offset, oop  o)        { *(oop*) addr_at(offset) = o;  wrote(offset); }
 88 
 89   // This doesn't really do anything on Intel, but it is the place where
 90   // cache invalidation belongs, generically:
 91   void wrote(int offset);
 92 
 93  public:
 94   bool has_rex2_prefix() const { return ubyte_at(0) == Assembler::REX2; }
 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 NativeCall;
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   static int byte_size()                    { return instruction_size; }
123   address instruction_address() const       { return addr_at(instruction_offset); }
124   address next_instruction_address() const  { return addr_at(return_address_offset); }
125   int   displacement() const                { return (jint) int_at(displacement_offset); }
126   address displacement_address() const      { return addr_at(displacement_offset); }
127   address return_address() const            { return addr_at(return_address_offset); }
128   address destination() const;
129   void  set_destination(address dest)       {
130     intptr_t disp = dest - return_address();
131     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()));
132     set_int_at(displacement_offset, (int)(dest - return_address()));
133   }
134   // Returns whether the 4-byte displacement operand is 4-byte aligned.
135   bool  is_displacement_aligned();
136   void  set_destination_mt_safe(address dest);
137 
138   void  verify_alignment() { assert(is_displacement_aligned(), "displacement of call is not aligned"); }
139   void  verify();
140   void  print();
141 
142   // Creation
143   inline friend NativeCall* nativeCall_at(address address);
144   inline friend NativeCall* nativeCall_before(address return_address);
145 
146   static bool is_call_at(address instr) {
147     return ((*instr) & 0xFF) == NativeCall::instruction_code;
148   }
149 
150   static bool is_call_before(address return_address) {
151     return is_call_at(return_address - NativeCall::return_address_offset);
152   }
153 
154   static bool is_call_to(address instr, address target) {
155     return nativeInstruction_at(instr)->is_call() &&
156       nativeCall_at(instr)->destination() == target;
157   }
158 
159   // MT-safe patching of a call instruction.
160   static void insert(address code_pos, address entry);
161 
162   static void replace_mt_safe(address instr_addr, address code_buffer);
163 };
164 
165 inline NativeCall* nativeCall_at(address address) {
166   NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
167 #ifdef ASSERT
168   call->verify();
169 #endif
170   return call;
171 }
172 
173 inline NativeCall* nativeCall_before(address return_address) {
174   NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
175 #ifdef ASSERT
176   call->verify();
177 #endif
178   return call;
179 }
180 
181 // Call with target address in a general purpose register(indirect absolute addressing).
182 // Encoding : FF /2  CALL r/m32
183 // Primary Opcode: FF
184 // Opcode Extension(part of ModRM.REG): /2
185 // Operand ModRM.RM  = r/m32
186 class NativeCallReg: public NativeInstruction {
187  public:
188   enum Intel_specific_constants {
189     instruction_code            = 0xFF,
190     instruction_offset          =    0,
191     return_address_offset_norex =    2,
192     return_address_offset_rex   =    3,
193     return_address_offset_rex2  =    4
194   };
195 
196   int next_instruction_offset() const  {
197     if (ubyte_at(0) == NativeCallReg::instruction_code) {
198       return return_address_offset_norex;
199     } else if (has_rex2_prefix()) {
200       return return_address_offset_rex2;
201     } else {
202       assert((ubyte_at(0) & 0xF0) ==  Assembler::REX, "");
203       return return_address_offset_rex;
204     }
205   }
206 };
207 
208 // An interface for accessing/manipulating native mov reg, imm32 instructions.
209 // (used to manipulate inlined 32bit data dll calls, etc.)
210 // Instruction format for implied addressing mode immediate operand move to register instruction:
211 //  [REX/REX2] [OPCODE] [IMM32]
212 class NativeMovConstReg: public NativeInstruction {
213   static const bool has_rex = true;
214   static const int rex_size = 1;
215   static const int rex2_size = 2;
216  public:
217   enum Intel_specific_constants {
218     instruction_code             = 0xB8,
219     instruction_offset           =    0,
220     instruction_size_rex         =    1 + rex_size + wordSize,
221     instruction_size_rex2        =    1 + rex2_size + wordSize,
222     data_offset_rex              =    1 + rex_size,
223     data_offset_rex2             =    1 + rex2_size,
224     next_instruction_offset_rex  =    instruction_size_rex,
225     next_instruction_offset_rex2 =    instruction_size_rex2,
226     register_mask                = 0x07
227   };
228 
229   int instruction_size() const              { return has_rex2_prefix() ? instruction_size_rex2 : instruction_size_rex; }
230   int next_inst_offset() const              { return has_rex2_prefix() ? next_instruction_offset_rex2 : next_instruction_offset_rex; }
231   int data_byte_offset() const              { return has_rex2_prefix() ? data_offset_rex2 : data_offset_rex;}
232   address instruction_address() const       { return addr_at(instruction_offset); }
233   address next_instruction_address() const  { return addr_at(next_inst_offset()); }
234   intptr_t data() const                     { return ptr_at(data_byte_offset()); }
235   void  set_data(intptr_t x)                { set_ptr_at(data_byte_offset(), x); }
236 
237   void  verify();
238   void  print();
239 
240   // Creation
241   inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
242   inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
243 };
244 
245 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
246   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
247 #ifdef ASSERT
248   test->verify();
249 #endif
250   return test;
251 }
252 
253 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
254   int instruction_size = ((NativeInstruction*)(address))->has_rex2_prefix() ?
255                                   NativeMovConstReg::instruction_size_rex2 :
256                                   NativeMovConstReg::instruction_size_rex;
257   NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size - NativeMovConstReg::instruction_offset);
258 #ifdef ASSERT
259   test->verify();
260 #endif
261   return test;
262 }
263 
264 class NativeMovConstRegPatching: public NativeMovConstReg {
265  private:
266     friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
267     NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
268     #ifdef ASSERT
269       test->verify();
270     #endif
271     return test;
272   }
273 };
274 
275 // An interface for accessing/manipulating native moves of the form:
276 //      mov[b/w/l/q] [reg + offset], reg   (instruction_code_reg2mem)
277 //      mov[b/w/l/q] reg, [reg+offset]     (instruction_code_mem2reg
278 //      mov[s/z]x[w/b/q] [reg + offset], reg
279 //      fld_s  [reg+offset]
280 //      fld_d  [reg+offset]
281 //      fstp_s [reg + offset]
282 //      fstp_d [reg + offset]
283 //      mov_literal64  scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
284 //
285 // Warning: These routines must be able to handle any instruction sequences
286 // that are generated as a result of the load/store byte,word,long
287 // macros.  For example: The load_unsigned_byte instruction generates
288 // an xor reg,reg inst prior to generating the movb instruction.  This
289 // class must skip the xor instruction.
290 
291 class NativeMovRegMem: public NativeInstruction {
292  public:
293   enum Intel_specific_constants {
294     instruction_prefix_wide_lo          = Assembler::REX,
295     instruction_prefix_wide_hi          = Assembler::REX_WRXB,
296     instruction_code_xor                = 0x33,
297     instruction_extended_prefix         = 0x0F,
298 
299     // Legacy encoding MAP1 instructions promotable to REX2 encoding.
300     instruction_code_mem2reg_movslq     = 0x63,
301     instruction_code_mem2reg_movzxb     = 0xB6,
302     instruction_code_mem2reg_movsxb     = 0xBE,
303     instruction_code_mem2reg_movzxw     = 0xB7,
304     instruction_code_mem2reg_movsxw     = 0xBF,
305     instruction_operandsize_prefix      = 0x66,
306 
307     // Legacy encoding MAP0 instructions promotable to REX2 encoding.
308     instruction_code_reg2mem            = 0x89,
309     instruction_code_mem2reg            = 0x8b,
310     instruction_code_reg2memb           = 0x88,
311     instruction_code_mem2regb           = 0x8a,
312     instruction_code_lea                = 0x8d,
313 
314     instruction_code_float_s            = 0xd9,
315     instruction_code_float_d            = 0xdd,
316     instruction_code_long_volatile      = 0xdf,
317 
318     // VEX/EVEX/Legacy encodeded MAP1 instructions promotable to REX2 encoding.
319     instruction_code_xmm_ss_prefix      = 0xf3,
320     instruction_code_xmm_sd_prefix      = 0xf2,
321 
322     instruction_code_xmm_code           = 0x0f,
323 
324     // Address operand load/store/ldp are promotable to REX2 to accomodate
325     // extended SIB encoding.
326     instruction_code_xmm_load           = 0x10,
327     instruction_code_xmm_store          = 0x11,
328     instruction_code_xmm_lpd            = 0x12,
329 
330     instruction_VEX_prefix_2bytes       = Assembler::VEX_2bytes,
331     instruction_VEX_prefix_3bytes       = Assembler::VEX_3bytes,
332     instruction_EVEX_prefix_4bytes      = Assembler::EVEX_4bytes,
333     instruction_REX2_prefix             = Assembler::REX2,
334 
335     instruction_offset                  = 0,
336     data_offset                         = 2,
337     next_instruction_offset_rex         = 4,
338     next_instruction_offset_rex2        = 5
339   };
340 
341   // helper
342   int instruction_start() const;
343 
344   address instruction_address() const {
345     return addr_at(instruction_start());
346   }
347 
348   int num_bytes_to_end_of_patch() const {
349     return patch_offset() + sizeof(jint);
350   }
351 
352   int offset() const {
353     return int_at(patch_offset());
354   }
355 
356   void set_offset(int x) {
357     set_int_at(patch_offset(), x);
358   }
359 
360   void add_offset_in_bytes(int add_offset) {
361     int patch_off = patch_offset();
362     set_int_at(patch_off, int_at(patch_off) + add_offset);
363   }
364 
365   void verify();
366   void print ();
367 
368  private:
369   int patch_offset() const;
370   inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
371 };
372 
373 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
374   NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
375 #ifdef ASSERT
376   test->verify();
377 #endif
378   return test;
379 }
380 
381 
382 // An interface for accessing/manipulating native leal instruction of form:
383 //        leal reg, [reg + offset]
384 
385 class NativeLoadAddress: public NativeMovRegMem {
386   static const bool has_rex = true;
387   static const int rex_size = 1;
388  public:
389   enum Intel_specific_constants {
390     instruction_prefix_wide             = Assembler::REX_W,
391     instruction_prefix_wide_extended    = Assembler::REX_WB,
392     lea_instruction_code                = 0x8D,
393     mov64_instruction_code              = 0xB8
394   };
395 
396   void verify();
397   void print ();
398 
399  private:
400   friend NativeLoadAddress* nativeLoadAddress_at (address address) {
401     NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
402     #ifdef ASSERT
403       test->verify();
404     #endif
405     return test;
406   }
407 };
408 
409 class NativeJump: public NativeInstruction {
410  public:
411   enum Intel_specific_constants {
412     instruction_code            = 0xe9,
413     instruction_size            =    5,
414     instruction_offset          =    0,
415     data_offset                 =    1,
416     next_instruction_offset     =    5
417   };
418 
419   address instruction_address() const       { return addr_at(instruction_offset); }
420   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
421   address jump_destination() const          {
422      address dest = (int_at(data_offset)+next_instruction_address());
423      // 32bit used to encode unresolved jmp as jmp -1
424      // 64bit can't produce this so it used jump to self.
425      // Now 32bit and 64bit use jump to self as the unresolved address
426      // which the inline cache code (and relocs) know about
427 
428      // return -1 if jump to self
429     dest = (dest == (address) this) ? (address) -1 : dest;
430     return dest;
431   }
432 
433   void  set_jump_destination(address dest)  {
434     intptr_t val = dest - next_instruction_address();
435     if (dest == (address) -1) {
436       val = -5; // jump to self
437     }
438     assert((labs(val)  & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
439     set_int_at(data_offset, (jint)val);
440   }
441 
442   // Creation
443   inline friend NativeJump* nativeJump_at(address address);
444 
445   void verify();
446 
447   // Insertion of native jump instruction
448   static void insert(address code_pos, address entry);
449 };
450 
451 inline NativeJump* nativeJump_at(address address) {
452   NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
453 #ifdef ASSERT
454   jump->verify();
455 #endif
456   return jump;
457 }
458 
459 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional with relative offsets
460 // barring register indirect jumps.
461 class NativeGeneralJump: public NativeInstruction {
462  public:
463   enum Intel_specific_constants {
464     // Constants does not apply, since the lengths and offsets depends on the actual jump
465     // used
466     // Instruction codes:
467     //   Unconditional jumps: 0xE9    (rel32off), 0xEB (rel8off)
468     //   Conditional jumps:   0x0F8x  (rel32off), 0x7x (rel8off)
469     unconditional_long_jump  = 0xe9,
470     unconditional_short_jump = 0xeb,
471     instruction_size = 5
472   };
473 
474   address instruction_address() const       { return addr_at(0); }
475   address jump_destination()    const;
476 
477   // Creation
478   inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
479 
480   // Insertion of native general jump instruction
481   static void insert_unconditional(address code_pos, address entry);
482   static void replace_mt_safe(address instr_addr, address code_buffer);
483 
484   void verify();
485 };
486 
487 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
488   NativeGeneralJump* jump = (NativeGeneralJump*)(address);
489   DEBUG_ONLY(jump->verify();)
490   return jump;
491 }
492 
493 class NativeIllegalInstruction: public NativeInstruction {
494  public:
495   enum Intel_specific_constants {
496     instruction_code            = 0x0B0F,    // Real byte order is: 0x0F, 0x0B
497     instruction_size            =    2,
498     instruction_offset          =    0,
499     next_instruction_offset     =    2
500   };
501 
502   // Insert illegal opcode as specific address
503   static void insert(address code_pos);
504 };
505 
506 // return instruction that does not pop values of the stack
507 class NativeReturn: public NativeInstruction {
508  public:
509   enum Intel_specific_constants {
510     instruction_code            = 0xC3,
511     instruction_size            =    1,
512     instruction_offset          =    0,
513     next_instruction_offset     =    1
514   };
515 };
516 
517 // return instruction that does pop values of the stack
518 class NativeReturnX: public NativeInstruction {
519  public:
520   enum Intel_specific_constants {
521     instruction_code            = 0xC2,
522     instruction_size            =    2,
523     instruction_offset          =    0,
524     next_instruction_offset     =    2
525   };
526 };
527 
528 // Simple test vs memory
529 class NativeTstRegMem: public NativeInstruction {
530  public:
531   enum Intel_specific_constants {
532     instruction_rex_prefix_mask = 0xF0,
533     instruction_rex_prefix      = Assembler::REX,
534     instruction_rex_b_prefix    = Assembler::REX_B,
535     instruction_code_memXregl   = 0x85,
536     modrm_mask                  = 0x38, // select reg from the ModRM byte
537     modrm_reg                   = 0x00  // rax
538   };
539 };
540 
541 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
542 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
543 inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code ||
544                                                           (ubyte_at(1) == NativeCallReg::instruction_code &&
545                                                            (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
546 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
547                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
548 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
549                                                           ubyte_at(0) == 0xEB; /* short jump */ }
550 inline bool NativeInstruction::is_jump_reg()     {
551   int pos = 0;
552   if (ubyte_at(0) == Assembler::REX_B) pos = 1;
553   return ubyte_at(pos) == 0xFF && (ubyte_at(pos + 1) & 0xF0) == 0xE0;
554 }
555 inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
556                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
557 inline bool NativeInstruction::is_safepoint_poll() {
558   const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
559   const int test_offset = has_rex2_prefix() ? 2 : (has_rex_prefix ? 1 : 0);
560   const bool is_test_opcode = ubyte_at(test_offset) == NativeTstRegMem::instruction_code_memXregl;
561   const bool is_rax_target = (ubyte_at(test_offset + 1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
562   return is_test_opcode && is_rax_target;
563 }
564 
565 inline bool NativeInstruction::is_mov_literal64() {
566   bool valid_rex_prefix  = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
567   bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2  &&
568        (ubyte_at(1) == Assembler::REX2BIT_W  ||
569         ubyte_at(1) == Assembler::REX2BIT_WB ||
570         ubyte_at(1) == Assembler::REX2BIT_WB4);
571 
572   int opcode = has_rex2_prefix() ? ubyte_at(2) : ubyte_at(1);
573   return ((valid_rex_prefix || valid_rex2_prefix) &&  (opcode & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
574 }
575 
576 class NativePostCallNop: public NativeInstruction {
577 public:
578   enum Intel_specific_constants {
579     instruction_code = 0x0f,
580     instruction_size = 8,
581     instruction_offset = 0,
582     displacement_offset = 4,
583 
584     // The two parts should be checked separately to prevent out of bounds access in case
585     // the return address points to the deopt handler stub code entry point which could be
586     // at the end of page.
587     first_check_size = 2
588   };
589 
590   bool check() const { return short_at(0) == 0x1f0f && short_at(first_check_size) == 0x0084; }
591   bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const {
592     int32_t data = int_at(displacement_offset);
593     if (data == 0) {
594       return false; // no information encoded
595     }
596     cb_offset = (data & 0xffffff);
597     oopmap_slot = (data >> 24) & 0xff;
598     return true; // decoding succeeded
599   }
600   bool patch(int32_t oopmap_slot, int32_t cb_offset);
601   void make_deopt();
602 };
603 
604 inline NativePostCallNop* nativePostCallNop_at(address address) {
605   NativePostCallNop* nop = (NativePostCallNop*) address;
606   if (nop->check()) {
607     return nop;
608   }
609   return nullptr;
610 }
611 
612 inline NativePostCallNop* nativePostCallNop_unsafe_at(address address) {
613   NativePostCallNop* nop = (NativePostCallNop*) address;
614   assert(nop->check(), "");
615   return nop;
616 }
617 
618 class NativeDeoptInstruction: public NativeInstruction {
619  public:
620   enum Intel_specific_constants {
621     instruction_prefix          = 0x0F,
622     instruction_code            = 0xFF,
623     instruction_size            =    3,
624     instruction_offset          =    0,
625   };
626 
627   address instruction_address() const       { return addr_at(instruction_offset); }
628   address next_instruction_address() const  { return addr_at(instruction_size); }
629 
630   void  verify();
631 
632   static bool is_deopt_at(address instr) {
633     return ((*instr) & 0xFF) == NativeDeoptInstruction::instruction_prefix &&
634       ((*(instr+1)) & 0xFF) == NativeDeoptInstruction::instruction_code;
635   }
636 
637   // MT-safe patching
638   static void insert(address code_pos, bool invalidate = true);
639 };
640 
641 #endif // CPU_X86_NATIVEINST_X86_HPP