src/cpu/mips/vm/nativeInst_mips.hpp

Tue, 31 May 2016 00:22:06 -0400

author
aoqi
date
Tue, 31 May 2016 00:22:06 -0400
changeset 16
3cedde979d75
parent 1
2d8a650513c2
child 346
3a6b04bc4dd7
permissions
-rw-r--r--

[Code Reorganization] load_two_bytes_from_at_bcp -> get_2_byte_integer_at_bcp
remove useless MacroAssembler::store_two_byts_to_at_bcp
change MacroAssembler::load_two_bytes_from_at_bcp to InterpreterMacroAssembler::get_2_byte_integer_at_bcp
change MacroAssembler::get_4_byte_integer_at_bcp to InterpreterMacroAssembler::get_4_byte_integer_at_bcp

     1 /*
     2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     8  * published by the Free Software Foundation.
     9  *
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    13  * version 2 for more details (a copy is included in the LICENSE file that
    14  * accompanied this code).
    15  *
    16  * You should have received a copy of the GNU General Public License version
    17  * 2 along with this work; if not, write to the Free Software Foundation,
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    19  *
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * or visit www.oracle.com if you need additional information or have any
    22  * questions.
    23  *
    24  */
    26 #ifndef CPU_MIPS_VM_NATIVEINST_MIPS_HPP
    27 #define CPU_MIPS_VM_NATIVEINST_MIPS_HPP
    29 #include "asm/assembler.hpp"
    30 #include "memory/allocation.hpp"
    31 #include "runtime/icache.hpp"
    32 #include "runtime/os.hpp"
    33 #include "utilities/top.hpp"
    35 // We have interfaces for the following instructions:
    36 // - NativeInstruction
    37 // - - NativeCall
    38 // - - NativeMovConstReg
    39 // - - NativeMovConstRegPatching
    40 // - - NativeMovRegMem
    41 // - - NativeMovRegMemPatching
    42 // - - NativeJump
    43 // - - NativeIllegalOpCode
    44 // - - NativeGeneralJump
    45 // - - NativeReturn
    46 // - - NativeReturnX (return with argument)
    47 // - - NativePushConst
    48 // - - NativeTstRegMem
    50 // The base class for different kinds of native instruction abstractions.
    51 // Provides the primitive operations to manipulate code relative to this.
    53 class NativeInstruction VALUE_OBJ_CLASS_SPEC {
    54   friend class Relocation;
    56  public:
    57   enum mips_specific_constants {
    58     nop_instruction_code        =    0,	//sll zero, zero, zero
    59     nop_instruction_size        =    4
    60   };
    62   bool is_nop()                        { return long_at(0) == nop_instruction_code; }
    63   bool is_dtrace_trap();
    64   inline bool is_call();
    65   inline bool is_illegal();
    66   inline bool is_return();
    67   bool is_jump();
    68   inline bool is_cond_jump();
    69   bool is_safepoint_poll();
    71 	//mips has no instruction to generate a illegal instrucion exception
    72 	//we define ours: break 11 
    73 	static int illegal_instruction();
    75 	bool is_int_branch();
    76 	bool is_float_branch();
    79  protected:
    80   address addr_at(int offset) const    { return address(this) + offset; }
    81   address instruction_address() const       { return addr_at(0); }
    82   address next_instruction_address() const  { return addr_at(BytesPerInstWord); }
    83   address prev_instruction_address() const	{ return addr_at(-BytesPerInstWord); }
    85   s_char sbyte_at(int offset) const    { return *(s_char*) addr_at(offset); }
    86   u_char ubyte_at(int offset) const    { return *(u_char*) addr_at(offset); }
    87   jint int_at(int offset) const         { return *(jint*) addr_at(offset); }
    88   intptr_t ptr_at(int offset) const    { return *(intptr_t*) addr_at(offset); }
    89   oop  oop_at (int offset) const       { return *(oop*) addr_at(offset); }
    90   int  long_at(int offset) const       { return *(jint*)addr_at(offset); }
    93   void set_char_at(int offset, char c)        { *addr_at(offset) = (u_char)c; wrote(offset); }
    94   void set_int_at(int offset, jint  i)        { *(jint*)addr_at(offset) = i;  wrote(offset); }
    95   void set_ptr_at (int offset, intptr_t  ptr) { *(intptr_t*) addr_at(offset) = ptr;  wrote(offset); }
    96   void set_oop_at (int offset, oop  o)        { *(oop*) addr_at(offset) = o;  wrote(offset); }
    97   void set_long_at(int offset, long  i);
    98   //void set_jlong_at(int offset, jlong i);
    99   //void set_addr_at(int offset, address x);
   101   int  insn_word() const { return long_at(0); }
   102   static bool is_op (int insn, Assembler::ops op) { return Assembler::opcode(insn) == (int)op; }
   103   bool is_op (Assembler::ops op)     const { return is_op(insn_word(), op); }
   104   bool is_rs (int insn, Register rs) const { return Assembler::rs(insn) == (int)rs->encoding(); }
   105   bool is_rs (Register rs)           const { return is_rs(insn_word(), rs); }
   106   bool is_rt (int insn, Register rt) const { return Assembler::rt(insn) == (int)rt->encoding(); }
   107   bool is_rt (Register rt) 	     const { return is_rt(insn_word(), rt); }
   109   static bool is_special_op (int insn, Assembler::special_ops op) { 
   110     return is_op(insn, Assembler::special_op) && Assembler::special(insn)==(int)op; 
   111   }
   112   bool is_special_op (Assembler::special_ops op) const { return is_special_op(insn_word(), op); }
   114   // This doesn't really do anything on Intel, but it is the place where
   115   // cache invalidation belongs, generically:
   116   void wrote(int offset);
   118  public:
   120   // unit test stuff
   121   static void test() {}                 // override for testing
   123   inline friend NativeInstruction* nativeInstruction_at(address address);
   124 };
   126 inline NativeInstruction* nativeInstruction_at(address address) {
   127   NativeInstruction* inst = (NativeInstruction*)address;
   128 #ifdef ASSERT
   129   //inst->verify();
   130 #endif
   131   return inst;
   132 }
   134 inline NativeCall* nativeCall_at(address address);
   135 // The NativeCall is an abstraction for accessing/manipulating native call imm32/imm64
   136 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
   137 // MIPS has no call instruction with imm32/imm64. Usually, a call was done like this:
   138 // 32 bits:
   139 // 			lui 		rt, imm16
   140 // 			addiu		rt, rt, imm16
   141 // 			jalr 		rt
   142 //			nop
   143 // 			
   144 // 64 bits:
   145 //    		    lui   rd, imm(63...48);
   146 //		    ori   rd, rd, imm(47...32);
   147 //		    dsll  rd, rd, 16;
   148 //		    ori   rd, rd, imm(31...16);
   149 //		    dsll  rd, rd, 16;
   150 //		    ori   rd, rd, imm(15...0);
   151 //		    jalr  rd
   152 //      	    nop
   153 //		    
   155 // we just consider the above for instruction as one call instruction
   156 class NativeCall: public NativeInstruction {
   157   public:
   158     enum mips_specific_constants {
   159       instruction_offset          =    0,
   160 #ifndef _LP64
   161       instruction_size            =   4 * BytesPerInstWord,
   162       return_address_offset       =   4 * BytesPerInstWord,
   163 #else
   164       instruction_size            =   6 * BytesPerInstWord,
   165       return_address_offset       =   6 * BytesPerInstWord,
   166 #endif
   167       displacement_offset         =    0
   168     };
   170     address instruction_address() const       { return addr_at(instruction_offset); }
   171     address next_instruction_address() const  { return addr_at(return_address_offset); }
   172     address return_address() const            { return addr_at(return_address_offset); }
   173     address destination() const;
   174     void  set_destination(address dest);
   175     void  set_destination_mt_safe(address dest) { set_destination(dest);}
   177     void  verify_alignment() {  }
   178     void  verify();
   179     void  print();
   181     // Creation
   182     inline friend NativeCall* nativeCall_at(address address);
   183     inline friend NativeCall* nativeCall_before(address return_address);
   185     static bool is_call_at(address instr) {
   186       return nativeInstruction_at(instr)->is_call();
   187     }
   189     static bool is_call_before(address return_address) {
   190       return is_call_at(return_address - NativeCall::return_address_offset);
   191     }
   193     static bool is_call_to(address instr, address target) {
   194       return nativeInstruction_at(instr)->is_call() &&
   195 	nativeCall_at(instr)->destination() == target;
   196     }
   198     // MT-safe patching of a call instruction.
   199     static void insert(address code_pos, address entry);
   201     static void replace_mt_safe(address instr_addr, address code_buffer);
   202 };
   204 inline NativeCall* nativeCall_at(address address) {
   205   NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
   206 #ifdef ASSERT
   207   call->verify();
   208 #endif
   209   return call;
   210 }
   212 inline NativeCall* nativeCall_before(address return_address) {
   213   NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
   214 #ifdef ASSERT
   215   call->verify();
   216 #endif
   217   return call;
   218 }
   220 // An interface for accessing/manipulating native mov reg, imm32 instructions.
   221 // (used to manipulate inlined 32bit data dll calls, etc.)
   222 //we use two instructions to implement this:
   223 //		lui rd, imm16
   224 //		addiu rd, immm16
   225 //see MacroAssembler::move(Register, int)
   226 class NativeMovConstReg: public NativeInstruction {
   227  public:
   228   enum mips_specific_constants {
   229     instruction_offset  	=    0,
   230 #ifndef _LP64
   231     instruction_size  	      	=    2 * BytesPerInstWord,
   232     next_instruction_offset 	=    2 * BytesPerInstWord,
   233 #else
   234     instruction_size  	      	=    4 * BytesPerInstWord,
   235     next_instruction_offset 	=    4 * BytesPerInstWord,
   236 #endif
   237   };
   239   int     insn_word() const                 { return long_at(instruction_offset); }
   240   address instruction_address() const       { return addr_at(0); }
   241   address next_instruction_address() const  { return addr_at(next_instruction_offset); }
   242   intptr_t data() const;
   243   void    set_data(intptr_t x);
   246   void  verify();
   247   void  print();
   249   // unit test stuff
   250   static void test() {}
   252   // Creation
   253   inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
   254   inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
   255 };
   257 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
   258   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
   259 #ifdef ASSERT
   260   test->verify();
   261 #endif
   262   return test;
   263 }
   265 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
   266   NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
   267 #ifdef ASSERT
   268   test->verify();
   269 #endif
   270   return test;
   271 }
   273 class NativeMovConstRegPatching: public NativeMovConstReg {
   274  private:
   275     friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
   276     NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
   277     #ifdef ASSERT
   278       test->verify();
   279     #endif
   280     return test;
   281   }
   282 };
   284 // An interface for accessing/manipulating native moves of the form:
   285 // 			lui   AT, split_high(offset)
   286 // 			addiu AT, split_low(offset)
   287 // 			add   reg, reg, AT
   288 // 			lb/lbu/sb/lh/lhu/sh/lw/sw/lwc1/swc1 dest, reg, 0
   289 // 			[lw/sw/lwc1/swc1                    dest, reg, 4]
   290 // 		or 
   291 // 			lb/lbu/sb/lh/lhu/sh/lw/sw/lwc1/swc1 dest, reg, offset
   292 // 			[lw/sw/lwc1/swc1                    dest, reg, offset+4]
   293 //
   294 // Warning: These routines must be able to handle any instruction sequences
   295 // that are generated as a result of the load/store byte,word,long
   296 // macros.  
   298 class NativeMovRegMem: public NativeInstruction {
   299  public:
   300   enum mips_specific_constants {
   301     instruction_offset  = 0,
   302     hiword_offset 	= 4,
   303     ldst_offset   	= 12,
   304     immediate_size	= 4,
   305     ldst_size     	= 16
   306   };
   308   //offset is less than 16 bits.
   309   bool is_immediate() const { return !is_op(long_at(instruction_offset), Assembler::lui_op); }
   310   bool is_64ldst() const {
   311     if (is_immediate()) {
   312       return (Assembler::opcode(long_at(hiword_offset)) == Assembler::opcode(long_at(instruction_offset))) &&
   313 	     (Assembler::imm_off(long_at(hiword_offset)) == Assembler::imm_off(long_at(instruction_offset)) + wordSize);
   314     } else {
   315       return (Assembler::opcode(long_at(ldst_offset+hiword_offset)) == Assembler::opcode(long_at(ldst_offset))) &&
   316 	     (Assembler::imm_off(long_at(ldst_offset+hiword_offset)) == Assembler::imm_off(long_at(ldst_offset)) + wordSize);
   317     }
   318   }
   320   address instruction_address() const       { return addr_at(instruction_offset); }
   321   address next_instruction_address() const  { 
   322     return addr_at( (is_immediate()? immediate_size : ldst_size) + (is_64ldst()? 4 : 0));  
   323   }
   324 /*  // helper
   325   int instruction_start() const;
   327   address instruction_address() const;
   329   address next_instruction_address() const;
   330 */
   332   int   offset() const;
   334   void  set_offset(int x);
   336   void  add_offset_in_bytes(int add_offset)     { set_offset ( ( offset() + add_offset ) ); }
   338   void verify();
   339   void print ();
   341   // unit test stuff
   342   static void test() {}
   344  private:
   345   inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
   346 };
   348 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
   349   NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
   350 #ifdef ASSERT
   351   test->verify();
   352 #endif
   353   return test;
   354 }
   356 class NativeMovRegMemPatching: public NativeMovRegMem {
   357  private:
   358   friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {
   359     NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)(address - instruction_offset);
   360     #ifdef ASSERT
   361       test->verify();
   362     #endif
   363     return test;
   364   }
   365 };
   368 // Handles all kinds of jump on Loongson. Long/far, conditional/unconditional
   369 // 32 bits:
   370 //    far jump:
   371 //				lui   reg, split_high(addr)
   372 //				addiu reg, split_low(addr)
   373 //				jr    reg
   374 //				nop
   375 //    or 
   376 //				beq 	ZERO, ZERO, offset
   377 //				nop
   378 //
   380 //64 bits:
   381 //    far jump:
   382 //			    lui   rd, imm(63...48);
   383 //			    ori   rd, rd, imm(47...32);
   384 //			    dsll  rd, rd, 16;
   385 //			    ori   rd, rd, imm(31...16);
   386 //			    dsll  rd, rd, 16;
   387 //			    ori   rd, rd, imm(15...0);
   388 //			    jalr  rd
   389 //			    nop
   390 //		    
   391 class NativeGeneralJump: public NativeInstruction {
   392 public:
   393   enum mips_specific_constants {
   394     instruction_offset 	=    0,
   395     beq_opcode         	=    0x10000000,//000100|00000|00000|offset
   396     b_mask       	=    0xffff0000,
   397     short_size    	=    8,
   398 #ifndef _LP64
   399     instruction_size   =    4 * BytesPerInstWord
   400 #else
   401     instruction_size   =    6 * BytesPerInstWord
   402 #endif
   403   };
   405   bool is_short() const { return (long_at(instruction_offset) & b_mask) == beq_opcode; }
   406 #ifdef _LP64
   407   bool is_b_far();
   408 #endif
   409   address instruction_address() const { return addr_at(instruction_offset); }
   410   address jump_destination();
   412   void  set_jump_destination(address dest);
   414 	// Creation
   415   inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
   417 	// Insertion of native general jump instruction
   418   static void insert_unconditional(address code_pos, address entry);
   419   static void replace_mt_safe(address instr_addr, address code_buffer);
   420   static void check_verified_entry_alignment(address entry, address verified_entry){}
   421   static void patch_verified_entry(address entry, address verified_entry, address dest);
   423   void verify();
   424 };
   426 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
   427   NativeGeneralJump* jump = (NativeGeneralJump*)(address);
   428   debug_only(jump->verify();)
   429   return jump;
   430 }
   432 /*class NativePopReg : public NativeInstruction {
   433   public:
   434   enum Intel_specific_constants {
   435   instruction_code            = 0x58,
   436   instruction_size            =    1,
   437   instruction_offset          =    0,
   438   data_offset                 =    1,
   439   next_instruction_offset     =    1
   440   };
   442 // Insert a pop instruction
   443 static void insert(address code_pos, Register reg);
   444 };*/
   447 class NativeIllegalInstruction: public NativeInstruction {
   448 public:
   449   enum Intel_specific_constants {
   450     instruction_size          =    4,
   451     instruction_offset        =    0,
   452     next_instruction_offset   =    4
   453   };
   455   // Insert illegal opcode as specific address
   456   static void insert(address code_pos);
   457 };
   459 // return instruction that does not pop values of the stack
   460 // jr RA
   461 // delay slot
   462 class NativeReturn: public NativeInstruction {
   463 public:
   464   enum mips_specific_constants {
   465     instruction_size          =    8,
   466     instruction_offset        =    0,
   467     next_instruction_offset   =    8
   468   };
   469 };
   474 class NativeCondJump;
   475 inline NativeCondJump* nativeCondJump_at(address address);
   476 class NativeCondJump: public NativeInstruction {
   477 public:
   478   enum mips_specific_constants {
   479     instruction_size 	      = 16,
   480     instruction_offset        = 12,
   481     next_instruction_offset   = 20
   482   };
   485   int insn_word() const  { return long_at(instruction_offset); }
   486   address instruction_address() const { return addr_at(0); }
   487   address next_instruction_address() const { return addr_at(next_instruction_offset); }
   489   // Creation
   490   inline friend NativeCondJump* nativeCondJump_at(address address);
   492   address jump_destination()  const {
   493     return ::nativeCondJump_at(addr_at(12))->jump_destination();
   494   }
   496   void set_jump_destination(address dest) {
   497     ::nativeCondJump_at(addr_at(12))->set_jump_destination(dest);
   498   }
   500 };	
   502 inline NativeCondJump* nativeCondJump_at(address address) {
   503   NativeCondJump* jump = (NativeCondJump*)(address);
   504   return jump;
   505 }
   509 inline bool NativeInstruction::is_illegal() { return insn_word() == illegal_instruction(); }
   511 inline bool NativeInstruction::is_call()    { 
   512 #ifndef _LP64
   513   return is_op(long_at(0), Assembler::lui_op) &&
   514          is_op(long_at(4), Assembler::addiu_op) &&
   515 	 is_special_op(long_at(8), Assembler::jalr_op);
   516 #else
   517   /* li64 or li48 */
   518   if (is_special_op(long_at(16), Assembler::dsll_op)) {
   519   /* li64 */
   520     return is_op(long_at(0), Assembler::lui_op) &&
   521            is_op(long_at(4), Assembler::ori_op) &&
   522            is_special_op(long_at(8), Assembler::dsll_op) &&
   523            is_op(long_at(12), Assembler::ori_op) &&
   524            is_special_op(long_at(16), Assembler::dsll_op) &&
   525            is_op(long_at(20), Assembler::ori_op) &&
   526 	   is_special_op(long_at(24), Assembler::jalr_op);
   527   } else {
   528   /* li48 */
   529     return is_op(long_at(0), Assembler::lui_op) &&
   530            is_op(long_at(4), Assembler::ori_op) &&
   531            is_special_op(long_at(8), Assembler::dsll_op) &&
   532            is_op(long_at(12), Assembler::ori_op) &&
   533 	   is_special_op(long_at(16), Assembler::jalr_op);
   534   }
   535 #endif
   536 }
   538 inline bool NativeInstruction::is_return()  { return is_special_op(Assembler::jr_op) && is_rs(RA);}
   540 inline bool NativeInstruction::is_cond_jump()    { return is_int_branch() || is_float_branch(); }
   541 #endif // CPU_MIPS_VM_NATIVEINST_MIPS_HPP

mercurial