Tue, 31 May 2016 00:22:06 -0400
[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