Thu, 07 Sep 2017 09:12:16 +0800
#5745 [Code Reorganization] code cleanup and code style fix
This is a huge patch, but only code cleanup, code style fix and useless code deletion are included, for example:
tab -> two spaces, deleted spacees at the end of a line, delete useless comments.
This patch also included:
Declaration and definition of class MacroAssembler is moved from assembler_mips.h/cpp to macroAssembler_mips.h/cpp
aoqi@1 | 1 | /* |
aoqi@1 | 2 | * Copyright (c) 1997, 2013, 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@6880 | 26 | #ifndef CPU_MIPS_VM_MACROASSEMBLER_MIPS_HPP |
aoqi@6880 | 27 | #define CPU_MIPS_VM_MACROASSEMBLER_MIPS_HPP |
aoqi@1 | 28 | |
aoqi@6880 | 29 | #include "asm/assembler.hpp" |
aoqi@6880 | 30 | #include "utilities/macros.hpp" |
aoqi@6880 | 31 | #include "runtime/rtmLocking.hpp" |
aoqi@1 | 32 | |
aoqi@6880 | 33 | |
aoqi@6880 | 34 | // MacroAssembler extends Assembler by frequently used macros. |
aoqi@6880 | 35 | // |
aoqi@6880 | 36 | // Instructions for which a 'better' code sequence exists depending |
aoqi@6880 | 37 | // on arguments should also go in here. |
aoqi@6880 | 38 | |
aoqi@6880 | 39 | class MacroAssembler: public Assembler { |
aoqi@6880 | 40 | friend class LIR_Assembler; |
aoqi@6880 | 41 | friend class Runtime1; // as_Address() |
aoqi@6880 | 42 | |
aoqi@6880 | 43 | protected: |
aoqi@6880 | 44 | |
aoqi@6880 | 45 | Address as_Address(AddressLiteral adr); |
aoqi@6880 | 46 | Address as_Address(ArrayAddress adr); |
aoqi@6880 | 47 | |
aoqi@6880 | 48 | // Support for VM calls |
aoqi@6880 | 49 | // |
aoqi@6880 | 50 | // This is the base routine called by the different versions of call_VM_leaf. The interpreter |
aoqi@6880 | 51 | // may customize this version by overriding it for its purposes (e.g., to save/restore |
aoqi@6880 | 52 | // additional registers when doing a VM call). |
aoqi@6880 | 53 | #ifdef CC_INTERP |
aoqi@6880 | 54 | // c++ interpreter never wants to use interp_masm version of call_VM |
aoqi@6880 | 55 | #define VIRTUAL |
aoqi@6880 | 56 | #else |
aoqi@6880 | 57 | #define VIRTUAL virtual |
aoqi@6880 | 58 | #endif |
aoqi@6880 | 59 | |
aoqi@6880 | 60 | VIRTUAL void call_VM_leaf_base( |
aoqi@6880 | 61 | address entry_point, // the entry point |
aoqi@6880 | 62 | int number_of_arguments // the number of arguments to pop after the call |
aoqi@6880 | 63 | ); |
aoqi@6880 | 64 | |
aoqi@6880 | 65 | // This is the base routine called by the different versions of call_VM. The interpreter |
aoqi@6880 | 66 | // may customize this version by overriding it for its purposes (e.g., to save/restore |
aoqi@6880 | 67 | // additional registers when doing a VM call). |
aoqi@6880 | 68 | // |
aoqi@6880 | 69 | // If no java_thread register is specified (noreg) than rdi will be used instead. call_VM_base |
aoqi@6880 | 70 | // returns the register which contains the thread upon return. If a thread register has been |
aoqi@6880 | 71 | // specified, the return value will correspond to that register. If no last_java_sp is specified |
aoqi@6880 | 72 | // (noreg) than rsp will be used instead. |
aoqi@6880 | 73 | VIRTUAL void call_VM_base( // returns the register containing the thread upon return |
aoqi@6880 | 74 | Register oop_result, // where an oop-result ends up if any; use noreg otherwise |
aoqi@6880 | 75 | Register java_thread, // the thread if computed before ; use noreg otherwise |
aoqi@6880 | 76 | Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise |
aoqi@6880 | 77 | address entry_point, // the entry point |
aoqi@6880 | 78 | int number_of_arguments, // the number of arguments (w/o thread) to pop after the call |
aoqi@6880 | 79 | bool check_exceptions // whether to check for pending exceptions after return |
aoqi@6880 | 80 | ); |
aoqi@6880 | 81 | |
aoqi@6880 | 82 | // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. |
aoqi@6880 | 83 | // The implementation is only non-empty for the InterpreterMacroAssembler, |
aoqi@6880 | 84 | // as only the interpreter handles PopFrame and ForceEarlyReturn requests. |
aoqi@6880 | 85 | virtual void check_and_handle_popframe(Register java_thread); |
aoqi@6880 | 86 | virtual void check_and_handle_earlyret(Register java_thread); |
aoqi@6880 | 87 | |
aoqi@6880 | 88 | void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); |
aoqi@6880 | 89 | |
aoqi@6880 | 90 | // helpers for FPU flag access |
aoqi@6880 | 91 | // tmp is a temporary register, if none is available use noreg |
aoqi@6880 | 92 | |
aoqi@6880 | 93 | public: |
aoqi@6880 | 94 | static intptr_t i[32]; |
aoqi@6880 | 95 | static float f[32]; |
aoqi@6880 | 96 | static void print(outputStream *s); |
aoqi@6880 | 97 | |
aoqi@6880 | 98 | static int i_offset(unsigned int k); |
aoqi@6880 | 99 | static int f_offset(unsigned int k); |
aoqi@6880 | 100 | |
aoqi@6880 | 101 | static void save_registers(MacroAssembler *masm); |
aoqi@6880 | 102 | static void restore_registers(MacroAssembler *masm); |
aoqi@6880 | 103 | |
aoqi@6880 | 104 | MacroAssembler(CodeBuffer* code) : Assembler(code) {} |
aoqi@6880 | 105 | |
aoqi@6880 | 106 | // Support for NULL-checks |
aoqi@6880 | 107 | // |
aoqi@6880 | 108 | // Generates code that causes a NULL OS exception if the content of reg is NULL. |
aoqi@6880 | 109 | // If the accessed location is M[reg + offset] and the offset is known, provide the |
aoqi@6880 | 110 | // offset. No explicit code generation is needed if the offset is within a certain |
aoqi@6880 | 111 | // range (0 <= offset <= page_size). |
aoqi@6880 | 112 | |
aoqi@6880 | 113 | void null_check(Register reg, int offset = -1); |
aoqi@6880 | 114 | static bool needs_explicit_null_check(intptr_t offset); |
aoqi@6880 | 115 | |
aoqi@6880 | 116 | // Required platform-specific helpers for Label::patch_instructions. |
aoqi@6880 | 117 | // They _shadow_ the declarations in AbstractAssembler, which are undefined. |
aoqi@6880 | 118 | void pd_patch_instruction(address branch, address target); |
aoqi@6880 | 119 | |
aoqi@6880 | 120 | // Support for inc/dec with optimal instruction selection depending on value |
aoqi@6880 | 121 | void incrementl(Register reg, int value = 1); |
aoqi@6880 | 122 | void decrementl(Register reg, int value = 1); |
aoqi@6880 | 123 | |
aoqi@6880 | 124 | |
aoqi@6880 | 125 | // Alignment |
aoqi@6880 | 126 | void align(int modulus); |
aoqi@6880 | 127 | |
aoqi@6880 | 128 | |
aoqi@6880 | 129 | // Stack frame creation/removal |
aoqi@6880 | 130 | void enter(); |
aoqi@6880 | 131 | void leave(); |
aoqi@6880 | 132 | |
aoqi@6880 | 133 | // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information) |
aoqi@6880 | 134 | // The pointer will be loaded into the thread register. |
aoqi@6880 | 135 | void get_thread(Register thread); |
aoqi@6880 | 136 | |
aoqi@6880 | 137 | |
aoqi@6880 | 138 | // Support for VM calls |
aoqi@6880 | 139 | // |
aoqi@6880 | 140 | // It is imperative that all calls into the VM are handled via the call_VM macros. |
aoqi@6880 | 141 | // They make sure that the stack linkage is setup correctly. call_VM's correspond |
aoqi@6880 | 142 | // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. |
aoqi@6880 | 143 | |
aoqi@6880 | 144 | |
aoqi@6880 | 145 | void call_VM(Register oop_result, |
aoqi@6880 | 146 | address entry_point, |
aoqi@6880 | 147 | bool check_exceptions = true); |
aoqi@6880 | 148 | void call_VM(Register oop_result, |
aoqi@6880 | 149 | address entry_point, |
aoqi@6880 | 150 | Register arg_1, |
aoqi@6880 | 151 | bool check_exceptions = true); |
aoqi@6880 | 152 | void call_VM(Register oop_result, |
aoqi@6880 | 153 | address entry_point, |
aoqi@6880 | 154 | Register arg_1, Register arg_2, |
aoqi@6880 | 155 | bool check_exceptions = true); |
aoqi@6880 | 156 | void call_VM(Register oop_result, |
aoqi@6880 | 157 | address entry_point, |
aoqi@6880 | 158 | Register arg_1, Register arg_2, Register arg_3, |
aoqi@6880 | 159 | bool check_exceptions = true); |
aoqi@6880 | 160 | |
aoqi@6880 | 161 | // Overloadings with last_Java_sp |
aoqi@6880 | 162 | void call_VM(Register oop_result, |
aoqi@6880 | 163 | Register last_java_sp, |
aoqi@6880 | 164 | address entry_point, |
aoqi@6880 | 165 | int number_of_arguments = 0, |
aoqi@6880 | 166 | bool check_exceptions = true); |
aoqi@6880 | 167 | void call_VM(Register oop_result, |
aoqi@6880 | 168 | Register last_java_sp, |
aoqi@6880 | 169 | address entry_point, |
aoqi@6880 | 170 | Register arg_1, bool |
aoqi@6880 | 171 | check_exceptions = true); |
aoqi@6880 | 172 | void call_VM(Register oop_result, |
aoqi@6880 | 173 | Register last_java_sp, |
aoqi@6880 | 174 | address entry_point, |
aoqi@6880 | 175 | Register arg_1, Register arg_2, |
aoqi@6880 | 176 | bool check_exceptions = true); |
aoqi@6880 | 177 | void call_VM(Register oop_result, |
aoqi@6880 | 178 | Register last_java_sp, |
aoqi@6880 | 179 | address entry_point, |
aoqi@6880 | 180 | Register arg_1, Register arg_2, Register arg_3, |
aoqi@6880 | 181 | bool check_exceptions = true); |
aoqi@6880 | 182 | |
aoqi@6880 | 183 | void get_vm_result (Register oop_result, Register thread); |
aoqi@6880 | 184 | void get_vm_result_2(Register metadata_result, Register thread); |
aoqi@6880 | 185 | void call_VM_leaf(address entry_point, |
aoqi@6880 | 186 | int number_of_arguments = 0); |
aoqi@6880 | 187 | void call_VM_leaf(address entry_point, |
aoqi@6880 | 188 | Register arg_1); |
aoqi@6880 | 189 | void call_VM_leaf(address entry_point, |
aoqi@6880 | 190 | Register arg_1, Register arg_2); |
aoqi@6880 | 191 | void call_VM_leaf(address entry_point, |
aoqi@6880 | 192 | Register arg_1, Register arg_2, Register arg_3); |
aoqi@6880 | 193 | |
aoqi@6880 | 194 | // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls |
aoqi@6880 | 195 | void super_call_VM_leaf(address entry_point); |
aoqi@6880 | 196 | void super_call_VM_leaf(address entry_point, Register arg_1); |
aoqi@6880 | 197 | void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2); |
aoqi@6880 | 198 | void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); |
aoqi@6880 | 199 | // last Java Frame (fills frame anchor) |
aoqi@6880 | 200 | void set_last_Java_frame(Register thread, |
aoqi@6880 | 201 | Register last_java_sp, |
aoqi@6880 | 202 | Register last_java_fp, |
aoqi@6880 | 203 | address last_java_pc); |
aoqi@6880 | 204 | |
aoqi@6880 | 205 | // thread in the default location (r15_thread on 64bit) |
aoqi@6880 | 206 | void set_last_Java_frame(Register last_java_sp, |
aoqi@6880 | 207 | Register last_java_fp, |
aoqi@6880 | 208 | address last_java_pc); |
aoqi@6880 | 209 | |
aoqi@6880 | 210 | void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc); |
aoqi@6880 | 211 | |
aoqi@6880 | 212 | // thread in the default location (r15_thread on 64bit) |
aoqi@6880 | 213 | void reset_last_Java_frame(bool clear_fp, bool clear_pc); |
aoqi@6880 | 214 | |
aoqi@6880 | 215 | // Stores |
aoqi@6880 | 216 | void store_check(Register obj); // store check for obj - register is destroyed afterwards |
aoqi@6880 | 217 | void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) |
aoqi@6880 | 218 | |
aoqi@6880 | 219 | #if INCLUDE_ALL_GCS |
aoqi@6880 | 220 | |
aoqi@6880 | 221 | void g1_write_barrier_pre(Register obj, |
aoqi@6880 | 222 | #ifndef _LP64 |
aoqi@6880 | 223 | Register thread, |
aoqi@6880 | 224 | #endif |
aoqi@6880 | 225 | Register tmp, |
aoqi@6880 | 226 | Register tmp2, |
aoqi@6880 | 227 | bool tosca_live); |
aoqi@6880 | 228 | |
aoqi@6880 | 229 | void g1_write_barrier_post(Register store_addr, |
aoqi@6880 | 230 | Register new_val, |
aoqi@6880 | 231 | #ifndef _LP64 |
aoqi@6880 | 232 | Register thread, |
aoqi@6880 | 233 | #endif |
aoqi@6880 | 234 | Register tmp, |
aoqi@6880 | 235 | Register tmp2); |
aoqi@6880 | 236 | |
aoqi@6880 | 237 | #endif // INCLUDE_ALL_GCS |
aoqi@6880 | 238 | |
aoqi@6880 | 239 | // split store_check(Register obj) to enhance instruction interleaving |
aoqi@6880 | 240 | void store_check_part_1(Register obj); |
aoqi@6880 | 241 | void store_check_part_2(Register obj); |
aoqi@6880 | 242 | |
aoqi@6880 | 243 | // C 'boolean' to Java boolean: x == 0 ? 0 : 1 |
aoqi@6880 | 244 | void c2bool(Register x); |
aoqi@6880 | 245 | //add for compressedoops |
aoqi@6880 | 246 | void load_klass(Register dst, Register src); |
aoqi@6880 | 247 | void store_klass(Register dst, Register src); |
aoqi@6880 | 248 | void load_prototype_header(Register dst, Register src); |
aoqi@6880 | 249 | |
aoqi@6880 | 250 | #ifdef _LP64 |
aoqi@6880 | 251 | void store_klass_gap(Register dst, Register src); |
aoqi@6880 | 252 | |
aoqi@6880 | 253 | void load_heap_oop(Register dst, Address src); |
aoqi@6880 | 254 | void store_heap_oop(Address dst, Register src); |
aoqi@6880 | 255 | void encode_heap_oop(Register r); |
aoqi@6880 | 256 | void encode_heap_oop(Register dst, Register src); |
aoqi@6880 | 257 | void decode_heap_oop(Register r); |
aoqi@6880 | 258 | void decode_heap_oop(Register dst, Register src); |
aoqi@6880 | 259 | void encode_heap_oop_not_null(Register r); |
aoqi@6880 | 260 | void decode_heap_oop_not_null(Register r); |
aoqi@6880 | 261 | void encode_heap_oop_not_null(Register dst, Register src); |
aoqi@6880 | 262 | void decode_heap_oop_not_null(Register dst, Register src); |
aoqi@6880 | 263 | |
aoqi@6880 | 264 | void encode_klass_not_null(Register r); |
aoqi@6880 | 265 | void decode_klass_not_null(Register r); |
aoqi@6880 | 266 | void encode_klass_not_null(Register dst, Register src); |
aoqi@6880 | 267 | void decode_klass_not_null(Register dst, Register src); |
aoqi@6880 | 268 | |
aoqi@6880 | 269 | // Returns the byte size of the instructions generated by decode_klass_not_null() |
aoqi@6880 | 270 | // when compressed klass pointers are being used. |
aoqi@6880 | 271 | static int instr_size_for_decode_klass_not_null(); |
aoqi@6880 | 272 | |
aoqi@6880 | 273 | // if heap base register is used - reinit it with the correct value |
aoqi@6880 | 274 | void reinit_heapbase(); |
aoqi@6880 | 275 | |
aoqi@6880 | 276 | DEBUG_ONLY(void verify_heapbase(const char* msg);) |
aoqi@6880 | 277 | |
aoqi@6880 | 278 | void set_narrow_klass(Register dst, Klass* k); |
aoqi@6880 | 279 | void set_narrow_oop(Register dst, jobject obj); |
aoqi@6880 | 280 | |
aoqi@6880 | 281 | #endif // _LP64 |
aoqi@6880 | 282 | |
aoqi@6880 | 283 | |
aoqi@6880 | 284 | |
aoqi@6880 | 285 | void int3(); |
aoqi@6880 | 286 | // Sign extension |
aoqi@6880 | 287 | #ifdef _LP64 |
aoqi@6880 | 288 | void sign_extend_short(Register reg) { /*dsll32(reg, reg, 16); dsra32(reg, reg, 16);*/ seh(reg, reg); } |
aoqi@6880 | 289 | void sign_extend_byte(Register reg) { /*dsll32(reg, reg, 24); dsra32(reg, reg, 24);*/ seb(reg, reg); } |
aoqi@6880 | 290 | #else |
aoqi@6880 | 291 | void sign_extend_short(Register reg) { /*sll(reg, reg, 16); sra(reg, reg, 16);*/ seh(reg, reg); } |
aoqi@6880 | 292 | void sign_extend_byte(Register reg) { /*sll(reg, reg, 24); sra(reg, reg, 24);*/ seb(reg, reg);} |
aoqi@6880 | 293 | #endif |
aoqi@6880 | 294 | void rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp); |
aoqi@6880 | 295 | void rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp); |
aoqi@6880 | 296 | |
aoqi@6880 | 297 | // Inlined sin/cos generator for Java; must not use CPU instruction |
aoqi@6880 | 298 | // directly on Intel as it does not have high enough precision |
aoqi@6880 | 299 | // outside of the range [-pi/4, pi/4]. Extra argument indicate the |
aoqi@6880 | 300 | // number of FPU stack slots in use; all but the topmost will |
aoqi@6880 | 301 | // require saving if a slow case is necessary. Assumes argument is |
aoqi@6880 | 302 | // on FP TOS; result is on FP TOS. No cpu registers are changed by |
aoqi@6880 | 303 | // this code. |
aoqi@6880 | 304 | void trigfunc(char trig, int num_fpu_regs_in_use = 1); |
aoqi@6880 | 305 | // allocation |
aoqi@6880 | 306 | void eden_allocate( |
aoqi@6880 | 307 | Register obj, // result: pointer to object after successful allocation |
aoqi@6880 | 308 | Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise |
aoqi@6880 | 309 | int con_size_in_bytes, // object size in bytes if known at compile time |
aoqi@6880 | 310 | Register t1, // temp register |
aoqi@6880 | 311 | Register t2, |
aoqi@6880 | 312 | Label& slow_case // continuation point if fast allocation fails |
aoqi@6880 | 313 | ); |
aoqi@6880 | 314 | void tlab_allocate( |
aoqi@6880 | 315 | Register obj, // result: pointer to object after successful allocation |
aoqi@6880 | 316 | Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise |
aoqi@6880 | 317 | int con_size_in_bytes, // object size in bytes if known at compile time |
aoqi@6880 | 318 | Register t1, // temp register |
aoqi@6880 | 319 | Register t2, // temp register |
aoqi@6880 | 320 | Label& slow_case // continuation point if fast allocation fails |
aoqi@6880 | 321 | ); |
aoqi@6880 | 322 | void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); |
aoqi@6880 | 323 | // interface method calling |
aoqi@6880 | 324 | void lookup_interface_method(Register recv_klass, |
aoqi@6880 | 325 | Register intf_klass, |
aoqi@6880 | 326 | RegisterOrConstant itable_index, |
aoqi@6880 | 327 | Register method_result, |
aoqi@6880 | 328 | Register scan_temp, |
aoqi@6880 | 329 | Label& no_such_interface); |
aoqi@6880 | 330 | |
aoqi@6880 | 331 | // virtual method calling |
aoqi@6880 | 332 | void lookup_virtual_method(Register recv_klass, |
aoqi@6880 | 333 | RegisterOrConstant vtable_index, |
aoqi@6880 | 334 | Register method_result); |
aoqi@6880 | 335 | |
aoqi@6880 | 336 | // Test sub_klass against super_klass, with fast and slow paths. |
aoqi@6880 | 337 | |
aoqi@6880 | 338 | // The fast path produces a tri-state answer: yes / no / maybe-slow. |
aoqi@6880 | 339 | // One of the three labels can be NULL, meaning take the fall-through. |
aoqi@6880 | 340 | // If super_check_offset is -1, the value is loaded up from super_klass. |
aoqi@6880 | 341 | // No registers are killed, except temp_reg. |
aoqi@6880 | 342 | void check_klass_subtype_fast_path(Register sub_klass, |
aoqi@6880 | 343 | Register super_klass, |
aoqi@6880 | 344 | Register temp_reg, |
aoqi@6880 | 345 | Label* L_success, |
aoqi@6880 | 346 | Label* L_failure, |
aoqi@6880 | 347 | Label* L_slow_path, |
aoqi@6880 | 348 | RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); |
aoqi@6880 | 349 | |
aoqi@6880 | 350 | // The rest of the type check; must be wired to a corresponding fast path. |
aoqi@6880 | 351 | // It does not repeat the fast path logic, so don't use it standalone. |
aoqi@6880 | 352 | // The temp_reg and temp2_reg can be noreg, if no temps are available. |
aoqi@6880 | 353 | // Updates the sub's secondary super cache as necessary. |
aoqi@6880 | 354 | // If set_cond_codes, condition codes will be Z on success, NZ on failure. |
aoqi@6880 | 355 | void check_klass_subtype_slow_path(Register sub_klass, |
aoqi@6880 | 356 | Register super_klass, |
aoqi@6880 | 357 | Register temp_reg, |
aoqi@6880 | 358 | Register temp2_reg, |
aoqi@6880 | 359 | Label* L_success, |
aoqi@6880 | 360 | Label* L_failure, |
aoqi@6880 | 361 | bool set_cond_codes = false); |
aoqi@6880 | 362 | |
aoqi@6880 | 363 | // Simplified, combined version, good for typical uses. |
aoqi@6880 | 364 | // Falls through on failure. |
aoqi@6880 | 365 | void check_klass_subtype(Register sub_klass, |
aoqi@6880 | 366 | Register super_klass, |
aoqi@6880 | 367 | Register temp_reg, |
aoqi@6880 | 368 | Label& L_success); |
aoqi@6880 | 369 | |
aoqi@6880 | 370 | |
aoqi@6880 | 371 | // Debugging |
aoqi@6880 | 372 | |
aoqi@6880 | 373 | // only if +VerifyOops |
aoqi@6880 | 374 | void verify_oop(Register reg, const char* s = "broken oop"); |
aoqi@6880 | 375 | void verify_oop_addr(Address addr, const char * s = "broken oop addr"); |
aoqi@6880 | 376 | void verify_oop_subroutine(); |
aoqi@6880 | 377 | // TODO: verify method and klass metadata (compare against vptr?) |
aoqi@6880 | 378 | void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} |
aoqi@6880 | 379 | void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} |
aoqi@6880 | 380 | |
aoqi@6880 | 381 | #define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) |
aoqi@6880 | 382 | #define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) |
aoqi@6880 | 383 | |
aoqi@6880 | 384 | // only if +VerifyFPU |
aoqi@6880 | 385 | void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); |
aoqi@6880 | 386 | |
aoqi@6880 | 387 | // prints msg, dumps registers and stops execution |
aoqi@6880 | 388 | void stop(const char* msg); |
aoqi@6880 | 389 | |
aoqi@6880 | 390 | // prints msg and continues |
aoqi@6880 | 391 | void warn(const char* msg); |
aoqi@6880 | 392 | |
aoqi@6880 | 393 | static void debug(char* msg/*, RegistersForDebugging* regs*/); |
aoqi@6880 | 394 | static void debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg); |
aoqi@6880 | 395 | static void debug64(char* msg, int64_t pc, int64_t regs[]); |
aoqi@6880 | 396 | |
aoqi@6880 | 397 | void print_reg(Register reg); |
aoqi@6880 | 398 | void print_reg(FloatRegister reg); |
aoqi@6880 | 399 | //void os_breakpoint(); |
aoqi@6880 | 400 | |
aoqi@6880 | 401 | void untested() { stop("untested"); } |
aoqi@6880 | 402 | |
aoqi@6880 | 403 | void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, sizeof(b), "unimplemented: %s", what); stop(b); } |
aoqi@6880 | 404 | |
aoqi@6880 | 405 | void should_not_reach_here() { stop("should not reach here"); } |
aoqi@6880 | 406 | |
aoqi@6880 | 407 | void print_CPU_state(); |
aoqi@6880 | 408 | |
aoqi@6880 | 409 | // Stack overflow checking |
aoqi@6880 | 410 | void bang_stack_with_offset(int offset) { |
aoqi@6880 | 411 | // stack grows down, caller passes positive offset |
aoqi@6880 | 412 | assert(offset > 0, "must bang with negative offset"); |
aoqi@6880 | 413 | if (offset <= 32768) { |
aoqi@6880 | 414 | sw(A0, SP, -offset); |
aoqi@6880 | 415 | } else { |
aoqi@6880 | 416 | #ifdef _LP64 |
aoqi@6880 | 417 | li(AT, offset); |
aoqi@6880 | 418 | dsub(AT, SP, AT); |
aoqi@6880 | 419 | #else |
aoqi@6880 | 420 | move(AT, offset); |
aoqi@6880 | 421 | sub(AT, SP, AT); |
aoqi@6880 | 422 | #endif |
aoqi@6880 | 423 | sw(A0, AT, 0); |
aoqi@6880 | 424 | } |
aoqi@6880 | 425 | } |
aoqi@6880 | 426 | |
aoqi@6880 | 427 | // Writes to stack successive pages until offset reached to check for |
aoqi@6880 | 428 | // stack overflow + shadow pages. Also, clobbers tmp |
aoqi@6880 | 429 | void bang_stack_size(Register size, Register tmp); |
aoqi@6880 | 430 | |
aoqi@6880 | 431 | virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, |
aoqi@6880 | 432 | Register tmp, |
aoqi@6880 | 433 | int offset); |
aoqi@6880 | 434 | |
aoqi@6880 | 435 | // Support for serializing memory accesses between threads |
aoqi@6880 | 436 | void serialize_memory(Register thread, Register tmp); |
aoqi@6880 | 437 | |
aoqi@6880 | 438 | //void verify_tlab(); |
aoqi@6880 | 439 | void verify_tlab(Register t1, Register t2); |
aoqi@6880 | 440 | |
aoqi@6880 | 441 | // Biased locking support |
aoqi@6880 | 442 | // lock_reg and obj_reg must be loaded up with the appropriate values. |
aoqi@6880 | 443 | // swap_reg must be rax, and is killed. |
aoqi@6880 | 444 | // tmp_reg is optional. If it is supplied (i.e., != noreg) it will |
aoqi@6880 | 445 | // be killed; if not supplied, push/pop will be used internally to |
aoqi@6880 | 446 | // allocate a temporary (inefficient, avoid if possible). |
aoqi@6880 | 447 | // Optional slow case is for implementations (interpreter and C1) which branch to |
aoqi@6880 | 448 | // slow case directly. Leaves condition codes set for C2's Fast_Lock node. |
aoqi@6880 | 449 | // Returns offset of first potentially-faulting instruction for null |
aoqi@6880 | 450 | // check info (currently consumed only by C1). If |
aoqi@6880 | 451 | // swap_reg_contains_mark is true then returns -1 as it is assumed |
aoqi@6880 | 452 | // the calling code has already passed any potential faults. |
aoqi@6880 | 453 | int biased_locking_enter(Register lock_reg, Register obj_reg, |
aoqi@6880 | 454 | Register swap_reg, Register tmp_reg, |
aoqi@6880 | 455 | bool swap_reg_contains_mark, |
aoqi@6880 | 456 | Label& done, Label* slow_case = NULL, |
aoqi@6880 | 457 | BiasedLockingCounters* counters = NULL); |
aoqi@6880 | 458 | void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done); |
aoqi@6880 | 459 | #ifdef COMPILER2 |
aoqi@6880 | 460 | void fast_lock(Register obj, Register box, Register tmp, Register scr); |
aoqi@6880 | 461 | void fast_unlock(Register obj, Register box, Register tmp); |
aoqi@6880 | 462 | #endif |
aoqi@6880 | 463 | |
aoqi@6880 | 464 | |
aoqi@6880 | 465 | // Arithmetics |
aoqi@6880 | 466 | // Regular vs. d* versions |
aoqi@6880 | 467 | inline void addu_long(Register rd, Register rs, Register rt) { |
aoqi@6880 | 468 | #ifdef _LP64 |
aoqi@6880 | 469 | daddu(rd, rs, rt); |
aoqi@6880 | 470 | #else |
aoqi@6880 | 471 | addu(rd, rs, rt); |
aoqi@6880 | 472 | #endif |
aoqi@6880 | 473 | } |
aoqi@6880 | 474 | inline void addu_long(Register rd, Register rs, long imm32_64) { |
aoqi@6880 | 475 | #ifdef _LP64 |
aoqi@6880 | 476 | daddiu(rd, rs, imm32_64); |
aoqi@6880 | 477 | #else |
aoqi@6880 | 478 | addiu(rd, rs, imm32_64); |
aoqi@6880 | 479 | #endif |
aoqi@6880 | 480 | |
aoqi@6880 | 481 | } |
aoqi@6880 | 482 | |
aoqi@6880 | 483 | void round_to(Register reg, int modulus) { |
aoqi@6880 | 484 | assert_different_registers(reg, AT); |
aoqi@6880 | 485 | increment(reg, modulus - 1); |
aoqi@6880 | 486 | move(AT, - modulus); |
aoqi@6880 | 487 | andr(reg, reg, AT); |
aoqi@6880 | 488 | } |
aoqi@6880 | 489 | |
aoqi@6880 | 490 | // the follow two might use AT register, be sure you have no meanful data in AT before you call them |
aoqi@6880 | 491 | void increment(Register reg, int imm); |
aoqi@6880 | 492 | void decrement(Register reg, int imm); |
aoqi@6880 | 493 | |
aoqi@6880 | 494 | #ifdef _LP64 |
aoqi@6880 | 495 | void shl(Register reg, int sa) { dsll(reg, reg, sa); } |
aoqi@6880 | 496 | void shr(Register reg, int sa) { dsrl(reg, reg, sa); } |
aoqi@6880 | 497 | void sar(Register reg, int sa) { dsra(reg, reg, sa); } |
aoqi@6880 | 498 | #else |
aoqi@6880 | 499 | void shl(Register reg, int sa) { sll(reg, reg, sa); } |
aoqi@6880 | 500 | void shr(Register reg, int sa) { srl(reg, reg, sa); } |
aoqi@6880 | 501 | void sar(Register reg, int sa) { sra(reg, reg, sa); } |
aoqi@6880 | 502 | #endif |
aoqi@6880 | 503 | // Helper functions for statistics gathering. |
aoqi@6880 | 504 | void atomic_inc32(address counter_addr, int inc, Register tmp_reg1, Register tmp_reg2); |
aoqi@6880 | 505 | |
aoqi@6880 | 506 | // Calls |
aoqi@6880 | 507 | void call(address entry); |
aoqi@6880 | 508 | void call(address entry, relocInfo::relocType rtype); |
aoqi@6880 | 509 | void call(address entry, RelocationHolder& rh); |
aoqi@6880 | 510 | // Emit the CompiledIC call idiom |
aoqi@6880 | 511 | void ic_call(address entry); |
aoqi@6880 | 512 | |
aoqi@6880 | 513 | // Jumps |
aoqi@6880 | 514 | void jmp(address entry); |
aoqi@6880 | 515 | void jmp(address entry, relocInfo::relocType rtype); |
aoqi@6880 | 516 | |
aoqi@6880 | 517 | /* branches may exceed 16-bit offset */ |
aoqi@6880 | 518 | void b_far(address entry); |
aoqi@6880 | 519 | void b_far(Label& L); |
aoqi@6880 | 520 | |
aoqi@6880 | 521 | void bne_far (Register rs, Register rt, address entry); |
aoqi@6880 | 522 | void bne_far (Register rs, Register rt, Label& L); |
aoqi@6880 | 523 | |
aoqi@6880 | 524 | void beq_far (Register rs, Register rt, address entry); |
aoqi@6880 | 525 | void beq_far (Register rs, Register rt, Label& L); |
aoqi@6880 | 526 | |
aoqi@6880 | 527 | void patchable_call(address target); |
aoqi@6880 | 528 | void general_call(address target); |
aoqi@6880 | 529 | |
aoqi@6880 | 530 | void patchable_jump(address target); |
aoqi@6880 | 531 | void general_jump(address target); |
aoqi@6880 | 532 | |
aoqi@6880 | 533 | static int insts_for_patchable_call(address target); |
aoqi@6880 | 534 | static int insts_for_general_call(address target); |
aoqi@6880 | 535 | |
aoqi@6880 | 536 | static int insts_for_patchable_jump(address target); |
aoqi@6880 | 537 | static int insts_for_general_jump(address target); |
aoqi@6880 | 538 | |
aoqi@6880 | 539 | // Floating |
aoqi@6880 | 540 | // Data |
aoqi@6880 | 541 | |
aoqi@6880 | 542 | // Argument ops |
aoqi@6880 | 543 | inline void store_int_argument(Register s, Argument &a) { |
aoqi@6880 | 544 | if(a.is_Register()) { |
aoqi@6880 | 545 | move(a.as_Register(), s); |
aoqi@6880 | 546 | } else { |
aoqi@6880 | 547 | sw(s, a.as_caller_address()); |
aoqi@6880 | 548 | } |
aoqi@6880 | 549 | } |
aoqi@6880 | 550 | |
aoqi@6880 | 551 | inline void store_long_argument(Register s, Argument &a) { |
aoqi@6880 | 552 | Argument a1 = a.successor(); |
aoqi@6880 | 553 | if(a.is_Register() && a1.is_Register()) { |
aoqi@6880 | 554 | move(a.as_Register(), s); |
aoqi@6880 | 555 | move(a.as_Register(), s); |
aoqi@6880 | 556 | } else { |
aoqi@6880 | 557 | sd(s, a.as_caller_address()); |
aoqi@6880 | 558 | } |
aoqi@6880 | 559 | } |
aoqi@6880 | 560 | |
aoqi@6880 | 561 | inline void store_float_argument(FloatRegister s, Argument &a) { |
aoqi@6880 | 562 | if(a.is_Register()) { |
aoqi@6880 | 563 | mov_s(a.as_FloatRegister(), s); |
aoqi@6880 | 564 | } else { |
aoqi@6880 | 565 | swc1(s, a.as_caller_address()); |
aoqi@6880 | 566 | } |
aoqi@6880 | 567 | } |
aoqi@6880 | 568 | inline void store_double_argument(FloatRegister s, Argument &a) { |
aoqi@6880 | 569 | if(a.is_Register()) { |
aoqi@6880 | 570 | mov_d(a.as_FloatRegister(), s); |
aoqi@6880 | 571 | } else { |
aoqi@6880 | 572 | sdc1(s, a.as_caller_address()); |
aoqi@6880 | 573 | } |
aoqi@6880 | 574 | } |
aoqi@6880 | 575 | |
aoqi@6880 | 576 | inline void store_ptr_argument(Register s, Argument &a) { |
aoqi@6880 | 577 | if(a.is_Register()) { |
aoqi@6880 | 578 | move(a.as_Register(), s); |
aoqi@6880 | 579 | } else { |
aoqi@6880 | 580 | st_ptr(s, a.as_caller_address()); |
aoqi@6880 | 581 | } |
aoqi@6880 | 582 | } |
aoqi@6880 | 583 | |
aoqi@6880 | 584 | // Load and store values by size and signed-ness |
aoqi@6880 | 585 | void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg); |
aoqi@6880 | 586 | void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg); |
aoqi@6880 | 587 | |
aoqi@6880 | 588 | // ld_ptr will perform lw for 32 bit VMs and ld for 64 bit VMs |
aoqi@6880 | 589 | // st_ptr will perform sw for 32 bit VMs and sd for 64 bit VMs |
aoqi@6880 | 590 | inline void ld_ptr(Register rt, Address a){ |
aoqi@6880 | 591 | #ifdef _LP64 |
aoqi@6880 | 592 | ld(rt, a.base(), a.disp()); |
aoqi@6880 | 593 | #else |
aoqi@6880 | 594 | lw(rt, a.base(), a.disp()); |
aoqi@6880 | 595 | #endif |
aoqi@6880 | 596 | } |
aoqi@6880 | 597 | inline void ld_ptr(Register rt, Register base, int offset16){ |
aoqi@6880 | 598 | #ifdef _LP64 |
aoqi@6880 | 599 | ld(rt, base, offset16); |
aoqi@6880 | 600 | #else |
aoqi@6880 | 601 | lw(rt, base, offset16); |
aoqi@6880 | 602 | #endif |
aoqi@6880 | 603 | |
aoqi@6880 | 604 | } |
aoqi@6880 | 605 | inline void st_ptr(Register rt, Address a){ |
aoqi@6880 | 606 | #ifdef _LP64 |
aoqi@6880 | 607 | sd(rt, a.base(), a.disp()); |
aoqi@6880 | 608 | #else |
aoqi@6880 | 609 | sw(rt, a.base(), a.disp()); |
aoqi@6880 | 610 | #endif |
aoqi@6880 | 611 | } |
aoqi@6880 | 612 | inline void st_ptr(Register rt, Register base, int offset16) { |
aoqi@6880 | 613 | #ifdef _LP64 |
aoqi@6880 | 614 | sd(rt, base, offset16); |
aoqi@6880 | 615 | #else |
aoqi@6880 | 616 | sw(rt, base, offset16); |
aoqi@6880 | 617 | #endif |
aoqi@6880 | 618 | } |
aoqi@6880 | 619 | |
aoqi@6880 | 620 | void ld_ptr(Register rt, Register offset, Register base); |
aoqi@6880 | 621 | void st_ptr(Register rt, Register offset, Register base); |
aoqi@6880 | 622 | |
aoqi@6880 | 623 | // ld_long will perform lw for 32 bit VMs and ld for 64 bit VMs |
aoqi@6880 | 624 | // st_long will perform sw for 32 bit VMs and sd for 64 bit VMs |
aoqi@6880 | 625 | inline void ld_long(Register rt, Register base, int offset16); |
aoqi@6880 | 626 | inline void st_long(Register rt, Register base, int offset16); |
aoqi@6880 | 627 | inline void ld_long(Register rt, Address a); |
aoqi@6880 | 628 | inline void st_long(Register rt, Address a); |
aoqi@6880 | 629 | void ld_long(Register rt, Register offset, Register base); |
aoqi@6880 | 630 | void st_long(Register rt, Register offset, Register base); |
aoqi@6880 | 631 | |
aoqi@6880 | 632 | // swap the two byte of the low 16-bit halfword |
aoqi@6880 | 633 | // this directive will use AT, be sure the high 16-bit of reg is zero |
aoqi@6880 | 634 | void hswap(Register reg); |
aoqi@6880 | 635 | void huswap(Register reg); |
aoqi@6880 | 636 | |
aoqi@6880 | 637 | // convert big endian integer to little endian integer |
aoqi@6880 | 638 | void swap(Register reg); |
aoqi@6880 | 639 | |
aoqi@6880 | 640 | // implement the x86 instruction semantic |
aoqi@6880 | 641 | // if c_reg == *dest then *dest <= x_reg |
aoqi@6880 | 642 | // else c_reg <= *dest |
aoqi@6880 | 643 | // the AT indicate if xchg occurred, 1 for xchged, else 0 |
aoqi@6880 | 644 | void cmpxchg(Register x_reg, Address dest, Register c_reg); |
aoqi@6880 | 645 | #ifdef _LP64 |
aoqi@6880 | 646 | void cmpxchg32(Register x_reg, Address dest, Register c_reg); |
aoqi@6880 | 647 | #endif |
aoqi@6880 | 648 | void cmpxchg8(Register x_regLo, Register x_regHi, Address dest, Register c_regLo, Register c_regHi); |
aoqi@6880 | 649 | |
aoqi@6880 | 650 | //pop & push, added by aoqi |
aoqi@6880 | 651 | #ifdef _LP64 |
aoqi@6880 | 652 | void extend_sign(Register rh, Register rl) { stop("extend_sign"); } |
aoqi@6880 | 653 | void neg(Register reg) { dsubu(reg, R0, reg); } |
aoqi@6880 | 654 | void push (Register reg) { sd (reg, SP, -8); daddi(SP, SP, -8); } |
aoqi@6880 | 655 | void push (FloatRegister reg) { sdc1(reg, SP, -8); daddi(SP, SP, -8); } |
aoqi@6880 | 656 | void pop (Register reg) { ld (reg, SP, 0); daddi(SP, SP, 8); } |
aoqi@6880 | 657 | void pop (FloatRegister reg) { ldc1(reg, SP, 0); daddi(SP, SP, 8); } |
aoqi@6880 | 658 | void pop () { daddi(SP, SP, 8); } |
aoqi@6880 | 659 | void pop2 () { daddi(SP, SP, 16); } |
aoqi@6880 | 660 | #else |
aoqi@6880 | 661 | void extend_sign(Register rh, Register rl) { sra(rh, rl, 31); } |
aoqi@6880 | 662 | void neg(Register reg) { subu(reg, R0, reg); } |
aoqi@6880 | 663 | void push (Register reg) { sw (reg, SP, -4); addi(SP, SP, -4); } |
aoqi@6880 | 664 | void push (FloatRegister reg) { swc1(reg, SP, -4); addi(SP, SP, -4); } |
aoqi@6880 | 665 | void pop (Register reg) { lw (reg, SP, 0); addi(SP, SP, 4); } |
aoqi@6880 | 666 | void pop (FloatRegister reg) { lwc1(reg, SP, 0); addi(SP, SP, 4); } |
aoqi@6880 | 667 | void pop () { addi(SP, SP, 4); } |
aoqi@6880 | 668 | void pop2 () { addi(SP, SP, 8); } |
aoqi@6880 | 669 | #endif |
aoqi@6880 | 670 | void push2(Register reg1, Register reg2); |
aoqi@6880 | 671 | void pop2 (Register reg1, Register reg2); |
aoqi@6880 | 672 | void dpush (Register reg) { sd (reg, SP, -8); daddi(SP, SP, -8); } |
aoqi@6880 | 673 | void dpop (Register reg) { ld (reg, SP, 0); daddi(SP, SP, 8); } |
aoqi@6880 | 674 | //we need 2 fun to save and resotre general register |
aoqi@6880 | 675 | void pushad(); |
aoqi@6880 | 676 | void popad(); |
aoqi@6880 | 677 | |
aoqi@6880 | 678 | //move an 32-bit immediate to Register |
aoqi@6880 | 679 | void move(Register reg, int imm32) { li32(reg, imm32); } |
aoqi@6880 | 680 | void li (Register rd, long imm); |
aoqi@6880 | 681 | void li (Register rd, address addr) { li(rd, (long)addr); } |
aoqi@6880 | 682 | //replace move(Register reg, int imm) |
aoqi@6880 | 683 | void li32(Register rd, int imm32); // sign-extends to 64 bits on mips64 |
aoqi@6880 | 684 | #ifdef _LP64 |
aoqi@6880 | 685 | void set64(Register d, jlong value); |
aoqi@6880 | 686 | static int insts_for_set64(jlong value); |
aoqi@6880 | 687 | |
aoqi@6880 | 688 | void patchable_set48(Register d, jlong value); |
aoqi@6880 | 689 | void patchable_set32(Register d, jlong value); |
aoqi@6880 | 690 | |
aoqi@6880 | 691 | void patchable_call32(Register d, jlong value); |
aoqi@6880 | 692 | |
aoqi@6880 | 693 | static int call_size(address target, bool far, bool patchable); |
aoqi@6880 | 694 | |
aoqi@6880 | 695 | static bool reachable_from_cache(address target); |
aoqi@6880 | 696 | |
aoqi@6880 | 697 | |
aoqi@6880 | 698 | void dli(Register rd, long imm) { li(rd, imm); } |
aoqi@6880 | 699 | void li64(Register rd, long imm); |
aoqi@6880 | 700 | void li48(Register rd, long imm); |
aoqi@6880 | 701 | #endif |
aoqi@6880 | 702 | |
aoqi@6880 | 703 | #ifdef _LP64 |
aoqi@6880 | 704 | void move(Register rd, Register rs) { dadd(rd, rs, R0); } |
aoqi@6880 | 705 | void move_u32(Register rd, Register rs) { addu32(rd, rs, R0); } |
aoqi@6880 | 706 | #else |
aoqi@6880 | 707 | void move(Register rd, Register rs) { add(rd, rs, R0); } |
aoqi@6880 | 708 | #endif |
aoqi@6880 | 709 | void dmove(Register rd, Register rs) { dadd(rd, rs, R0); } |
aoqi@6880 | 710 | |
aoqi@6880 | 711 | |
aoqi@6880 | 712 | #ifndef PRODUCT |
aoqi@6880 | 713 | static void pd_print_patched_instruction(address branch) { |
aoqi@6880 | 714 | jint stub_inst = *(jint*) branch; |
aoqi@6880 | 715 | print_instruction(stub_inst); |
aoqi@6880 | 716 | ::tty->print("%s", " (unresolved)"); |
aoqi@6880 | 717 | |
aoqi@6880 | 718 | } |
aoqi@6880 | 719 | #endif |
aoqi@6880 | 720 | |
aoqi@6880 | 721 | //FIXME |
aoqi@6880 | 722 | void empty_FPU_stack(){/*need implemented*/}; |
aoqi@6880 | 723 | |
aoqi@6880 | 724 | |
aoqi@6880 | 725 | // method handles (JSR 292) |
aoqi@6880 | 726 | Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); |
aoqi@6880 | 727 | |
aoqi@6880 | 728 | #undef VIRTUAL |
aoqi@6880 | 729 | |
aoqi@6880 | 730 | }; |
aoqi@6880 | 731 | |
aoqi@6880 | 732 | /** |
aoqi@6880 | 733 | * class SkipIfEqual: |
aoqi@6880 | 734 | * |
aoqi@6880 | 735 | * Instantiating this class will result in assembly code being output that will |
aoqi@6880 | 736 | * jump around any code emitted between the creation of the instance and it's |
aoqi@6880 | 737 | * automatic destruction at the end of a scope block, depending on the value of |
aoqi@6880 | 738 | * the flag passed to the constructor, which will be checked at run-time. |
aoqi@6880 | 739 | */ |
aoqi@6880 | 740 | class SkipIfEqual { |
aoqi@6880 | 741 | private: |
aoqi@6880 | 742 | MacroAssembler* _masm; |
aoqi@6880 | 743 | Label _label; |
aoqi@6880 | 744 | |
aoqi@6880 | 745 | public: |
aoqi@6880 | 746 | SkipIfEqual(MacroAssembler*, const bool* flag_addr, bool value); |
aoqi@6880 | 747 | ~SkipIfEqual(); |
aoqi@6880 | 748 | }; |
aoqi@6880 | 749 | |
aoqi@6880 | 750 | #ifdef ASSERT |
aoqi@6880 | 751 | inline bool AbstractAssembler::pd_check_instruction_mark() { return true; } |
aoqi@6880 | 752 | #endif |
aoqi@6880 | 753 | |
aoqi@6880 | 754 | |
aoqi@6880 | 755 | #endif // CPU_MIPS_VM_MACROASSEMBLER_MIPS_HPP |