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