1 /*
2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef CPU_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/os.hpp"
31 #include "runtime/safepointMechanism.hpp"
32 
33 // We have interfaces for the following instructions:
34 // - NativeInstruction
35 // - - NativeCall
36 // - - NativeMovConstReg
37 // - - NativeMovConstRegPatching
38 // - - NativeMovRegMem
39 // - - NativeMovRegMemPatching
40 // - - NativeJump
41 // - - NativeFarJump
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 {
53   friend class Relocation;
54 
55  public:
56   enum Intel_specific_constants {
57     nop_instruction_code        = 0x90,
58     nop_instruction_size        =    1
59   };
60 
is_nop()61   bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
62   inline bool is_call();
63   inline bool is_call_reg();
64   inline bool is_illegal();
65   inline bool is_return();
66   inline bool is_jump();
67   inline bool is_jump_reg();
68   inline bool is_far_jump();
69   inline bool is_cond_jump();
70   inline bool is_safepoint_poll();
71   inline bool is_mov_literal64();
72 
73  protected:
addr_at(int offset) const74   address addr_at(int offset) const    { return address(this) + offset; }
75 
sbyte_at(int offset) const76   s_char sbyte_at(int offset) const    { return *(s_char*) addr_at(offset); }
ubyte_at(int offset) const77   u_char ubyte_at(int offset) const    { return *(u_char*) addr_at(offset); }
78 
int_at(int offset) const79   jint int_at(int offset) const         { return *(jint*) addr_at(offset); }
80 
ptr_at(int offset) const81   intptr_t ptr_at(int offset) const    { return *(intptr_t*) addr_at(offset); }
82 
oop_at(int offset) const83   oop  oop_at (int offset) const       { return *(oop*) addr_at(offset); }
84 
85 
set_char_at(int offset,char c)86   void set_char_at(int offset, char c)        { *addr_at(offset) = (u_char)c; wrote(offset); }
set_int_at(int offset,jint i)87   void set_int_at(int offset, jint  i)        { *(jint*)addr_at(offset) = i;  wrote(offset); }
set_ptr_at(int offset,intptr_t ptr)88   void set_ptr_at (int offset, intptr_t  ptr) { *(intptr_t*) addr_at(offset) = ptr;  wrote(offset); }
set_oop_at(int offset,oop o)89   void set_oop_at (int offset, oop  o)        { *(oop*) addr_at(offset) = o;  wrote(offset); }
90 
91   // This doesn't really do anything on Intel, but it is the place where
92   // cache invalidation belongs, generically:
93   void wrote(int offset);
94 
95  public:
96 
97   // unit test stuff
test()98   static void test() {}                 // override for testing
99 
100   inline friend NativeInstruction* nativeInstruction_at(address address);
101 };
102 
nativeInstruction_at(address address)103 inline NativeInstruction* nativeInstruction_at(address address) {
104   NativeInstruction* inst = (NativeInstruction*)address;
105 #ifdef ASSERT
106   //inst->verify();
107 #endif
108   return inst;
109 }
110 
111 class NativePltCall: public NativeInstruction {
112 public:
113   enum Intel_specific_constants {
114     instruction_code           = 0xE8,
115     instruction_size           =    5,
116     instruction_offset         =    0,
117     displacement_offset        =    1,
118     return_address_offset      =    5
119   };
instruction_address() const120   address instruction_address() const { return addr_at(instruction_offset); }
next_instruction_address() const121   address next_instruction_address() const { return addr_at(return_address_offset); }
displacement_address() const122   address displacement_address() const { return addr_at(displacement_offset); }
displacement() const123   int displacement() const { return (jint) int_at(displacement_offset); }
return_address() const124   address return_address() const { return addr_at(return_address_offset); }
125   address destination() const;
126   address plt_entry() const;
127   address plt_jump() const;
128   address plt_load_got() const;
129   address plt_resolve_call() const;
130   address plt_c2i_stub() const;
131   void set_stub_to_clean();
132 
133   void  reset_to_plt_resolve_call();
134   void  set_destination_mt_safe(address dest);
135 
136   void verify() const;
137 };
138 
nativePltCall_at(address address)139 inline NativePltCall* nativePltCall_at(address address) {
140   NativePltCall* call = (NativePltCall*) address;
141 #ifdef ASSERT
142   call->verify();
143 #endif
144   return call;
145 }
146 
nativePltCall_before(address addr)147 inline NativePltCall* nativePltCall_before(address addr) {
148   address at = addr - NativePltCall::instruction_size;
149   return nativePltCall_at(at);
150 }
151 
152 class NativeCall;
153 inline NativeCall* nativeCall_at(address address);
154 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
155 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
156 
157 class NativeCall: public NativeInstruction {
158  public:
159   enum Intel_specific_constants {
160     instruction_code            = 0xE8,
161     instruction_size            =    5,
162     instruction_offset          =    0,
163     displacement_offset         =    1,
164     return_address_offset       =    5
165   };
166 
167   enum { cache_line_size = BytesPerWord };  // conservative estimate!
168 
instruction_address() const169   address instruction_address() const       { return addr_at(instruction_offset); }
next_instruction_address() const170   address next_instruction_address() const  { return addr_at(return_address_offset); }
displacement() const171   int   displacement() const                { return (jint) int_at(displacement_offset); }
displacement_address() const172   address displacement_address() const      { return addr_at(displacement_offset); }
return_address() const173   address return_address() const            { return addr_at(return_address_offset); }
174   address destination() const;
set_destination(address dest)175   void  set_destination(address dest)       {
176 #ifdef AMD64
177     intptr_t disp = dest - return_address();
178     guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset");
179 #endif // AMD64
180     set_int_at(displacement_offset, dest - return_address());
181   }
182   void  set_destination_mt_safe(address dest);
183 
verify_alignment()184   void  verify_alignment() { assert((intptr_t)addr_at(displacement_offset) % BytesPerInt == 0, "must be aligned"); }
185   void  verify();
186   void  print();
187 
188   // Creation
189   inline friend NativeCall* nativeCall_at(address address);
190   inline friend NativeCall* nativeCall_before(address return_address);
191 
is_call_at(address instr)192   static bool is_call_at(address instr) {
193     return ((*instr) & 0xFF) == NativeCall::instruction_code;
194   }
195 
is_call_before(address return_address)196   static bool is_call_before(address return_address) {
197     return is_call_at(return_address - NativeCall::return_address_offset);
198   }
199 
is_call_to(address instr,address target)200   static bool is_call_to(address instr, address target) {
201     return nativeInstruction_at(instr)->is_call() &&
202       nativeCall_at(instr)->destination() == target;
203   }
204 
205 #if INCLUDE_AOT
is_far_call(address instr,address target)206   static bool is_far_call(address instr, address target) {
207     intptr_t disp = target - (instr + sizeof(int32_t));
208     return !Assembler::is_simm32(disp);
209   }
210 #endif
211 
212   // MT-safe patching of a call instruction.
213   static void insert(address code_pos, address entry);
214 
215   static void replace_mt_safe(address instr_addr, address code_buffer);
216 };
217 
nativeCall_at(address address)218 inline NativeCall* nativeCall_at(address address) {
219   NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
220 #ifdef ASSERT
221   call->verify();
222 #endif
223   return call;
224 }
225 
nativeCall_before(address return_address)226 inline NativeCall* nativeCall_before(address return_address) {
227   NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
228 #ifdef ASSERT
229   call->verify();
230 #endif
231   return call;
232 }
233 
234 class NativeCallReg: public NativeInstruction {
235  public:
236   enum Intel_specific_constants {
237     instruction_code            = 0xFF,
238     instruction_offset          =    0,
239     return_address_offset_norex =    2,
240     return_address_offset_rex   =    3
241   };
242 
next_instruction_offset() const243   int next_instruction_offset() const  {
244     if (ubyte_at(0) == NativeCallReg::instruction_code) {
245       return return_address_offset_norex;
246     } else {
247       return return_address_offset_rex;
248     }
249   }
250 };
251 
252 // An interface for accessing/manipulating native mov reg, imm32 instructions.
253 // (used to manipulate inlined 32bit data dll calls, etc.)
254 class NativeMovConstReg: public NativeInstruction {
255 #ifdef AMD64
256   static const bool has_rex = true;
257   static const int rex_size = 1;
258 #else
259   static const bool has_rex = false;
260   static const int rex_size = 0;
261 #endif // AMD64
262  public:
263   enum Intel_specific_constants {
264     instruction_code            = 0xB8,
265     instruction_size            =    1 + rex_size + wordSize,
266     instruction_offset          =    0,
267     data_offset                 =    1 + rex_size,
268     next_instruction_offset     =    instruction_size,
269     register_mask               = 0x07
270   };
271 
instruction_address() const272   address instruction_address() const       { return addr_at(instruction_offset); }
next_instruction_address() const273   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
data() const274   intptr_t data() const                     { return ptr_at(data_offset); }
set_data(intptr_t x)275   void  set_data(intptr_t x)                { set_ptr_at(data_offset, x); }
276 
277   void  verify();
278   void  print();
279 
280   // unit test stuff
test()281   static void test() {}
282 
283   // Creation
284   inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
285   inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
286 };
287 
nativeMovConstReg_at(address address)288 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
289   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
290 #ifdef ASSERT
291   test->verify();
292 #endif
293   return test;
294 }
295 
nativeMovConstReg_before(address address)296 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
297   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
298 #ifdef ASSERT
299   test->verify();
300 #endif
301   return test;
302 }
303 
304 class NativeMovConstRegPatching: public NativeMovConstReg {
305  private:
nativeMovConstRegPatching_at(address address)306     friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
307     NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
308     #ifdef ASSERT
309       test->verify();
310     #endif
311     return test;
312   }
313 };
314 
315 // An interface for accessing/manipulating native moves of the form:
316 //      mov[b/w/l/q] [reg + offset], reg   (instruction_code_reg2mem)
317 //      mov[b/w/l/q] reg, [reg+offset]     (instruction_code_mem2reg
318 //      mov[s/z]x[w/b/q] [reg + offset], reg
319 //      fld_s  [reg+offset]
320 //      fld_d  [reg+offset]
321 //      fstp_s [reg + offset]
322 //      fstp_d [reg + offset]
323 //      mov_literal64  scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
324 //
325 // Warning: These routines must be able to handle any instruction sequences
326 // that are generated as a result of the load/store byte,word,long
327 // macros.  For example: The load_unsigned_byte instruction generates
328 // an xor reg,reg inst prior to generating the movb instruction.  This
329 // class must skip the xor instruction.
330 
331 class NativeMovRegMem: public NativeInstruction {
332  public:
333   enum Intel_specific_constants {
334     instruction_prefix_wide_lo          = Assembler::REX,
335     instruction_prefix_wide_hi          = Assembler::REX_WRXB,
336     instruction_code_xor                = 0x33,
337     instruction_extended_prefix         = 0x0F,
338     instruction_code_mem2reg_movslq     = 0x63,
339     instruction_code_mem2reg_movzxb     = 0xB6,
340     instruction_code_mem2reg_movsxb     = 0xBE,
341     instruction_code_mem2reg_movzxw     = 0xB7,
342     instruction_code_mem2reg_movsxw     = 0xBF,
343     instruction_operandsize_prefix      = 0x66,
344     instruction_code_reg2mem            = 0x89,
345     instruction_code_mem2reg            = 0x8b,
346     instruction_code_reg2memb           = 0x88,
347     instruction_code_mem2regb           = 0x8a,
348     instruction_code_float_s            = 0xd9,
349     instruction_code_float_d            = 0xdd,
350     instruction_code_long_volatile      = 0xdf,
351     instruction_code_xmm_ss_prefix      = 0xf3,
352     instruction_code_xmm_sd_prefix      = 0xf2,
353     instruction_code_xmm_code           = 0x0f,
354     instruction_code_xmm_load           = 0x10,
355     instruction_code_xmm_store          = 0x11,
356     instruction_code_xmm_lpd            = 0x12,
357 
358     instruction_code_lea                = 0x8d,
359 
360     instruction_VEX_prefix_2bytes       = Assembler::VEX_2bytes,
361     instruction_VEX_prefix_3bytes       = Assembler::VEX_3bytes,
362     instruction_EVEX_prefix_4bytes      = Assembler::EVEX_4bytes,
363 
364     instruction_offset                  = 0,
365     data_offset                         = 2,
366     next_instruction_offset             = 4
367   };
368 
369   // helper
370   int instruction_start() const;
371 
instruction_address() const372   address instruction_address() const {
373     return addr_at(instruction_start());
374   }
375 
num_bytes_to_end_of_patch() const376   int num_bytes_to_end_of_patch() const {
377     return patch_offset() + sizeof(jint);
378   }
379 
offset() const380   int offset() const {
381     return int_at(patch_offset());
382   }
383 
set_offset(int x)384   void set_offset(int x) {
385     set_int_at(patch_offset(), x);
386   }
387 
add_offset_in_bytes(int add_offset)388   void add_offset_in_bytes(int add_offset) {
389     int patch_off = patch_offset();
390     set_int_at(patch_off, int_at(patch_off) + add_offset);
391   }
392 
393   void verify();
394   void print ();
395 
396   // unit test stuff
test()397   static void test() {}
398 
399  private:
400   int patch_offset() const;
401   inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
402 };
403 
nativeMovRegMem_at(address address)404 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
405   NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
406 #ifdef ASSERT
407   test->verify();
408 #endif
409   return test;
410 }
411 
412 
413 // An interface for accessing/manipulating native leal instruction of form:
414 //        leal reg, [reg + offset]
415 
416 class NativeLoadAddress: public NativeMovRegMem {
417 #ifdef AMD64
418   static const bool has_rex = true;
419   static const int rex_size = 1;
420 #else
421   static const bool has_rex = false;
422   static const int rex_size = 0;
423 #endif // AMD64
424  public:
425   enum Intel_specific_constants {
426     instruction_prefix_wide             = Assembler::REX_W,
427     instruction_prefix_wide_extended    = Assembler::REX_WB,
428     lea_instruction_code                = 0x8D,
429     mov64_instruction_code              = 0xB8
430   };
431 
432   void verify();
433   void print ();
434 
435   // unit test stuff
test()436   static void test() {}
437 
438  private:
nativeLoadAddress_at(address address)439   friend NativeLoadAddress* nativeLoadAddress_at (address address) {
440     NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
441     #ifdef ASSERT
442       test->verify();
443     #endif
444     return test;
445   }
446 };
447 
448 // destination is rbx or rax
449 // mov rbx, [rip + offset]
450 class NativeLoadGot: public NativeInstruction {
451 #ifdef AMD64
452   static const bool has_rex = true;
453   static const int rex_size = 1;
454 #else
455   static const bool has_rex = false;
456   static const int rex_size = 0;
457 #endif
458 public:
459   enum Intel_specific_constants {
460     rex_prefix = 0x48,
461     instruction_code = 0x8b,
462     modrm_rbx_code = 0x1d,
463     modrm_rax_code = 0x05,
464     instruction_length = 6 + rex_size,
465     offset_offset = 2 + rex_size
466   };
467 
instruction_address() const468   address instruction_address() const { return addr_at(0); }
rip_offset_address() const469   address rip_offset_address() const { return addr_at(offset_offset); }
rip_offset() const470   int rip_offset() const { return int_at(offset_offset); }
return_address() const471   address return_address() const { return addr_at(instruction_length); }
got_address() const472   address got_address() const { return return_address() + rip_offset(); }
next_instruction_address() const473   address next_instruction_address() const { return return_address(); }
474   intptr_t data() const;
set_data(intptr_t data)475   void set_data(intptr_t data) {
476     intptr_t *addr = (intptr_t *) got_address();
477     *addr = data;
478   }
479 
480   void verify() const;
481 private:
482   void report_and_fail() const;
483 };
484 
nativeLoadGot_at(address addr)485 inline NativeLoadGot* nativeLoadGot_at(address addr) {
486   NativeLoadGot* load = (NativeLoadGot*) addr;
487 #ifdef ASSERT
488   load->verify();
489 #endif
490   return load;
491 }
492 
493 // jump rel32off
494 
495 class NativeJump: public NativeInstruction {
496  public:
497   enum Intel_specific_constants {
498     instruction_code            = 0xe9,
499     instruction_size            =    5,
500     instruction_offset          =    0,
501     data_offset                 =    1,
502     next_instruction_offset     =    5
503   };
504 
instruction_address() const505   address instruction_address() const       { return addr_at(instruction_offset); }
next_instruction_address() const506   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
jump_destination() const507   address jump_destination() const          {
508      address dest = (int_at(data_offset)+next_instruction_address());
509      // 32bit used to encode unresolved jmp as jmp -1
510      // 64bit can't produce this so it used jump to self.
511      // Now 32bit and 64bit use jump to self as the unresolved address
512      // which the inline cache code (and relocs) know about
513 
514      // return -1 if jump to self
515     dest = (dest == (address) this) ? (address) -1 : dest;
516     return dest;
517   }
518 
set_jump_destination(address dest)519   void  set_jump_destination(address dest)  {
520     intptr_t val = dest - next_instruction_address();
521     if (dest == (address) -1) {
522       val = -5; // jump to self
523     }
524 #ifdef AMD64
525     assert((labs(val)  & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
526 #endif // AMD64
527     set_int_at(data_offset, (jint)val);
528   }
529 
530   // Creation
531   inline friend NativeJump* nativeJump_at(address address);
532 
533   void verify();
534 
535   // Unit testing stuff
test()536   static void test() {}
537 
538   // Insertion of native jump instruction
539   static void insert(address code_pos, address entry);
540   // MT-safe insertion of native jump at verified method entry
541   static void check_verified_entry_alignment(address entry, address verified_entry);
542   static void patch_verified_entry(address entry, address verified_entry, address dest);
543 };
544 
nativeJump_at(address address)545 inline NativeJump* nativeJump_at(address address) {
546   NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
547 #ifdef ASSERT
548   jump->verify();
549 #endif
550   return jump;
551 }
552 
553 // far jump reg
554 class NativeFarJump: public NativeInstruction {
555  public:
556   address jump_destination() const;
557 
558   // Creation
559   inline friend NativeFarJump* nativeFarJump_at(address address);
560 
561   void verify();
562 
563   // Unit testing stuff
test()564   static void test() {}
565 
566 };
567 
nativeFarJump_at(address address)568 inline NativeFarJump* nativeFarJump_at(address address) {
569   NativeFarJump* jump = (NativeFarJump*)(address);
570 #ifdef ASSERT
571   jump->verify();
572 #endif
573   return jump;
574 }
575 
576 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional
577 class NativeGeneralJump: public NativeInstruction {
578  public:
579   enum Intel_specific_constants {
580     // Constants does not apply, since the lengths and offsets depends on the actual jump
581     // used
582     // Instruction codes:
583     //   Unconditional jumps: 0xE9    (rel32off), 0xEB (rel8off)
584     //   Conditional jumps:   0x0F8x  (rel32off), 0x7x (rel8off)
585     unconditional_long_jump  = 0xe9,
586     unconditional_short_jump = 0xeb,
587     instruction_size = 5
588   };
589 
instruction_address() const590   address instruction_address() const       { return addr_at(0); }
591   address jump_destination()    const;
592 
593   // Creation
594   inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
595 
596   // Insertion of native general jump instruction
597   static void insert_unconditional(address code_pos, address entry);
598   static void replace_mt_safe(address instr_addr, address code_buffer);
599 
600   void verify();
601 };
602 
nativeGeneralJump_at(address address)603 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
604   NativeGeneralJump* jump = (NativeGeneralJump*)(address);
605   debug_only(jump->verify();)
606   return jump;
607 }
608 
609 class NativeGotJump: public NativeInstruction {
610 public:
611   enum Intel_specific_constants {
612     instruction_code = 0xff,
613     instruction_offset = 0,
614     instruction_size = 6,
615     rip_offset = 2
616   };
617 
618   void verify() const;
instruction_address() const619   address instruction_address() const { return addr_at(instruction_offset); }
620   address destination() const;
return_address() const621   address return_address() const { return addr_at(instruction_size); }
got_offset() const622   int got_offset() const { return (jint) int_at(rip_offset); }
got_address() const623   address got_address() const { return return_address() + got_offset(); }
next_instruction_address() const624   address next_instruction_address() const { return addr_at(instruction_size); }
is_GotJump() const625   bool is_GotJump() const { return ubyte_at(0) == instruction_code; }
626 
set_jump_destination(address dest)627   void set_jump_destination(address dest)  {
628     address *got_entry = (address *) got_address();
629     *got_entry = dest;
630   }
631 };
632 
nativeGotJump_at(address addr)633 inline NativeGotJump* nativeGotJump_at(address addr) {
634   NativeGotJump* jump = (NativeGotJump*)(addr);
635   debug_only(jump->verify());
636   return jump;
637 }
638 
639 class NativePopReg : public NativeInstruction {
640  public:
641   enum Intel_specific_constants {
642     instruction_code            = 0x58,
643     instruction_size            =    1,
644     instruction_offset          =    0,
645     data_offset                 =    1,
646     next_instruction_offset     =    1
647   };
648 
649   // Insert a pop instruction
650   static void insert(address code_pos, Register reg);
651 };
652 
653 
654 class NativeIllegalInstruction: public NativeInstruction {
655  public:
656   enum Intel_specific_constants {
657     instruction_code            = 0x0B0F,    // Real byte order is: 0x0F, 0x0B
658     instruction_size            =    2,
659     instruction_offset          =    0,
660     next_instruction_offset     =    2
661   };
662 
663   // Insert illegal opcode as specific address
664   static void insert(address code_pos);
665 };
666 
667 // return instruction that does not pop values of the stack
668 class NativeReturn: public NativeInstruction {
669  public:
670   enum Intel_specific_constants {
671     instruction_code            = 0xC3,
672     instruction_size            =    1,
673     instruction_offset          =    0,
674     next_instruction_offset     =    1
675   };
676 };
677 
678 // return instruction that does pop values of the stack
679 class NativeReturnX: public NativeInstruction {
680  public:
681   enum Intel_specific_constants {
682     instruction_code            = 0xC2,
683     instruction_size            =    2,
684     instruction_offset          =    0,
685     next_instruction_offset     =    2
686   };
687 };
688 
689 // Simple test vs memory
690 class NativeTstRegMem: public NativeInstruction {
691  public:
692   enum Intel_specific_constants {
693     instruction_rex_prefix_mask = 0xF0,
694     instruction_rex_prefix      = Assembler::REX,
695     instruction_rex_b_prefix    = Assembler::REX_B,
696     instruction_code_memXregl   = 0x85,
697     modrm_mask                  = 0x38, // select reg from the ModRM byte
698     modrm_reg                   = 0x00  // rax
699   };
700 };
701 
is_illegal()702 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
is_call()703 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
is_call_reg()704 inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code ||
705                                                           (ubyte_at(1) == NativeCallReg::instruction_code &&
706                                                            (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
is_return()707 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
708                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
is_jump()709 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
710                                                           ubyte_at(0) == 0xEB; /* short jump */ }
is_jump_reg()711 inline bool NativeInstruction::is_jump_reg()     {
712   int pos = 0;
713   if (ubyte_at(0) == Assembler::REX_B) pos = 1;
714   return ubyte_at(pos) == 0xFF && (ubyte_at(pos + 1) & 0xF0) == 0xE0;
715 }
is_far_jump()716 inline bool NativeInstruction::is_far_jump()     { return is_mov_literal64(); }
is_cond_jump()717 inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
718                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
is_safepoint_poll()719 inline bool NativeInstruction::is_safepoint_poll() {
720   if (SafepointMechanism::uses_thread_local_poll()) {
721 #ifdef AMD64
722     const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
723     const int test_offset = has_rex_prefix ? 1 : 0;
724 #else
725     const int test_offset = 0;
726 #endif
727     const bool is_test_opcode = ubyte_at(test_offset) == NativeTstRegMem::instruction_code_memXregl;
728     const bool is_rax_target = (ubyte_at(test_offset + 1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
729     return is_test_opcode && is_rax_target;
730   }
731 #ifdef AMD64
732   // Try decoding a near safepoint first:
733   if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
734       ubyte_at(1) == 0x05) { // 00 rax 101
735     address fault = addr_at(6) + int_at(2);
736     NOT_JVMCI(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");)
737     return os::is_poll_address(fault);
738   }
739   // Now try decoding a far safepoint:
740   // two cases, depending on the choice of the base register in the address.
741   if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
742        ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
743        (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
744       (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
745        (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg)) {
746     NOT_JVMCI(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");)
747     return true;
748   }
749   return false;
750 #else
751   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
752            ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
753            (ubyte_at(1)&0xC7) == 0x05 && /* Mod R/M == disp32 */
754            (os::is_poll_address((address)int_at(2)));
755 #endif // AMD64
756 }
757 
is_mov_literal64()758 inline bool NativeInstruction::is_mov_literal64() {
759 #ifdef AMD64
760   return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
761           (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
762 #else
763   return false;
764 #endif // AMD64
765 }
766 
767 #endif // CPU_X86_NATIVEINST_X86_HPP
768