src/cpu/mips/vm/nativeInst_mips.hpp

Fri, 29 Apr 2016 00:06:10 +0800

author
aoqi
date
Fri, 29 Apr 2016 00:06:10 +0800
changeset 1
2d8a650513c2
child 346
3a6b04bc4dd7
permissions
-rw-r--r--

Added MIPS 64-bit port.

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
aoqi@1 3 * Copyright (c) 2015, 2016, 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 {
aoqi@1 58 nop_instruction_code = 0, //sll zero, zero, zero
aoqi@1 59 nop_instruction_size = 4
aoqi@1 60 };
aoqi@1 61
aoqi@1 62 bool is_nop() { return long_at(0) == nop_instruction_code; }
aoqi@1 63 bool is_dtrace_trap();
aoqi@1 64 inline bool is_call();
aoqi@1 65 inline bool is_illegal();
aoqi@1 66 inline bool is_return();
aoqi@1 67 bool is_jump();
aoqi@1 68 inline bool is_cond_jump();
aoqi@1 69 bool is_safepoint_poll();
aoqi@1 70
aoqi@1 71 //mips has no instruction to generate a illegal instrucion exception
aoqi@1 72 //we define ours: break 11
aoqi@1 73 static int illegal_instruction();
aoqi@1 74
aoqi@1 75 bool is_int_branch();
aoqi@1 76 bool is_float_branch();
aoqi@1 77
aoqi@1 78
aoqi@1 79 protected:
aoqi@1 80 address addr_at(int offset) const { return address(this) + offset; }
aoqi@1 81 address instruction_address() const { return addr_at(0); }
aoqi@1 82 address next_instruction_address() const { return addr_at(BytesPerInstWord); }
aoqi@1 83 address prev_instruction_address() const { return addr_at(-BytesPerInstWord); }
aoqi@1 84
aoqi@1 85 s_char sbyte_at(int offset) const { return *(s_char*) addr_at(offset); }
aoqi@1 86 u_char ubyte_at(int offset) const { return *(u_char*) addr_at(offset); }
aoqi@1 87 jint int_at(int offset) const { return *(jint*) addr_at(offset); }
aoqi@1 88 intptr_t ptr_at(int offset) const { return *(intptr_t*) addr_at(offset); }
aoqi@1 89 oop oop_at (int offset) const { return *(oop*) addr_at(offset); }
aoqi@1 90 int long_at(int offset) const { return *(jint*)addr_at(offset); }
aoqi@1 91
aoqi@1 92
aoqi@1 93 void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; wrote(offset); }
aoqi@1 94 void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; wrote(offset); }
aoqi@1 95 void set_ptr_at (int offset, intptr_t ptr) { *(intptr_t*) addr_at(offset) = ptr; wrote(offset); }
aoqi@1 96 void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; wrote(offset); }
aoqi@1 97 void set_long_at(int offset, long i);
aoqi@1 98 //void set_jlong_at(int offset, jlong i);
aoqi@1 99 //void set_addr_at(int offset, address x);
aoqi@1 100
aoqi@1 101 int insn_word() const { return long_at(0); }
aoqi@1 102 static bool is_op (int insn, Assembler::ops op) { return Assembler::opcode(insn) == (int)op; }
aoqi@1 103 bool is_op (Assembler::ops op) const { return is_op(insn_word(), op); }
aoqi@1 104 bool is_rs (int insn, Register rs) const { return Assembler::rs(insn) == (int)rs->encoding(); }
aoqi@1 105 bool is_rs (Register rs) const { return is_rs(insn_word(), rs); }
aoqi@1 106 bool is_rt (int insn, Register rt) const { return Assembler::rt(insn) == (int)rt->encoding(); }
aoqi@1 107 bool is_rt (Register rt) const { return is_rt(insn_word(), rt); }
aoqi@1 108
aoqi@1 109 static bool is_special_op (int insn, Assembler::special_ops op) {
aoqi@1 110 return is_op(insn, Assembler::special_op) && Assembler::special(insn)==(int)op;
aoqi@1 111 }
aoqi@1 112 bool is_special_op (Assembler::special_ops op) const { return is_special_op(insn_word(), op); }
aoqi@1 113
aoqi@1 114 // This doesn't really do anything on Intel, but it is the place where
aoqi@1 115 // cache invalidation belongs, generically:
aoqi@1 116 void wrote(int offset);
aoqi@1 117
aoqi@1 118 public:
aoqi@1 119
aoqi@1 120 // unit test stuff
aoqi@1 121 static void test() {} // override for testing
aoqi@1 122
aoqi@1 123 inline friend NativeInstruction* nativeInstruction_at(address address);
aoqi@1 124 };
aoqi@1 125
aoqi@1 126 inline NativeInstruction* nativeInstruction_at(address address) {
aoqi@1 127 NativeInstruction* inst = (NativeInstruction*)address;
aoqi@1 128 #ifdef ASSERT
aoqi@1 129 //inst->verify();
aoqi@1 130 #endif
aoqi@1 131 return inst;
aoqi@1 132 }
aoqi@1 133
aoqi@1 134 inline NativeCall* nativeCall_at(address address);
aoqi@1 135 // The NativeCall is an abstraction for accessing/manipulating native call imm32/imm64
aoqi@1 136 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
aoqi@1 137 // MIPS has no call instruction with imm32/imm64. Usually, a call was done like this:
aoqi@1 138 // 32 bits:
aoqi@1 139 // lui rt, imm16
aoqi@1 140 // addiu rt, rt, imm16
aoqi@1 141 // jalr rt
aoqi@1 142 // nop
aoqi@1 143 //
aoqi@1 144 // 64 bits:
aoqi@1 145 // lui rd, imm(63...48);
aoqi@1 146 // ori rd, rd, imm(47...32);
aoqi@1 147 // dsll rd, rd, 16;
aoqi@1 148 // ori rd, rd, imm(31...16);
aoqi@1 149 // dsll rd, rd, 16;
aoqi@1 150 // ori rd, rd, imm(15...0);
aoqi@1 151 // jalr rd
aoqi@1 152 // nop
aoqi@1 153 //
aoqi@1 154
aoqi@1 155 // we just consider the above for instruction as one call instruction
aoqi@1 156 class NativeCall: public NativeInstruction {
aoqi@1 157 public:
aoqi@1 158 enum mips_specific_constants {
aoqi@1 159 instruction_offset = 0,
aoqi@1 160 #ifndef _LP64
aoqi@1 161 instruction_size = 4 * BytesPerInstWord,
aoqi@1 162 return_address_offset = 4 * BytesPerInstWord,
aoqi@1 163 #else
aoqi@1 164 instruction_size = 6 * BytesPerInstWord,
aoqi@1 165 return_address_offset = 6 * BytesPerInstWord,
aoqi@1 166 #endif
aoqi@1 167 displacement_offset = 0
aoqi@1 168 };
aoqi@1 169
aoqi@1 170 address instruction_address() const { return addr_at(instruction_offset); }
aoqi@1 171 address next_instruction_address() const { return addr_at(return_address_offset); }
aoqi@1 172 address return_address() const { return addr_at(return_address_offset); }
aoqi@1 173 address destination() const;
aoqi@1 174 void set_destination(address dest);
aoqi@1 175 void set_destination_mt_safe(address dest) { set_destination(dest);}
aoqi@1 176
aoqi@1 177 void verify_alignment() { }
aoqi@1 178 void verify();
aoqi@1 179 void print();
aoqi@1 180
aoqi@1 181 // Creation
aoqi@1 182 inline friend NativeCall* nativeCall_at(address address);
aoqi@1 183 inline friend NativeCall* nativeCall_before(address return_address);
aoqi@1 184
aoqi@1 185 static bool is_call_at(address instr) {
aoqi@1 186 return nativeInstruction_at(instr)->is_call();
aoqi@1 187 }
aoqi@1 188
aoqi@1 189 static bool is_call_before(address return_address) {
aoqi@1 190 return is_call_at(return_address - NativeCall::return_address_offset);
aoqi@1 191 }
aoqi@1 192
aoqi@1 193 static bool is_call_to(address instr, address target) {
aoqi@1 194 return nativeInstruction_at(instr)->is_call() &&
aoqi@1 195 nativeCall_at(instr)->destination() == target;
aoqi@1 196 }
aoqi@1 197
aoqi@1 198 // MT-safe patching of a call instruction.
aoqi@1 199 static void insert(address code_pos, address entry);
aoqi@1 200
aoqi@1 201 static void replace_mt_safe(address instr_addr, address code_buffer);
aoqi@1 202 };
aoqi@1 203
aoqi@1 204 inline NativeCall* nativeCall_at(address address) {
aoqi@1 205 NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
aoqi@1 206 #ifdef ASSERT
aoqi@1 207 call->verify();
aoqi@1 208 #endif
aoqi@1 209 return call;
aoqi@1 210 }
aoqi@1 211
aoqi@1 212 inline NativeCall* nativeCall_before(address return_address) {
aoqi@1 213 NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
aoqi@1 214 #ifdef ASSERT
aoqi@1 215 call->verify();
aoqi@1 216 #endif
aoqi@1 217 return call;
aoqi@1 218 }
aoqi@1 219
aoqi@1 220 // An interface for accessing/manipulating native mov reg, imm32 instructions.
aoqi@1 221 // (used to manipulate inlined 32bit data dll calls, etc.)
aoqi@1 222 //we use two instructions to implement this:
aoqi@1 223 // lui rd, imm16
aoqi@1 224 // addiu rd, immm16
aoqi@1 225 //see MacroAssembler::move(Register, int)
aoqi@1 226 class NativeMovConstReg: public NativeInstruction {
aoqi@1 227 public:
aoqi@1 228 enum mips_specific_constants {
aoqi@1 229 instruction_offset = 0,
aoqi@1 230 #ifndef _LP64
aoqi@1 231 instruction_size = 2 * BytesPerInstWord,
aoqi@1 232 next_instruction_offset = 2 * BytesPerInstWord,
aoqi@1 233 #else
aoqi@1 234 instruction_size = 4 * BytesPerInstWord,
aoqi@1 235 next_instruction_offset = 4 * BytesPerInstWord,
aoqi@1 236 #endif
aoqi@1 237 };
aoqi@1 238
aoqi@1 239 int insn_word() const { return long_at(instruction_offset); }
aoqi@1 240 address instruction_address() const { return addr_at(0); }
aoqi@1 241 address next_instruction_address() const { return addr_at(next_instruction_offset); }
aoqi@1 242 intptr_t data() const;
aoqi@1 243 void set_data(intptr_t x);
aoqi@1 244
aoqi@1 245
aoqi@1 246 void verify();
aoqi@1 247 void print();
aoqi@1 248
aoqi@1 249 // unit test stuff
aoqi@1 250 static void test() {}
aoqi@1 251
aoqi@1 252 // Creation
aoqi@1 253 inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
aoqi@1 254 inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
aoqi@1 255 };
aoqi@1 256
aoqi@1 257 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
aoqi@1 258 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
aoqi@1 259 #ifdef ASSERT
aoqi@1 260 test->verify();
aoqi@1 261 #endif
aoqi@1 262 return test;
aoqi@1 263 }
aoqi@1 264
aoqi@1 265 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
aoqi@1 266 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
aoqi@1 267 #ifdef ASSERT
aoqi@1 268 test->verify();
aoqi@1 269 #endif
aoqi@1 270 return test;
aoqi@1 271 }
aoqi@1 272
aoqi@1 273 class NativeMovConstRegPatching: public NativeMovConstReg {
aoqi@1 274 private:
aoqi@1 275 friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
aoqi@1 276 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
aoqi@1 277 #ifdef ASSERT
aoqi@1 278 test->verify();
aoqi@1 279 #endif
aoqi@1 280 return test;
aoqi@1 281 }
aoqi@1 282 };
aoqi@1 283
aoqi@1 284 // An interface for accessing/manipulating native moves of the form:
aoqi@1 285 // lui AT, split_high(offset)
aoqi@1 286 // addiu AT, split_low(offset)
aoqi@1 287 // add reg, reg, AT
aoqi@1 288 // lb/lbu/sb/lh/lhu/sh/lw/sw/lwc1/swc1 dest, reg, 0
aoqi@1 289 // [lw/sw/lwc1/swc1 dest, reg, 4]
aoqi@1 290 // or
aoqi@1 291 // lb/lbu/sb/lh/lhu/sh/lw/sw/lwc1/swc1 dest, reg, offset
aoqi@1 292 // [lw/sw/lwc1/swc1 dest, reg, offset+4]
aoqi@1 293 //
aoqi@1 294 // Warning: These routines must be able to handle any instruction sequences
aoqi@1 295 // that are generated as a result of the load/store byte,word,long
aoqi@1 296 // macros.
aoqi@1 297
aoqi@1 298 class NativeMovRegMem: public NativeInstruction {
aoqi@1 299 public:
aoqi@1 300 enum mips_specific_constants {
aoqi@1 301 instruction_offset = 0,
aoqi@1 302 hiword_offset = 4,
aoqi@1 303 ldst_offset = 12,
aoqi@1 304 immediate_size = 4,
aoqi@1 305 ldst_size = 16
aoqi@1 306 };
aoqi@1 307
aoqi@1 308 //offset is less than 16 bits.
aoqi@1 309 bool is_immediate() const { return !is_op(long_at(instruction_offset), Assembler::lui_op); }
aoqi@1 310 bool is_64ldst() const {
aoqi@1 311 if (is_immediate()) {
aoqi@1 312 return (Assembler::opcode(long_at(hiword_offset)) == Assembler::opcode(long_at(instruction_offset))) &&
aoqi@1 313 (Assembler::imm_off(long_at(hiword_offset)) == Assembler::imm_off(long_at(instruction_offset)) + wordSize);
aoqi@1 314 } else {
aoqi@1 315 return (Assembler::opcode(long_at(ldst_offset+hiword_offset)) == Assembler::opcode(long_at(ldst_offset))) &&
aoqi@1 316 (Assembler::imm_off(long_at(ldst_offset+hiword_offset)) == Assembler::imm_off(long_at(ldst_offset)) + wordSize);
aoqi@1 317 }
aoqi@1 318 }
aoqi@1 319
aoqi@1 320 address instruction_address() const { return addr_at(instruction_offset); }
aoqi@1 321 address next_instruction_address() const {
aoqi@1 322 return addr_at( (is_immediate()? immediate_size : ldst_size) + (is_64ldst()? 4 : 0));
aoqi@1 323 }
aoqi@1 324 /* // helper
aoqi@1 325 int instruction_start() const;
aoqi@1 326
aoqi@1 327 address instruction_address() const;
aoqi@1 328
aoqi@1 329 address next_instruction_address() const;
aoqi@1 330 */
aoqi@1 331
aoqi@1 332 int offset() const;
aoqi@1 333
aoqi@1 334 void set_offset(int x);
aoqi@1 335
aoqi@1 336 void add_offset_in_bytes(int add_offset) { set_offset ( ( offset() + add_offset ) ); }
aoqi@1 337
aoqi@1 338 void verify();
aoqi@1 339 void print ();
aoqi@1 340
aoqi@1 341 // unit test stuff
aoqi@1 342 static void test() {}
aoqi@1 343
aoqi@1 344 private:
aoqi@1 345 inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
aoqi@1 346 };
aoqi@1 347
aoqi@1 348 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
aoqi@1 349 NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
aoqi@1 350 #ifdef ASSERT
aoqi@1 351 test->verify();
aoqi@1 352 #endif
aoqi@1 353 return test;
aoqi@1 354 }
aoqi@1 355
aoqi@1 356 class NativeMovRegMemPatching: public NativeMovRegMem {
aoqi@1 357 private:
aoqi@1 358 friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {
aoqi@1 359 NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)(address - instruction_offset);
aoqi@1 360 #ifdef ASSERT
aoqi@1 361 test->verify();
aoqi@1 362 #endif
aoqi@1 363 return test;
aoqi@1 364 }
aoqi@1 365 };
aoqi@1 366
aoqi@1 367
aoqi@1 368 // Handles all kinds of jump on Loongson. Long/far, conditional/unconditional
aoqi@1 369 // 32 bits:
aoqi@1 370 // far jump:
aoqi@1 371 // lui reg, split_high(addr)
aoqi@1 372 // addiu reg, split_low(addr)
aoqi@1 373 // jr reg
aoqi@1 374 // nop
aoqi@1 375 // or
aoqi@1 376 // beq ZERO, ZERO, offset
aoqi@1 377 // nop
aoqi@1 378 //
aoqi@1 379
aoqi@1 380 //64 bits:
aoqi@1 381 // far jump:
aoqi@1 382 // lui rd, imm(63...48);
aoqi@1 383 // ori rd, rd, imm(47...32);
aoqi@1 384 // dsll rd, rd, 16;
aoqi@1 385 // ori rd, rd, imm(31...16);
aoqi@1 386 // dsll rd, rd, 16;
aoqi@1 387 // ori rd, rd, imm(15...0);
aoqi@1 388 // jalr rd
aoqi@1 389 // nop
aoqi@1 390 //
aoqi@1 391 class NativeGeneralJump: public NativeInstruction {
aoqi@1 392 public:
aoqi@1 393 enum mips_specific_constants {
aoqi@1 394 instruction_offset = 0,
aoqi@1 395 beq_opcode = 0x10000000,//000100|00000|00000|offset
aoqi@1 396 b_mask = 0xffff0000,
aoqi@1 397 short_size = 8,
aoqi@1 398 #ifndef _LP64
aoqi@1 399 instruction_size = 4 * BytesPerInstWord
aoqi@1 400 #else
aoqi@1 401 instruction_size = 6 * BytesPerInstWord
aoqi@1 402 #endif
aoqi@1 403 };
aoqi@1 404
aoqi@1 405 bool is_short() const { return (long_at(instruction_offset) & b_mask) == beq_opcode; }
aoqi@1 406 #ifdef _LP64
aoqi@1 407 bool is_b_far();
aoqi@1 408 #endif
aoqi@1 409 address instruction_address() const { return addr_at(instruction_offset); }
aoqi@1 410 address jump_destination();
aoqi@1 411
aoqi@1 412 void set_jump_destination(address dest);
aoqi@1 413
aoqi@1 414 // Creation
aoqi@1 415 inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
aoqi@1 416
aoqi@1 417 // Insertion of native general jump instruction
aoqi@1 418 static void insert_unconditional(address code_pos, address entry);
aoqi@1 419 static void replace_mt_safe(address instr_addr, address code_buffer);
aoqi@1 420 static void check_verified_entry_alignment(address entry, address verified_entry){}
aoqi@1 421 static void patch_verified_entry(address entry, address verified_entry, address dest);
aoqi@1 422
aoqi@1 423 void verify();
aoqi@1 424 };
aoqi@1 425
aoqi@1 426 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
aoqi@1 427 NativeGeneralJump* jump = (NativeGeneralJump*)(address);
aoqi@1 428 debug_only(jump->verify();)
aoqi@1 429 return jump;
aoqi@1 430 }
aoqi@1 431
aoqi@1 432 /*class NativePopReg : public NativeInstruction {
aoqi@1 433 public:
aoqi@1 434 enum Intel_specific_constants {
aoqi@1 435 instruction_code = 0x58,
aoqi@1 436 instruction_size = 1,
aoqi@1 437 instruction_offset = 0,
aoqi@1 438 data_offset = 1,
aoqi@1 439 next_instruction_offset = 1
aoqi@1 440 };
aoqi@1 441
aoqi@1 442 // Insert a pop instruction
aoqi@1 443 static void insert(address code_pos, Register reg);
aoqi@1 444 };*/
aoqi@1 445
aoqi@1 446
aoqi@1 447 class NativeIllegalInstruction: public NativeInstruction {
aoqi@1 448 public:
aoqi@1 449 enum Intel_specific_constants {
aoqi@1 450 instruction_size = 4,
aoqi@1 451 instruction_offset = 0,
aoqi@1 452 next_instruction_offset = 4
aoqi@1 453 };
aoqi@1 454
aoqi@1 455 // Insert illegal opcode as specific address
aoqi@1 456 static void insert(address code_pos);
aoqi@1 457 };
aoqi@1 458
aoqi@1 459 // return instruction that does not pop values of the stack
aoqi@1 460 // jr RA
aoqi@1 461 // delay slot
aoqi@1 462 class NativeReturn: public NativeInstruction {
aoqi@1 463 public:
aoqi@1 464 enum mips_specific_constants {
aoqi@1 465 instruction_size = 8,
aoqi@1 466 instruction_offset = 0,
aoqi@1 467 next_instruction_offset = 8
aoqi@1 468 };
aoqi@1 469 };
aoqi@1 470
aoqi@1 471
aoqi@1 472
aoqi@1 473
aoqi@1 474 class NativeCondJump;
aoqi@1 475 inline NativeCondJump* nativeCondJump_at(address address);
aoqi@1 476 class NativeCondJump: public NativeInstruction {
aoqi@1 477 public:
aoqi@1 478 enum mips_specific_constants {
aoqi@1 479 instruction_size = 16,
aoqi@1 480 instruction_offset = 12,
aoqi@1 481 next_instruction_offset = 20
aoqi@1 482 };
aoqi@1 483
aoqi@1 484
aoqi@1 485 int insn_word() const { return long_at(instruction_offset); }
aoqi@1 486 address instruction_address() const { return addr_at(0); }
aoqi@1 487 address next_instruction_address() const { return addr_at(next_instruction_offset); }
aoqi@1 488
aoqi@1 489 // Creation
aoqi@1 490 inline friend NativeCondJump* nativeCondJump_at(address address);
aoqi@1 491
aoqi@1 492 address jump_destination() const {
aoqi@1 493 return ::nativeCondJump_at(addr_at(12))->jump_destination();
aoqi@1 494 }
aoqi@1 495
aoqi@1 496 void set_jump_destination(address dest) {
aoqi@1 497 ::nativeCondJump_at(addr_at(12))->set_jump_destination(dest);
aoqi@1 498 }
aoqi@1 499
aoqi@1 500 };
aoqi@1 501
aoqi@1 502 inline NativeCondJump* nativeCondJump_at(address address) {
aoqi@1 503 NativeCondJump* jump = (NativeCondJump*)(address);
aoqi@1 504 return jump;
aoqi@1 505 }
aoqi@1 506
aoqi@1 507
aoqi@1 508
aoqi@1 509 inline bool NativeInstruction::is_illegal() { return insn_word() == illegal_instruction(); }
aoqi@1 510
aoqi@1 511 inline bool NativeInstruction::is_call() {
aoqi@1 512 #ifndef _LP64
aoqi@1 513 return is_op(long_at(0), Assembler::lui_op) &&
aoqi@1 514 is_op(long_at(4), Assembler::addiu_op) &&
aoqi@1 515 is_special_op(long_at(8), Assembler::jalr_op);
aoqi@1 516 #else
aoqi@1 517 /* li64 or li48 */
aoqi@1 518 if (is_special_op(long_at(16), Assembler::dsll_op)) {
aoqi@1 519 /* li64 */
aoqi@1 520 return is_op(long_at(0), Assembler::lui_op) &&
aoqi@1 521 is_op(long_at(4), Assembler::ori_op) &&
aoqi@1 522 is_special_op(long_at(8), Assembler::dsll_op) &&
aoqi@1 523 is_op(long_at(12), Assembler::ori_op) &&
aoqi@1 524 is_special_op(long_at(16), Assembler::dsll_op) &&
aoqi@1 525 is_op(long_at(20), Assembler::ori_op) &&
aoqi@1 526 is_special_op(long_at(24), Assembler::jalr_op);
aoqi@1 527 } else {
aoqi@1 528 /* li48 */
aoqi@1 529 return is_op(long_at(0), Assembler::lui_op) &&
aoqi@1 530 is_op(long_at(4), Assembler::ori_op) &&
aoqi@1 531 is_special_op(long_at(8), Assembler::dsll_op) &&
aoqi@1 532 is_op(long_at(12), Assembler::ori_op) &&
aoqi@1 533 is_special_op(long_at(16), Assembler::jalr_op);
aoqi@1 534 }
aoqi@1 535 #endif
aoqi@1 536 }
aoqi@1 537
aoqi@1 538 inline bool NativeInstruction::is_return() { return is_special_op(Assembler::jr_op) && is_rs(RA);}
aoqi@1 539
aoqi@1 540 inline bool NativeInstruction::is_cond_jump() { return is_int_branch() || is_float_branch(); }
aoqi@1 541 #endif // CPU_MIPS_VM_NATIVEINST_MIPS_HPP
aoqi@1 542

mercurial