src/cpu/mips/vm/nativeInst_mips.hpp

Thu, 24 May 2018 19:49:50 +0800

author
aoqi
date
Thu, 24 May 2018 19:49:50 +0800
changeset 8865
ffcdff41a92f
parent 8863
5376ce0dc552
child 9146
4c971a763d55
permissions
-rw-r--r--

some C1 fix
Contributed-by: chenhaoxuan, zhaixiang, aoqi

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
aoqi@8863 3 * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved.
aoqi@1 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@1 5 *
aoqi@1 6 * This code is free software; you can redistribute it and/or modify it
aoqi@1 7 * under the terms of the GNU General Public License version 2 only, as
aoqi@1 8 * published by the Free Software Foundation.
aoqi@1 9 *
aoqi@1 10 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@1 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@1 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@1 13 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@1 14 * accompanied this code).
aoqi@1 15 *
aoqi@1 16 * You should have received a copy of the GNU General Public License version
aoqi@1 17 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@1 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@1 19 *
aoqi@1 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@1 21 * or visit www.oracle.com if you need additional information or have any
aoqi@1 22 * questions.
aoqi@1 23 *
aoqi@1 24 */
aoqi@1 25
aoqi@1 26 #ifndef CPU_MIPS_VM_NATIVEINST_MIPS_HPP
aoqi@1 27 #define CPU_MIPS_VM_NATIVEINST_MIPS_HPP
aoqi@1 28
aoqi@1 29 #include "asm/assembler.hpp"
aoqi@1 30 #include "memory/allocation.hpp"
aoqi@1 31 #include "runtime/icache.hpp"
aoqi@1 32 #include "runtime/os.hpp"
aoqi@1 33 #include "utilities/top.hpp"
aoqi@1 34
aoqi@1 35 // We have interfaces for the following instructions:
aoqi@1 36 // - NativeInstruction
aoqi@1 37 // - - NativeCall
aoqi@1 38 // - - NativeMovConstReg
aoqi@1 39 // - - NativeMovConstRegPatching
aoqi@1 40 // - - NativeMovRegMem
aoqi@1 41 // - - NativeMovRegMemPatching
aoqi@1 42 // - - NativeJump
aoqi@1 43 // - - NativeIllegalOpCode
aoqi@1 44 // - - NativeGeneralJump
aoqi@1 45 // - - NativeReturn
aoqi@1 46 // - - NativeReturnX (return with argument)
aoqi@1 47 // - - NativePushConst
aoqi@1 48 // - - NativeTstRegMem
aoqi@1 49
aoqi@1 50 // The base class for different kinds of native instruction abstractions.
aoqi@1 51 // Provides the primitive operations to manipulate code relative to this.
aoqi@1 52
aoqi@1 53 class NativeInstruction VALUE_OBJ_CLASS_SPEC {
aoqi@1 54 friend class Relocation;
aoqi@1 55
aoqi@1 56 public:
aoqi@1 57 enum mips_specific_constants {
fujie@346 58 nop_instruction_code = 0,
aoqi@8023 59 nop_instruction_size = 4,
aoqi@8023 60 sync_instruction_code = 0xf
aoqi@1 61 };
aoqi@1 62
aoqi@1 63 bool is_nop() { return long_at(0) == nop_instruction_code; }
aoqi@8023 64 bool is_sync() { return long_at(0) == sync_instruction_code; }
aoqi@1 65 bool is_dtrace_trap();
aoqi@1 66 inline bool is_call();
aoqi@1 67 inline bool is_illegal();
aoqi@1 68 inline bool is_return();
aoqi@1 69 bool is_jump();
aoqi@1 70 inline bool is_cond_jump();
aoqi@1 71 bool is_safepoint_poll();
aoqi@6880 72
fujie@346 73 //mips has no instruction to generate a illegal instrucion exception
aoqi@6880 74 //we define ours: break 11
fujie@346 75 static int illegal_instruction();
aoqi@6880 76
fujie@346 77 bool is_int_branch();
fujie@346 78 bool is_float_branch();
aoqi@1 79
aoqi@1 80
aoqi@1 81 protected:
aoqi@1 82 address addr_at(int offset) const { return address(this) + offset; }
aoqi@1 83 address instruction_address() const { return addr_at(0); }
aoqi@1 84 address next_instruction_address() const { return addr_at(BytesPerInstWord); }
aoqi@6880 85 address prev_instruction_address() const { return addr_at(-BytesPerInstWord); }
aoqi@6880 86
aoqi@1 87 s_char sbyte_at(int offset) const { return *(s_char*) addr_at(offset); }
aoqi@1 88 u_char ubyte_at(int offset) const { return *(u_char*) addr_at(offset); }
aoqi@6880 89
aoqi@1 90 jint int_at(int offset) const { return *(jint*) addr_at(offset); }
aoqi@6880 91
aoqi@1 92 intptr_t ptr_at(int offset) const { return *(intptr_t*) addr_at(offset); }
aoqi@6880 93
aoqi@1 94 oop oop_at (int offset) const { return *(oop*) addr_at(offset); }
aoqi@1 95 int long_at(int offset) const { return *(jint*)addr_at(offset); }
aoqi@1 96
aoqi@1 97
aoqi@1 98 void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; wrote(offset); }
aoqi@1 99 void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; wrote(offset); }
aoqi@1 100 void set_ptr_at (int offset, intptr_t ptr) { *(intptr_t*) addr_at(offset) = ptr; wrote(offset); }
aoqi@1 101 void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; wrote(offset); }
aoqi@1 102 void set_long_at(int offset, long i);
aoqi@1 103
aoqi@1 104 int insn_word() const { return long_at(0); }
aoqi@1 105 static bool is_op (int insn, Assembler::ops op) { return Assembler::opcode(insn) == (int)op; }
aoqi@1 106 bool is_op (Assembler::ops op) const { return is_op(insn_word(), op); }
aoqi@1 107 bool is_rs (int insn, Register rs) const { return Assembler::rs(insn) == (int)rs->encoding(); }
aoqi@1 108 bool is_rs (Register rs) const { return is_rs(insn_word(), rs); }
aoqi@1 109 bool is_rt (int insn, Register rt) const { return Assembler::rt(insn) == (int)rt->encoding(); }
aoqi@6880 110 bool is_rt (Register rt) const { return is_rt(insn_word(), rt); }
aoqi@1 111
aoqi@6880 112 static bool is_special_op (int insn, Assembler::special_ops op) {
aoqi@6880 113 return is_op(insn, Assembler::special_op) && Assembler::special(insn)==(int)op;
aoqi@1 114 }
aoqi@1 115 bool is_special_op (Assembler::special_ops op) const { return is_special_op(insn_word(), op); }
aoqi@1 116
aoqi@1 117 // This doesn't really do anything on Intel, but it is the place where
aoqi@1 118 // cache invalidation belongs, generically:
aoqi@1 119 void wrote(int offset);
aoqi@1 120
aoqi@1 121 public:
aoqi@1 122
aoqi@1 123 // unit test stuff
aoqi@1 124 static void test() {} // override for testing
aoqi@1 125
aoqi@1 126 inline friend NativeInstruction* nativeInstruction_at(address address);
aoqi@1 127 };
aoqi@1 128
aoqi@1 129 inline NativeInstruction* nativeInstruction_at(address address) {
aoqi@1 130 NativeInstruction* inst = (NativeInstruction*)address;
aoqi@1 131 #ifdef ASSERT
aoqi@1 132 //inst->verify();
aoqi@1 133 #endif
aoqi@1 134 return inst;
aoqi@1 135 }
aoqi@1 136
aoqi@1 137 inline NativeCall* nativeCall_at(address address);
aoqi@1 138 // The NativeCall is an abstraction for accessing/manipulating native call imm32/imm64
aoqi@1 139 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
aoqi@1 140 // MIPS has no call instruction with imm32/imm64. Usually, a call was done like this:
aoqi@1 141 // 32 bits:
aoqi@6880 142 // lui rt, imm16
aoqi@6880 143 // addiu rt, rt, imm16
aoqi@6880 144 // jalr rt
aoqi@8865 145 // nop
aoqi@6880 146 //
aoqi@1 147 // 64 bits:
aoqi@8865 148 // lui rd, imm(63...48);
aoqi@8865 149 // ori rd, rd, imm(47...32);
aoqi@8865 150 // dsll rd, rd, 16;
aoqi@8865 151 // ori rd, rd, imm(31...16);
aoqi@8865 152 // dsll rd, rd, 16;
aoqi@8865 153 // ori rd, rd, imm(15...0);
aoqi@8865 154 // jalr rd
aoqi@8865 155 // nop
aoqi@6880 156 //
aoqi@1 157
aoqi@1 158 // we just consider the above for instruction as one call instruction
aoqi@1 159 class NativeCall: public NativeInstruction {
aoqi@6880 160 public:
aoqi@6880 161 enum mips_specific_constants {
aoqi@6880 162 instruction_offset = 0,
aoqi@1 163 #ifndef _LP64
aoqi@6880 164 instruction_size = 4 * BytesPerInstWord,
aoqi@6880 165 return_address_offset = 4 * BytesPerInstWord,
aoqi@1 166 #else
aoqi@6880 167 instruction_size = 6 * BytesPerInstWord,
aoqi@6880 168 return_address_offset_short = 4 * BytesPerInstWord,
aoqi@6880 169 return_address_offset_long = 6 * BytesPerInstWord,
aoqi@1 170 #endif
aoqi@6880 171 displacement_offset = 0
aoqi@6880 172 };
aoqi@1 173
aoqi@6880 174 address instruction_address() const { return addr_at(instruction_offset); }
fujie@373 175
aoqi@6880 176 address next_instruction_address() const {
aoqi@6880 177 if (is_special_op(int_at(8), Assembler::jalr_op)) {
aoqi@6880 178 return addr_at(return_address_offset_short);
aoqi@6880 179 } else {
aoqi@6880 180 return addr_at(return_address_offset_long);
fujie@373 181 }
aoqi@6880 182 }
fujie@373 183
aoqi@6880 184 address return_address() const {
aoqi@6880 185 return next_instruction_address();
aoqi@6880 186 }
fujie@373 187
aoqi@6880 188 address destination() const;
aoqi@6880 189 void set_destination(address dest);
aoqi@6880 190 void set_destination_mt_safe(address dest) { set_destination(dest);}
aoqi@1 191
aoqi@6880 192 void patch_set48_gs(address dest);
aoqi@6880 193 void patch_set48(address dest);
fujie@366 194
aoqi@6880 195 void patch_on_jalr_gs(address dest);
aoqi@6880 196 void patch_on_jalr(address dest);
fujie@379 197
aoqi@6880 198 void patch_on_jal_gs(address dest);
aoqi@6880 199 void patch_on_jal(address dest);
fujie@379 200
aoqi@6880 201 void patch_on_jal_only(address dest);
fujie@397 202
aoqi@6880 203 void patch_set32_gs(address dest);
aoqi@6880 204 void patch_set32(address dest);
fujie@374 205
aoqi@6880 206 void verify_alignment() { }
aoqi@6880 207 void verify();
aoqi@6880 208 void print();
aoqi@1 209
aoqi@6880 210 // Creation
aoqi@6880 211 inline friend NativeCall* nativeCall_at(address address);
aoqi@6880 212 inline friend NativeCall* nativeCall_before(address return_address);
aoqi@1 213
aoqi@6880 214 static bool is_call_at(address instr) {
aoqi@6880 215 return nativeInstruction_at(instr)->is_call();
aoqi@6880 216 }
aoqi@1 217
aoqi@6880 218 static bool is_call_before(address return_address) {
aoqi@6880 219 return is_call_at(return_address - return_address_offset_short) | is_call_at(return_address - return_address_offset_long);
aoqi@6880 220 }
aoqi@1 221
aoqi@6880 222 static bool is_call_to(address instr, address target) {
aoqi@6880 223 return nativeInstruction_at(instr)->is_call() &&
aoqi@6880 224 nativeCall_at(instr)->destination() == target;
aoqi@6880 225 }
aoqi@1 226
aoqi@6880 227 // MT-safe patching of a call instruction.
aoqi@6880 228 static void insert(address code_pos, address entry);
aoqi@1 229
aoqi@6880 230 static void replace_mt_safe(address instr_addr, address code_buffer);
aoqi@1 231 };
aoqi@1 232
aoqi@1 233 inline NativeCall* nativeCall_at(address address) {
aoqi@1 234 NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
aoqi@1 235 #ifdef ASSERT
aoqi@1 236 call->verify();
aoqi@1 237 #endif
aoqi@1 238 return call;
aoqi@1 239 }
aoqi@1 240
aoqi@1 241 inline NativeCall* nativeCall_before(address return_address) {
fujie@373 242 NativeCall* call = NULL;
fujie@373 243 if (NativeCall::is_call_at(return_address - NativeCall::return_address_offset_long)) {
fujie@373 244 call = (NativeCall*)(return_address - NativeCall::return_address_offset_long);
fujie@373 245 } else {
fujie@373 246 call = (NativeCall*)(return_address - NativeCall::return_address_offset_short);
fujie@373 247 }
aoqi@1 248 #ifdef ASSERT
aoqi@1 249 call->verify();
aoqi@1 250 #endif
aoqi@1 251 return call;
aoqi@1 252 }
aoqi@1 253
aoqi@1 254 class NativeMovConstReg: public NativeInstruction {
aoqi@1 255 public:
aoqi@1 256 enum mips_specific_constants {
aoqi@6880 257 instruction_offset = 0,
aoqi@1 258 #ifndef _LP64
aoqi@6880 259 instruction_size = 2 * BytesPerInstWord,
aoqi@6880 260 next_instruction_offset = 2 * BytesPerInstWord,
aoqi@1 261 #else
aoqi@6880 262 instruction_size = 4 * BytesPerInstWord,
aoqi@6880 263 next_instruction_offset = 4 * BytesPerInstWord,
aoqi@1 264 #endif
aoqi@1 265 };
aoqi@6880 266
aoqi@1 267 int insn_word() const { return long_at(instruction_offset); }
aoqi@1 268 address instruction_address() const { return addr_at(0); }
aoqi@1 269 address next_instruction_address() const { return addr_at(next_instruction_offset); }
aoqi@1 270 intptr_t data() const;
aoqi@1 271 void set_data(intptr_t x);
fujie@347 272
fujie@347 273 void patch_set48(intptr_t x);
aoqi@1 274
aoqi@1 275 void verify();
aoqi@1 276 void print();
aoqi@1 277
aoqi@1 278 // unit test stuff
aoqi@1 279 static void test() {}
aoqi@1 280
aoqi@1 281 // Creation
aoqi@1 282 inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
aoqi@1 283 inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
aoqi@1 284 };
aoqi@1 285
aoqi@1 286 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
aoqi@1 287 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
aoqi@1 288 #ifdef ASSERT
aoqi@1 289 test->verify();
aoqi@1 290 #endif
aoqi@1 291 return test;
aoqi@1 292 }
aoqi@1 293
aoqi@1 294 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
aoqi@1 295 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
aoqi@1 296 #ifdef ASSERT
aoqi@1 297 test->verify();
aoqi@1 298 #endif
aoqi@1 299 return test;
aoqi@1 300 }
aoqi@1 301
aoqi@1 302 class NativeMovConstRegPatching: public NativeMovConstReg {
aoqi@1 303 private:
aoqi@1 304 friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
aoqi@1 305 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
aoqi@1 306 #ifdef ASSERT
aoqi@1 307 test->verify();
aoqi@1 308 #endif
aoqi@1 309 return test;
aoqi@1 310 }
aoqi@1 311 };
aoqi@1 312
aoqi@1 313 // An interface for accessing/manipulating native moves of the form:
aoqi@6880 314 // lui AT, split_high(offset)
aoqi@6880 315 // addiu AT, split_low(offset)
aoqi@6880 316 // add reg, reg, AT
aoqi@6880 317 // lb/lbu/sb/lh/lhu/sh/lw/sw/lwc1/swc1 dest, reg, 0
aoqi@6880 318 // [lw/sw/lwc1/swc1 dest, reg, 4]
aoqi@6880 319 // or
aoqi@6880 320 // lb/lbu/sb/lh/lhu/sh/lw/sw/lwc1/swc1 dest, reg, offset
aoqi@6880 321 // [lw/sw/lwc1/swc1 dest, reg, offset+4]
aoqi@1 322 //
aoqi@1 323 // Warning: These routines must be able to handle any instruction sequences
aoqi@1 324 // that are generated as a result of the load/store byte,word,long
aoqi@6880 325 // macros.
aoqi@1 326
aoqi@1 327 class NativeMovRegMem: public NativeInstruction {
aoqi@1 328 public:
aoqi@1 329 enum mips_specific_constants {
aoqi@1 330 instruction_offset = 0,
aoqi@6880 331 hiword_offset = 4,
aoqi@6880 332 ldst_offset = 12,
aoqi@6880 333 immediate_size = 4,
aoqi@6880 334 ldst_size = 16
aoqi@1 335 };
aoqi@1 336
aoqi@1 337 //offset is less than 16 bits.
aoqi@1 338 bool is_immediate() const { return !is_op(long_at(instruction_offset), Assembler::lui_op); }
aoqi@1 339 bool is_64ldst() const {
aoqi@1 340 if (is_immediate()) {
aoqi@1 341 return (Assembler::opcode(long_at(hiword_offset)) == Assembler::opcode(long_at(instruction_offset))) &&
aoqi@6880 342 (Assembler::imm_off(long_at(hiword_offset)) == Assembler::imm_off(long_at(instruction_offset)) + wordSize);
aoqi@1 343 } else {
aoqi@1 344 return (Assembler::opcode(long_at(ldst_offset+hiword_offset)) == Assembler::opcode(long_at(ldst_offset))) &&
aoqi@6880 345 (Assembler::imm_off(long_at(ldst_offset+hiword_offset)) == Assembler::imm_off(long_at(ldst_offset)) + wordSize);
aoqi@1 346 }
aoqi@1 347 }
aoqi@1 348
aoqi@1 349 address instruction_address() const { return addr_at(instruction_offset); }
aoqi@6880 350 address next_instruction_address() const {
aoqi@6880 351 return addr_at( (is_immediate()? immediate_size : ldst_size) + (is_64ldst()? 4 : 0));
aoqi@1 352 }
aoqi@1 353
aoqi@1 354 int offset() const;
aoqi@1 355
aoqi@1 356 void set_offset(int x);
aoqi@1 357
aoqi@1 358 void add_offset_in_bytes(int add_offset) { set_offset ( ( offset() + add_offset ) ); }
aoqi@1 359
aoqi@1 360 void verify();
aoqi@1 361 void print ();
aoqi@1 362
aoqi@1 363 // unit test stuff
aoqi@1 364 static void test() {}
aoqi@1 365
aoqi@1 366 private:
aoqi@1 367 inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
aoqi@1 368 };
aoqi@1 369
aoqi@1 370 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
aoqi@1 371 NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
aoqi@1 372 #ifdef ASSERT
aoqi@1 373 test->verify();
aoqi@1 374 #endif
aoqi@1 375 return test;
aoqi@1 376 }
aoqi@1 377
aoqi@1 378 class NativeMovRegMemPatching: public NativeMovRegMem {
aoqi@1 379 private:
aoqi@1 380 friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {
aoqi@1 381 NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)(address - instruction_offset);
aoqi@1 382 #ifdef ASSERT
aoqi@1 383 test->verify();
aoqi@1 384 #endif
aoqi@1 385 return test;
aoqi@1 386 }
aoqi@1 387 };
aoqi@1 388
aoqi@1 389
aoqi@1 390 // Handles all kinds of jump on Loongson. Long/far, conditional/unconditional
aoqi@1 391 // 32 bits:
aoqi@1 392 // far jump:
aoqi@6880 393 // lui reg, split_high(addr)
aoqi@6880 394 // addiu reg, split_low(addr)
aoqi@6880 395 // jr reg
aoqi@6880 396 // nop
aoqi@6880 397 // or
aoqi@6880 398 // beq ZERO, ZERO, offset
aoqi@6880 399 // nop
aoqi@1 400 //
aoqi@1 401
aoqi@1 402 //64 bits:
aoqi@1 403 // far jump:
aoqi@6880 404 // lui rd, imm(63...48);
aoqi@6880 405 // ori rd, rd, imm(47...32);
aoqi@6880 406 // dsll rd, rd, 16;
aoqi@6880 407 // ori rd, rd, imm(31...16);
aoqi@6880 408 // dsll rd, rd, 16;
aoqi@6880 409 // ori rd, rd, imm(15...0);
aoqi@6880 410 // jalr rd
aoqi@6880 411 // nop
aoqi@6880 412 //
aoqi@1 413 class NativeGeneralJump: public NativeInstruction {
aoqi@6880 414 public:
aoqi@1 415 enum mips_specific_constants {
aoqi@6880 416 instruction_offset = 0,
aoqi@6880 417 beq_opcode = 0x10000000,//000100|00000|00000|offset
aoqi@6880 418 b_mask = 0xffff0000,
aoqi@6880 419 short_size = 8,
aoqi@1 420 #ifndef _LP64
aoqi@1 421 instruction_size = 4 * BytesPerInstWord
aoqi@1 422 #else
aoqi@1 423 instruction_size = 6 * BytesPerInstWord
aoqi@1 424 #endif
aoqi@1 425 };
aoqi@1 426
aoqi@1 427 bool is_short() const { return (long_at(instruction_offset) & b_mask) == beq_opcode; }
aoqi@1 428 #ifdef _LP64
aoqi@1 429 bool is_b_far();
aoqi@1 430 #endif
aoqi@1 431 address instruction_address() const { return addr_at(instruction_offset); }
aoqi@1 432 address jump_destination();
aoqi@1 433
fujie@386 434 void patch_set48_gs(address dest);
fujie@367 435 void patch_set48(address dest);
fujie@386 436
fujie@386 437 void patch_on_jr_gs(address dest);
fujie@386 438 void patch_on_jr(address dest);
fujie@386 439
fujie@386 440 void patch_on_j_gs(address dest);
fujie@386 441 void patch_on_j(address dest);
fujie@386 442
fujie@397 443 void patch_on_j_only(address dest);
fujie@397 444
aoqi@1 445 void set_jump_destination(address dest);
aoqi@1 446
aoqi@6880 447 // Creation
aoqi@1 448 inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
aoqi@1 449
aoqi@6880 450 // Insertion of native general jump instruction
aoqi@1 451 static void insert_unconditional(address code_pos, address entry);
aoqi@1 452 static void replace_mt_safe(address instr_addr, address code_buffer);
aoqi@1 453 static void check_verified_entry_alignment(address entry, address verified_entry){}
aoqi@1 454 static void patch_verified_entry(address entry, address verified_entry, address dest);
aoqi@1 455
aoqi@1 456 void verify();
aoqi@1 457 };
aoqi@1 458
aoqi@1 459 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
aoqi@1 460 NativeGeneralJump* jump = (NativeGeneralJump*)(address);
aoqi@1 461 debug_only(jump->verify();)
aoqi@1 462 return jump;
aoqi@1 463 }
aoqi@1 464
aoqi@1 465
aoqi@1 466 class NativeIllegalInstruction: public NativeInstruction {
aoqi@1 467 public:
aoqi@1 468 enum Intel_specific_constants {
aoqi@1 469 instruction_size = 4,
aoqi@1 470 instruction_offset = 0,
aoqi@1 471 next_instruction_offset = 4
aoqi@1 472 };
aoqi@1 473
aoqi@1 474 // Insert illegal opcode as specific address
aoqi@1 475 static void insert(address code_pos);
aoqi@1 476 };
aoqi@1 477
aoqi@1 478 // return instruction that does not pop values of the stack
aoqi@1 479 // jr RA
aoqi@1 480 // delay slot
aoqi@1 481 class NativeReturn: public NativeInstruction {
aoqi@6880 482 public:
aoqi@1 483 enum mips_specific_constants {
aoqi@1 484 instruction_size = 8,
aoqi@1 485 instruction_offset = 0,
aoqi@1 486 next_instruction_offset = 8
aoqi@1 487 };
aoqi@1 488 };
aoqi@1 489
aoqi@1 490
aoqi@1 491
aoqi@1 492
aoqi@1 493 class NativeCondJump;
aoqi@1 494 inline NativeCondJump* nativeCondJump_at(address address);
aoqi@1 495 class NativeCondJump: public NativeInstruction {
aoqi@6880 496 public:
aoqi@1 497 enum mips_specific_constants {
aoqi@6880 498 instruction_size = 16,
aoqi@1 499 instruction_offset = 12,
aoqi@1 500 next_instruction_offset = 20
aoqi@1 501 };
aoqi@1 502
aoqi@1 503
aoqi@1 504 int insn_word() const { return long_at(instruction_offset); }
aoqi@1 505 address instruction_address() const { return addr_at(0); }
aoqi@1 506 address next_instruction_address() const { return addr_at(next_instruction_offset); }
aoqi@6880 507
aoqi@1 508 // Creation
aoqi@1 509 inline friend NativeCondJump* nativeCondJump_at(address address);
aoqi@1 510
aoqi@1 511 address jump_destination() const {
aoqi@1 512 return ::nativeCondJump_at(addr_at(12))->jump_destination();
aoqi@1 513 }
aoqi@1 514
aoqi@1 515 void set_jump_destination(address dest) {
aoqi@1 516 ::nativeCondJump_at(addr_at(12))->set_jump_destination(dest);
aoqi@1 517 }
aoqi@1 518
aoqi@6880 519 };
aoqi@1 520
aoqi@1 521 inline NativeCondJump* nativeCondJump_at(address address) {
aoqi@1 522 NativeCondJump* jump = (NativeCondJump*)(address);
aoqi@1 523 return jump;
aoqi@1 524 }
aoqi@1 525
aoqi@1 526
aoqi@1 527
aoqi@1 528 inline bool NativeInstruction::is_illegal() { return insn_word() == illegal_instruction(); }
aoqi@1 529
aoqi@6880 530 inline bool NativeInstruction::is_call() {
aoqi@1 531 #ifndef _LP64
aoqi@1 532 return is_op(long_at(0), Assembler::lui_op) &&
aoqi@1 533 is_op(long_at(4), Assembler::addiu_op) &&
aoqi@6880 534 is_special_op(long_at(8), Assembler::jalr_op);
aoqi@1 535 #else
aoqi@6880 536 // jal target
fujie@397 537 // nop
fujie@397 538 if ( nativeInstruction_at(addr_at(0))->is_op(Assembler::jal_op) &&
fujie@397 539 nativeInstruction_at(addr_at(4))->is_nop() ) {
fujie@397 540 return true;
fujie@397 541 }
fujie@379 542
fujie@379 543 // nop
fujie@379 544 // nop
fujie@379 545 // nop
fujie@379 546 // nop
aoqi@6880 547 // jal target
fujie@379 548 // nop
fujie@379 549 if ( is_nop() &&
fujie@379 550 nativeInstruction_at(addr_at(4))->is_nop() &&
fujie@379 551 nativeInstruction_at(addr_at(8))->is_nop() &&
fujie@379 552 nativeInstruction_at(addr_at(12))->is_nop() &&
fujie@379 553 nativeInstruction_at(addr_at(16))->is_op(Assembler::jal_op) &&
fujie@379 554 nativeInstruction_at(addr_at(20))->is_nop() ) {
aoqi@6880 555 return true;
fujie@379 556 }
fujie@379 557
fujie@379 558 // li64
fujie@367 559 if ( is_op(Assembler::lui_op) &&
aoqi@6880 560 is_op(int_at(4), Assembler::ori_op) &&
aoqi@6880 561 is_special_op(int_at(8), Assembler::dsll_op) &&
aoqi@6880 562 is_op(int_at(12), Assembler::ori_op) &&
aoqi@6880 563 is_special_op(int_at(16), Assembler::dsll_op) &&
aoqi@6880 564 is_op(int_at(20), Assembler::ori_op) &&
aoqi@6880 565 is_special_op(int_at(24), Assembler::jalr_op) ) {
aoqi@6880 566 return true;
aoqi@1 567 }
fujie@367 568
fujie@367 569 //lui dst, imm16
fujie@367 570 //ori dst, dst, imm16
fujie@367 571 //dsll dst, dst, 16
fujie@367 572 //ori dst, dst, imm16
fujie@367 573 if ( is_op(Assembler::lui_op) &&
aoqi@6880 574 is_op (int_at(4), Assembler::ori_op) &&
aoqi@6880 575 is_special_op(int_at(8), Assembler::dsll_op) &&
aoqi@6880 576 is_op (int_at(12), Assembler::ori_op) &&
aoqi@6880 577 is_special_op(int_at(16), Assembler::jalr_op) ) {
aoqi@6880 578 return true;
fujie@367 579 }
fujie@367 580
fujie@367 581 //ori dst, R0, imm16
fujie@367 582 //dsll dst, dst, 16
fujie@367 583 //ori dst, dst, imm16
fujie@367 584 //nop
fujie@367 585 if ( is_op(Assembler::ori_op) &&
aoqi@6880 586 is_special_op(int_at(4), Assembler::dsll_op) &&
aoqi@6880 587 is_op (int_at(8), Assembler::ori_op) &&
aoqi@6880 588 nativeInstruction_at(addr_at(12))->is_nop() &&
aoqi@6880 589 is_special_op(int_at(16), Assembler::jalr_op) ) {
aoqi@6880 590 return true;
fujie@367 591 }
fujie@367 592
fujie@367 593 //ori dst, R0, imm16
fujie@367 594 //dsll dst, dst, 16
fujie@367 595 //nop
fujie@367 596 //nop
fujie@367 597 if ( is_op(Assembler::ori_op) &&
aoqi@6880 598 is_special_op(int_at(4), Assembler::dsll_op) &&
aoqi@6880 599 nativeInstruction_at(addr_at(8))->is_nop() &&
aoqi@6880 600 nativeInstruction_at(addr_at(12))->is_nop() &&
aoqi@6880 601 is_special_op(int_at(16), Assembler::jalr_op) ) {
aoqi@6880 602 return true;
fujie@367 603 }
fujie@367 604
fujie@367 605 //daddiu dst, R0, imm16
fujie@367 606 //nop
fujie@367 607 //nop
fujie@367 608 //nop
fujie@367 609 if ( is_op(Assembler::daddiu_op) &&
aoqi@6880 610 nativeInstruction_at(addr_at(4))->is_nop() &&
aoqi@6880 611 nativeInstruction_at(addr_at(8))->is_nop() &&
aoqi@6880 612 nativeInstruction_at(addr_at(12))->is_nop() &&
aoqi@6880 613 is_special_op(int_at(16), Assembler::jalr_op) ) {
aoqi@6880 614 return true;
fujie@367 615 }
fujie@367 616
fujie@367 617 //lui dst, imm16
fujie@367 618 //ori dst, dst, imm16
fujie@367 619 //nop
fujie@367 620 //nop
fujie@367 621 if ( is_op(Assembler::lui_op) &&
aoqi@6880 622 is_op (int_at(4), Assembler::ori_op) &&
aoqi@6880 623 nativeInstruction_at(addr_at(8))->is_nop() &&
aoqi@6880 624 nativeInstruction_at(addr_at(12))->is_nop() &&
aoqi@6880 625 is_special_op(int_at(16), Assembler::jalr_op) ) {
aoqi@6880 626 return true;
fujie@367 627 }
fujie@367 628
fujie@367 629 //lui dst, imm16
fujie@367 630 //nop
fujie@367 631 //nop
fujie@367 632 //nop
fujie@367 633 if ( is_op(Assembler::lui_op) &&
aoqi@6880 634 nativeInstruction_at(addr_at(4))->is_nop() &&
aoqi@6880 635 nativeInstruction_at(addr_at(8))->is_nop() &&
aoqi@6880 636 nativeInstruction_at(addr_at(12))->is_nop() &&
aoqi@6880 637 is_special_op(int_at(16), Assembler::jalr_op) ) {
aoqi@6880 638 return true;
fujie@367 639 }
fujie@367 640
fujie@373 641
fujie@373 642 //daddiu dst, R0, imm16
fujie@373 643 //nop
fujie@373 644 if ( is_op(Assembler::daddiu_op) &&
aoqi@6880 645 nativeInstruction_at(addr_at(4))->is_nop() &&
aoqi@6880 646 is_special_op(int_at(8), Assembler::jalr_op) ) {
aoqi@6880 647 return true;
fujie@373 648 }
fujie@373 649
fujie@373 650 //lui dst, imm16
fujie@373 651 //ori dst, dst, imm16
fujie@373 652 if ( is_op(Assembler::lui_op) &&
aoqi@6880 653 is_op (int_at(4), Assembler::ori_op) &&
aoqi@6880 654 is_special_op(int_at(8), Assembler::jalr_op) ) {
aoqi@6880 655 return true;
fujie@373 656 }
fujie@373 657
fujie@373 658 //lui dst, imm16
fujie@373 659 //nop
fujie@373 660 if ( is_op(Assembler::lui_op) &&
aoqi@6880 661 nativeInstruction_at(addr_at(4))->is_nop() &&
aoqi@6880 662 is_special_op(int_at(8), Assembler::jalr_op) ) {
aoqi@6880 663 return true;
fujie@373 664 }
fujie@373 665
fujie@367 666 return false;
fujie@367 667
aoqi@1 668 #endif
aoqi@1 669 }
aoqi@1 670
aoqi@1 671 inline bool NativeInstruction::is_return() { return is_special_op(Assembler::jr_op) && is_rs(RA);}
aoqi@1 672
aoqi@1 673 inline bool NativeInstruction::is_cond_jump() { return is_int_branch() || is_float_branch(); }
aoqi@6880 674
aoqi@1 675 #endif // CPU_MIPS_VM_NATIVEINST_MIPS_HPP

mercurial