nativeInst_x86.hpp revision 9111:a41fe5ffa839
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
52class 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_call_reg();
64  inline bool is_illegal();
65  inline bool is_return();
66  inline bool is_jump();
67  inline bool is_cond_jump();
68  inline bool is_safepoint_poll();
69  inline bool is_mov_literal64();
70
71 protected:
72  address addr_at(int offset) const    { return address(this) + offset; }
73
74  s_char sbyte_at(int offset) const    { return *(s_char*) addr_at(offset); }
75  u_char ubyte_at(int offset) const    { return *(u_char*) addr_at(offset); }
76
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, char c)        { *addr_at(offset) = (u_char)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
95  // unit test stuff
96  static void test() {}                 // override for testing
97
98  inline friend NativeInstruction* nativeInstruction_at(address address);
99};
100
101inline NativeInstruction* nativeInstruction_at(address address) {
102  NativeInstruction* inst = (NativeInstruction*)address;
103#ifdef ASSERT
104  //inst->verify();
105#endif
106  return inst;
107}
108
109inline NativeCall* nativeCall_at(address address);
110// The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
111// instructions (used to manipulate inline caches, primitive & dll calls, etc.).
112
113class NativeCall: public NativeInstruction {
114 public:
115  enum Intel_specific_constants {
116    instruction_code            = 0xE8,
117    instruction_size            =    5,
118    instruction_offset          =    0,
119    displacement_offset         =    1,
120    return_address_offset       =    5
121  };
122
123  enum { cache_line_size = BytesPerWord };  // conservative estimate!
124
125  address instruction_address() const       { return addr_at(instruction_offset); }
126  address next_instruction_address() const  { return addr_at(return_address_offset); }
127  int   displacement() const                { return (jint) int_at(displacement_offset); }
128  address displacement_address() const      { return addr_at(displacement_offset); }
129  address return_address() const            { return addr_at(return_address_offset); }
130  address destination() const;
131  void  set_destination(address dest)       {
132#ifdef AMD64
133    assert((labs((intptr_t) dest - (intptr_t) return_address())  &
134            0xFFFFFFFF00000000) == 0,
135           "must be 32bit offset");
136#endif // AMD64
137    set_int_at(displacement_offset, dest - return_address());
138  }
139  void  set_destination_mt_safe(address dest);
140
141  void  verify_alignment() { assert((intptr_t)addr_at(displacement_offset) % BytesPerInt == 0, "must be aligned"); }
142  void  verify();
143  void  print();
144
145  // Creation
146  inline friend NativeCall* nativeCall_at(address address);
147  inline friend NativeCall* nativeCall_before(address return_address);
148
149  static bool is_call_at(address instr) {
150    return ((*instr) & 0xFF) == NativeCall::instruction_code;
151  }
152
153  static bool is_call_before(address return_address) {
154    return is_call_at(return_address - NativeCall::return_address_offset);
155  }
156
157  static bool is_call_to(address instr, address target) {
158    return nativeInstruction_at(instr)->is_call() &&
159      nativeCall_at(instr)->destination() == target;
160  }
161
162  // MT-safe patching of a call instruction.
163  static void insert(address code_pos, address entry);
164
165  static void replace_mt_safe(address instr_addr, address code_buffer);
166};
167
168inline NativeCall* nativeCall_at(address address) {
169  NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
170#ifdef ASSERT
171  call->verify();
172#endif
173  return call;
174}
175
176inline NativeCall* nativeCall_before(address return_address) {
177  NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
178#ifdef ASSERT
179  call->verify();
180#endif
181  return call;
182}
183
184class NativeCallReg: public NativeInstruction {
185 public:
186  enum Intel_specific_constants {
187    instruction_code            = 0xFF,
188    instruction_offset          =    0,
189    return_address_offset_norex =    2,
190    return_address_offset_rex   =    3
191  };
192
193  int next_instruction_offset() const  {
194    if (ubyte_at(0) == NativeCallReg::instruction_code) {
195      return return_address_offset_norex;
196    } else {
197      return return_address_offset_rex;
198    }
199  }
200};
201
202// An interface for accessing/manipulating native mov reg, imm32 instructions.
203// (used to manipulate inlined 32bit data dll calls, etc.)
204class NativeMovConstReg: public NativeInstruction {
205#ifdef AMD64
206  static const bool has_rex = true;
207  static const int rex_size = 1;
208#else
209  static const bool has_rex = false;
210  static const int rex_size = 0;
211#endif // AMD64
212 public:
213  enum Intel_specific_constants {
214    instruction_code            = 0xB8,
215    instruction_size            =    1 + rex_size + wordSize,
216    instruction_offset          =    0,
217    data_offset                 =    1 + rex_size,
218    next_instruction_offset     =    instruction_size,
219    register_mask               = 0x07
220  };
221
222  address instruction_address() const       { return addr_at(instruction_offset); }
223  address next_instruction_address() const  { return addr_at(next_instruction_offset); }
224  intptr_t data() const                     { return ptr_at(data_offset); }
225  void  set_data(intptr_t x)                { set_ptr_at(data_offset, x); }
226
227  void  verify();
228  void  print();
229
230  // unit test stuff
231  static void test() {}
232
233  // Creation
234  inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
235  inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
236};
237
238inline NativeMovConstReg* nativeMovConstReg_at(address address) {
239  NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
240#ifdef ASSERT
241  test->verify();
242#endif
243  return test;
244}
245
246inline NativeMovConstReg* nativeMovConstReg_before(address address) {
247  NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
248#ifdef ASSERT
249  test->verify();
250#endif
251  return test;
252}
253
254class NativeMovConstRegPatching: public NativeMovConstReg {
255 private:
256    friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
257    NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
258    #ifdef ASSERT
259      test->verify();
260    #endif
261    return test;
262  }
263};
264
265// An interface for accessing/manipulating native moves of the form:
266//      mov[b/w/l/q] [reg + offset], reg   (instruction_code_reg2mem)
267//      mov[b/w/l/q] reg, [reg+offset]     (instruction_code_mem2reg
268//      mov[s/z]x[w/b/q] [reg + offset], reg
269//      fld_s  [reg+offset]
270//      fld_d  [reg+offset]
271//      fstp_s [reg + offset]
272//      fstp_d [reg + offset]
273//      mov_literal64  scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
274//
275// Warning: These routines must be able to handle any instruction sequences
276// that are generated as a result of the load/store byte,word,long
277// macros.  For example: The load_unsigned_byte instruction generates
278// an xor reg,reg inst prior to generating the movb instruction.  This
279// class must skip the xor instruction.
280
281class NativeMovRegMem: public NativeInstruction {
282 public:
283  enum Intel_specific_constants {
284    instruction_prefix_wide_lo          = Assembler::REX,
285    instruction_prefix_wide_hi          = Assembler::REX_WRXB,
286    instruction_code_xor                = 0x33,
287    instruction_extended_prefix         = 0x0F,
288    instruction_code_mem2reg_movslq     = 0x63,
289    instruction_code_mem2reg_movzxb     = 0xB6,
290    instruction_code_mem2reg_movsxb     = 0xBE,
291    instruction_code_mem2reg_movzxw     = 0xB7,
292    instruction_code_mem2reg_movsxw     = 0xBF,
293    instruction_operandsize_prefix      = 0x66,
294    instruction_code_reg2mem            = 0x89,
295    instruction_code_mem2reg            = 0x8b,
296    instruction_code_reg2memb           = 0x88,
297    instruction_code_mem2regb           = 0x8a,
298    instruction_code_float_s            = 0xd9,
299    instruction_code_float_d            = 0xdd,
300    instruction_code_long_volatile      = 0xdf,
301    instruction_code_xmm_ss_prefix      = 0xf3,
302    instruction_code_xmm_sd_prefix      = 0xf2,
303    instruction_code_xmm_code           = 0x0f,
304    instruction_code_xmm_load           = 0x10,
305    instruction_code_xmm_store          = 0x11,
306    instruction_code_xmm_lpd            = 0x12,
307
308    instruction_VEX_prefix_2bytes       = Assembler::VEX_2bytes,
309    instruction_VEX_prefix_3bytes       = Assembler::VEX_3bytes,
310
311    instruction_size                    = 4,
312    instruction_offset                  = 0,
313    data_offset                         = 2,
314    next_instruction_offset             = 4
315  };
316
317  // helper
318  int instruction_start() const;
319
320  address instruction_address() const;
321
322  address next_instruction_address() const;
323
324  int   offset() const;
325
326  void  set_offset(int x);
327
328  void  add_offset_in_bytes(int add_offset)     { set_offset ( ( offset() + add_offset ) ); }
329
330  void verify();
331  void print ();
332
333  // unit test stuff
334  static void test() {}
335
336 private:
337  inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
338};
339
340inline NativeMovRegMem* nativeMovRegMem_at (address address) {
341  NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
342#ifdef ASSERT
343  test->verify();
344#endif
345  return test;
346}
347
348
349// An interface for accessing/manipulating native leal instruction of form:
350//        leal reg, [reg + offset]
351
352class NativeLoadAddress: public NativeMovRegMem {
353#ifdef AMD64
354  static const bool has_rex = true;
355  static const int rex_size = 1;
356#else
357  static const bool has_rex = false;
358  static const int rex_size = 0;
359#endif // AMD64
360 public:
361  enum Intel_specific_constants {
362    instruction_prefix_wide             = Assembler::REX_W,
363    instruction_prefix_wide_extended    = Assembler::REX_WB,
364    lea_instruction_code                = 0x8D,
365    mov64_instruction_code              = 0xB8
366  };
367
368  void verify();
369  void print ();
370
371  // unit test stuff
372  static void test() {}
373
374 private:
375  friend NativeLoadAddress* nativeLoadAddress_at (address address) {
376    NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
377    #ifdef ASSERT
378      test->verify();
379    #endif
380    return test;
381  }
382};
383
384// jump rel32off
385
386class NativeJump: public NativeInstruction {
387 public:
388  enum Intel_specific_constants {
389    instruction_code            = 0xe9,
390    instruction_size            =    5,
391    instruction_offset          =    0,
392    data_offset                 =    1,
393    next_instruction_offset     =    5
394  };
395
396  address instruction_address() const       { return addr_at(instruction_offset); }
397  address next_instruction_address() const  { return addr_at(next_instruction_offset); }
398  address jump_destination() const          {
399     address dest = (int_at(data_offset)+next_instruction_address());
400     // 32bit used to encode unresolved jmp as jmp -1
401     // 64bit can't produce this so it used jump to self.
402     // Now 32bit and 64bit use jump to self as the unresolved address
403     // which the inline cache code (and relocs) know about
404
405     // return -1 if jump to self
406    dest = (dest == (address) this) ? (address) -1 : dest;
407    return dest;
408  }
409
410  void  set_jump_destination(address dest)  {
411    intptr_t val = dest - next_instruction_address();
412    if (dest == (address) -1) {
413      val = -5; // jump to self
414    }
415#ifdef AMD64
416    assert((labs(val)  & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
417#endif // AMD64
418    set_int_at(data_offset, (jint)val);
419  }
420
421  // Creation
422  inline friend NativeJump* nativeJump_at(address address);
423
424  void verify();
425
426  // Unit testing stuff
427  static void test() {}
428
429  // Insertion of native jump instruction
430  static void insert(address code_pos, address entry);
431  // MT-safe insertion of native jump at verified method entry
432  static void check_verified_entry_alignment(address entry, address verified_entry);
433  static void patch_verified_entry(address entry, address verified_entry, address dest);
434};
435
436inline NativeJump* nativeJump_at(address address) {
437  NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
438#ifdef ASSERT
439  jump->verify();
440#endif
441  return jump;
442}
443
444// Handles all kinds of jump on Intel. Long/far, conditional/unconditional
445class NativeGeneralJump: public NativeInstruction {
446 public:
447  enum Intel_specific_constants {
448    // Constants does not apply, since the lengths and offsets depends on the actual jump
449    // used
450    // Instruction codes:
451    //   Unconditional jumps: 0xE9    (rel32off), 0xEB (rel8off)
452    //   Conditional jumps:   0x0F8x  (rel32off), 0x7x (rel8off)
453    unconditional_long_jump  = 0xe9,
454    unconditional_short_jump = 0xeb,
455    instruction_size = 5
456  };
457
458  address instruction_address() const       { return addr_at(0); }
459  address jump_destination()    const;
460
461  // Creation
462  inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
463
464  // Insertion of native general jump instruction
465  static void insert_unconditional(address code_pos, address entry);
466  static void replace_mt_safe(address instr_addr, address code_buffer);
467
468  void verify();
469};
470
471inline NativeGeneralJump* nativeGeneralJump_at(address address) {
472  NativeGeneralJump* jump = (NativeGeneralJump*)(address);
473  debug_only(jump->verify();)
474  return jump;
475}
476
477class NativePopReg : public NativeInstruction {
478 public:
479  enum Intel_specific_constants {
480    instruction_code            = 0x58,
481    instruction_size            =    1,
482    instruction_offset          =    0,
483    data_offset                 =    1,
484    next_instruction_offset     =    1
485  };
486
487  // Insert a pop instruction
488  static void insert(address code_pos, Register reg);
489};
490
491
492class NativeIllegalInstruction: public NativeInstruction {
493 public:
494  enum Intel_specific_constants {
495    instruction_code            = 0x0B0F,    // Real byte order is: 0x0F, 0x0B
496    instruction_size            =    2,
497    instruction_offset          =    0,
498    next_instruction_offset     =    2
499  };
500
501  // Insert illegal opcode as specific address
502  static void insert(address code_pos);
503};
504
505// return instruction that does not pop values of the stack
506class NativeReturn: public NativeInstruction {
507 public:
508  enum Intel_specific_constants {
509    instruction_code            = 0xC3,
510    instruction_size            =    1,
511    instruction_offset          =    0,
512    next_instruction_offset     =    1
513  };
514};
515
516// return instruction that does pop values of the stack
517class NativeReturnX: public NativeInstruction {
518 public:
519  enum Intel_specific_constants {
520    instruction_code            = 0xC2,
521    instruction_size            =    2,
522    instruction_offset          =    0,
523    next_instruction_offset     =    2
524  };
525};
526
527// Simple test vs memory
528class NativeTstRegMem: public NativeInstruction {
529 public:
530  enum Intel_specific_constants {
531    instruction_rex_prefix_mask = 0xF0,
532    instruction_rex_prefix      = Assembler::REX,
533    instruction_code_memXregl   = 0x85,
534    modrm_mask                  = 0x38, // select reg from the ModRM byte
535    modrm_reg                   = 0x00  // rax
536  };
537};
538
539inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
540inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
541inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code ||
542                                                          (ubyte_at(1) == NativeCallReg::instruction_code &&
543                                                           (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
544inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
545                                                          ubyte_at(0) == NativeReturnX::instruction_code; }
546inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
547                                                          ubyte_at(0) == 0xEB; /* short jump */ }
548inline bool NativeInstruction::is_cond_jump()    { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
549                                                          (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
550inline bool NativeInstruction::is_safepoint_poll() {
551#ifdef AMD64
552  // Try decoding a near safepoint first:
553  if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
554      ubyte_at(1) == 0x05) { // 00 rax 101
555    address fault = addr_at(6) + int_at(2);
556    NOT_JVMCI(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");)
557    return os::is_poll_address(fault);
558  }
559  // Now try decoding a far safepoint:
560  // two cases, depending on the choice of the base register in the address.
561  if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
562       ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
563       (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
564      ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
565      (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
566    NOT_JVMCI(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");)
567    return true;
568  }
569  return false;
570#else
571  return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
572           ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
573           (ubyte_at(1)&0xC7) == 0x05 && /* Mod R/M == disp32 */
574           (os::is_poll_address((address)int_at(2)));
575#endif // AMD64
576}
577
578inline bool NativeInstruction::is_mov_literal64() {
579#ifdef AMD64
580  return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
581          (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
582#else
583  return false;
584#endif // AMD64
585}
586
587#endif // CPU_X86_VM_NATIVEINST_X86_HPP
588