Tue, 26 Jul 2016 11:15:09 +0800
Instruction decoding support: add movn and movz in MIPS disassembler.
1 /*
2 * Copyright (c) 1997, 2010, 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 #ifdef USE_PRAGMA_IDENT_SRC
27 #pragma ident "@(#)disassembler_mips.cpp 1.35 03/12/23 16:36:14 JVM"
28 #endif
29 //by yjl 6/21/2005
30 //FIXME: ugly code here, it always loads a dll/so to do actually work, and dont work for product
31 //change it in the future
32 //1/2, 07 , jerome
33 # include "precompiled.hpp"
34 # include "depChecker_mips.hpp"
35 # include "runtime/fprofiler.hpp"
37 //CHANGE_ME BY YJL
38 #ifndef PRODUCT
40 class mips32_env : public DisassemblerEnv {
41 private:
42 nmethod* code;
43 outputStream* output;
44 public:
45 mips32_env(nmethod* rcode, outputStream* routput) {
46 code = rcode;
47 output = routput;
48 }
49 void print_label(intptr_t value);
50 void print_raw(char* str) { output->print_raw(str); }
51 void print(char* format, ...);
52 char* string_for_offset(intptr_t value);
53 char* string_for_constant(unsigned char* pc, intptr_t value, int is_decimal);
54 };
57 void mips32_env::print_label(intptr_t value) {
58 if (!Universe::is_fully_initialized()) {
59 output->print(INTPTR_FORMAT, value);
60 return;
61 }
62 address adr = (address) value;
63 if (StubRoutines::contains(adr)) {
64 StubCodeDesc* desc = StubCodeDesc::desc_for(adr);
65 const char * desc_name = "unknown stub";
66 if (desc != NULL) {
67 desc_name = desc->name();
68 }
69 output->print("Stub::%s", desc_name);
70 if (WizardMode) output->print(" " INTPTR_FORMAT, value);
71 } else {
72 output->print(INTPTR_FORMAT, value);
73 }
74 }
76 void mips32_env::print(char* format, ...) {
77 va_list ap;
78 va_start(ap, format);
79 output->vprint(format, ap);
80 va_end(ap);
81 }
83 char* mips32_env::string_for_offset(intptr_t value) {
84 stringStream st;
85 if (!Universe::is_fully_initialized()) {
86 st.print("%d", value);
87 return st.as_string();
88 }
89 BarrierSet* bs = Universe::heap()->barrier_set();
90 BarrierSet::Name bsn = bs->kind();
92 if (bs->kind() == BarrierSet::CardTableModRef && (jbyte*) value == ((CardTableModRefBS*)(bs))->byte_map_base) {
93 st.print("word_map_base");
94 } else {
95 st.print("%d", value);
96 }
97 return st.as_string();
98 }
100 char* mips32_env::string_for_constant(unsigned char* pc, intptr_t value, int is_decimal) {
101 stringStream st;
102 oop obj = NULL;
103 #ifndef CORE
104 if (code && (obj = code->embeddedOop_at(pc))!=NULL) {
105 obj->print_value_on(&st);
106 } else
107 #endif
108 {
109 if (is_decimal == 1) {
110 st.print("%d", value);
111 } else {
112 st.print("0x%lx", value);
113 }
114 }
115 return st.as_string();
116 }
118 #define PRINT_NOP() \
119 env->print("nop");
121 #define PRINT_ORRI(OP) \
122 env->print("%s %s, %s, 0x%x", OP, as_Register(Assembler::rt(insn))->name(), \
123 as_Register(Assembler::rs(insn))->name(), \
124 (short)Assembler::low16(insn) )
126 #define PRINT_ORRL(OP) \
127 env->print("%s %s, %s, ", OP, as_Register(Assembler::rs(insn))->name(), \
128 as_Register(Assembler::rt(insn))->name()); \
129 env->print_label( (intptr_t)start + 4 + ((short)Assembler::low16(insn)<<2) )
131 #define PRINT_J(OP) \
132 env->print((char*)OP); \
133 env->print_label( ( ( (intptr_t)start + 4 ) & 0xc0000000 ) | ( Assembler::low26(insn) << 2 ) ); \
134 env->print("");
136 #define PRINT_ORSL(OP) \
137 env->print("%s %s, ", OP, as_Register(Assembler::rs(insn))->name()); \
138 env->print_label( (intptr_t)start + 4 + (short)Assembler::low16(insn) ); \
139 env->print("");
141 #define PRINT_OROB(OP) \
142 env->print("%s %s, 0x%x(%s)", OP, as_Register(Assembler::rt(insn))->name(), \
143 (short)Assembler::low16(insn), \
144 as_Register(Assembler::rs(insn))->name() )
146 #define PRINT_OFOB(OP) \
147 env->print("%s %s, 0x%x(%s)", OP, as_FloatRegister(Assembler::rt(insn))->name(), \
148 (short)Assembler::low16(insn), \
149 as_Register(Assembler::rs(insn))->name() )
152 #define PRINT_ORRS(OP) \
153 env->print("%s %s, %s, %d", OP, as_Register(Assembler::rd(insn))->name(), \
154 as_Register(Assembler::rt(insn))->name(), \
155 Assembler::sa(insn) )
157 #define PRINT_ORRR(OP) \
158 env->print("%s %s, %s, %s", OP, as_Register(Assembler::rd(insn))->name(), \
159 as_Register(Assembler::rs(insn))->name(), \
160 as_Register(Assembler::rt(insn))->name() )
162 #define PRINT_ORRR_2(OP) \
163 env->print("%s %s, %s, %s", OP, as_Register(Assembler::rd(insn))->name(), \
164 as_Register(Assembler::rt(insn))->name(), \
165 as_Register(Assembler::rs(insn))->name() )
167 #define PRINT_ORS(OP) \
168 env->print("%s %s", OP, as_Register(Assembler::rs(insn))->name())
170 #define PRINT_ORD(OP) \
171 env->print("%s %s", OP, as_Register(Assembler::rd(insn))->name())
173 #define PRINT_ORR(OP) \
174 env->print("%s %s, %s", OP, as_Register(Assembler::rs(insn))->name(), \
175 as_Register(Assembler::rt(insn))->name())
177 #define PRINT_ORR_2(OP) \
178 env->print("%s %s, %s", OP, as_Register(Assembler::rt(insn))->name(), \
179 as_Register(Assembler::rd(insn))->name())
181 #define PRINT_FLOAT(OP) \
182 env->print("%s.%s %s, %s, %s", OP, fmt, as_FloatRegister(Assembler::sa(insn))->name(), \
183 as_FloatRegister(Assembler::rd(insn))->name(), \
184 as_FloatRegister(Assembler::rt(insn))->name() )
186 #define PRINT_CVT(OP) \
187 env->print("%s.%s %s, %s", OP, fmt, as_FloatRegister(Assembler::sa(insn))->name(), \
188 as_FloatRegister(Assembler::rd(insn))->name() )
190 static const char* fmt_str(int fmt) {
191 switch(fmt) {
192 case Assembler::single_fmt:
193 return "s";
194 case Assembler::double_fmt:
195 return "d";
196 case Assembler::word_fmt:
197 return "w";
198 case Assembler::long_fmt:
199 return "l";
200 }
202 return "";
203 }
205 address Disassembler::decode_instruction(address start, DisassemblerEnv* env) {
206 int insn = *(int*)start;
207 int opcode = Assembler::opcode(insn);
208 int special;
209 const char *fmt;
211 if (insn == 0)
212 {
213 PRINT_NOP();
214 return start+4;
215 }
217 switch(opcode) {
218 case Assembler::special_op:
219 special = Assembler::special(insn);
220 switch(special) {
221 case Assembler::sll_op:
222 case Assembler::srl_op:
223 case Assembler::sra_op:
224 case Assembler::dsll_op:
225 case Assembler::dsrl_op:
226 case Assembler::dsra_op:
227 case Assembler::dsll32_op:
228 case Assembler::dsrl32_op:
229 case Assembler::dsra32_op:
230 PRINT_ORRS(Assembler::special_name[special]);
231 break;
233 case Assembler::sllv_op:
234 case Assembler::srlv_op:
235 case Assembler::srav_op:
236 case Assembler::dsllv_op:
237 case Assembler::dsrlv_op:
238 case Assembler::dsrav_op:
239 PRINT_ORRR_2(Assembler::special_name[special]);
240 break;
242 case Assembler::jr_op:
243 case Assembler::jalr_op:
244 case Assembler::mthi_op:
245 case Assembler::mtlo_op:
246 PRINT_ORS(Assembler::special_name[special]);
247 break;
249 case Assembler::syscall_op:
250 case Assembler::break_op:
251 env->print("%s 0x%x\n", Assembler::special_name[special], bitfield(insn, 6, 20)>>10);
252 break;
254 case Assembler::sync_op:
255 env->print("sync\n");
256 break;
258 case Assembler::mfhi_op:
259 case Assembler::mflo_op:
260 PRINT_ORD(Assembler::special_name[special]);
261 break;
263 case Assembler::mult_op:
264 case Assembler::multu_op:
265 case Assembler::div_op:
266 case Assembler::divu_op:
267 case Assembler::dmult_op:
268 case Assembler::dmultu_op:
269 case Assembler::ddiv_op:
270 case Assembler::ddivu_op:
271 PRINT_ORR(Assembler::special_name[special]);
272 break;
274 case Assembler::add_op:
275 case Assembler::addu_op:
276 case Assembler::sub_op:
277 case Assembler::subu_op:
278 case Assembler::and_op:
279 case Assembler::or_op:
280 case Assembler::xor_op:
281 case Assembler::nor_op:
282 case Assembler::slt_op:
283 case Assembler::sltu_op:
284 case Assembler::movz_op:
285 case Assembler::movn_op:
286 case Assembler::dadd_op:
287 case Assembler::daddu_op:
288 case Assembler::dsub_op:
289 case Assembler::dsubu_op:
290 PRINT_ORRR(Assembler::special_name[special]);
291 break;
293 case Assembler::tge_op:
294 case Assembler::tgeu_op:
295 case Assembler::tlt_op:
296 case Assembler::tltu_op:
297 case Assembler::teq_op:
298 case Assembler::tne_op:
299 env->print("%s 0x%x, %s, %s\n", Assembler::special_name[special], bitfield(insn, 6, 10),
300 as_Register(Assembler::rs(insn))->name(),
301 as_Register(Assembler::rt(insn))->name() );
302 break;
304 default:
305 //Unimplemented();
306 env->print("0x%x\n", insn);
307 }
308 break;
310 case Assembler::regimm_op:
311 special = Assembler::rt(insn);
313 switch(special) {
314 case Assembler::bltz_op:
315 case Assembler::bgez_op:
316 case Assembler::bltzl_op:
317 case Assembler::bgezl_op:
318 case Assembler::bltzal_op:
319 case Assembler::bgezal_op:
320 case Assembler::bltzall_op:
321 case Assembler::bgezall_op:
322 env->print("[%lx]%s %s, ", *(int *)start, Assembler::regimm_name[special], as_Register(Assembler::rs(insn))->name());
323 env->print_label( (intptr_t)start + 4 + 4 * (short)Assembler::low16(insn) );
324 env->print("\n");
325 break;
327 case Assembler::tgei_op:
328 case Assembler::tgeiu_op:
329 case Assembler::tlti_op:
330 case Assembler::tltiu_op:
331 case Assembler::teqi_op:
332 case Assembler::tnei_op:
333 env->print("%s %s, %d\n", Assembler::regimm_name[special],
334 as_Register(Assembler::rs(insn))->name(),
335 (short)Assembler::low16(insn));
336 break;
338 default:
339 //Unimplemented();
340 env->print("0x%x\n", insn);
341 }
342 break;
344 case Assembler::j_op:
345 case Assembler::jal_op:
346 PRINT_J(Assembler::ops_name[opcode]);
347 break;
349 case Assembler::beq_op:
350 case Assembler::bne_op:
351 case Assembler::blez_op:
352 case Assembler::bgtz_op:
353 PRINT_ORRL(Assembler::ops_name[opcode]);
354 break;
356 case Assembler::addi_op:
357 case Assembler::addiu_op:
358 case Assembler::slti_op:
359 case Assembler::sltiu_op:
360 case Assembler::ori_op:
361 case Assembler::andi_op:
362 case Assembler::xori_op:
363 case Assembler::daddi_op:
364 case Assembler::daddiu_op:
365 PRINT_ORRI(Assembler::ops_name[opcode]);
366 break;
368 case Assembler::lui_op:
369 env->print("lui %s, 0x%x", as_Register(Assembler::rt(insn))->name(), (short)Assembler::low16(insn) ); \
370 break;
372 case Assembler::cop1_op:
373 special = Assembler::rs(insn);
374 switch(special) {
375 case Assembler::mf_op:
376 PRINT_ORR_2("mfc1");
377 break;
378 case Assembler::mt_op:
379 PRINT_ORR_2("mtc1");
380 break;
381 case Assembler::cf_op:
382 PRINT_ORR_2("cfc1");
383 break;
384 case Assembler::ct_op:
385 PRINT_ORR_2("ctc1");
386 break;
387 case Assembler::dmf_op:
388 PRINT_ORR_2("dmfc1");
389 break;
390 case Assembler::dmt_op:
391 PRINT_ORR_2("dmtc1");
392 break;
394 case Assembler::bc_op:
395 special = Assembler::rt(insn);
396 switch(special) {
397 case Assembler::bcf_op:
398 env->print("bc1f ");
399 env->print_label( (intptr_t)start + 4 + (short)Assembler::low16(insn) );
400 env->print("\n");
401 break;
402 case Assembler::bcfl_op:
403 env->print("bc1fl ");
404 env->print_label( (intptr_t)start + 4 + (short)Assembler::low16(insn) );
405 env->print("\n");
406 break;
407 case Assembler::bct_op:
408 env->print("bc1t ");
409 env->print_label( (intptr_t)start + 4 + (short)Assembler::low16(insn) );
410 env->print("\n");
411 break;
412 case Assembler::bctl_op:
413 env->print("bc1tl ");
414 env->print_label( (intptr_t)start + 4 + (short)Assembler::low16(insn) );
415 env->print("\n");
416 break;
417 default:
418 //Unimplemented();
419 env->print("0x%x\n", insn);
420 }
421 break;
422 case Assembler::single_fmt:
423 case Assembler::double_fmt:
424 case Assembler::word_fmt:
425 case Assembler::long_fmt:
426 fmt = fmt_str(special);
427 special = Assembler::special(insn);
428 switch(special) {
429 case Assembler::fadd_op:
430 case Assembler::fsub_op:
431 case Assembler::fmul_op:
432 case Assembler::fdiv_op:
433 case Assembler::fsqrt_op:
434 case Assembler::fabs_op:
435 case Assembler::fmov_op:
436 case Assembler::fneg_op:
437 case Assembler::froundl_op:
438 case Assembler::ftruncl_op:
439 case Assembler::fceill_op:
440 case Assembler::ffloorl_op:
441 case Assembler::froundw_op:
442 case Assembler::ftruncw_op:
443 case Assembler::fceilw_op:
444 case Assembler::ffloorw_op:
445 PRINT_FLOAT(Assembler::float_name[special]);
446 break;
448 case Assembler::fcvts_op:
449 PRINT_CVT("cvt.s");
450 break;
451 case Assembler::fcvtd_op:
452 PRINT_CVT("cvt.d");
453 break;
454 case Assembler::fcvtw_op:
455 PRINT_CVT("cvt.w");
456 break;
457 case Assembler::fcvtl_op:
458 PRINT_CVT("cvt.l");
459 break;
460 default:
461 //tty->print_cr("0x%x(%x)", insn, opcode);
462 //Unimplemented();
463 env->print("0x%x\n", insn);
464 }
465 }
466 break;
468 case Assembler::beql_op:
469 case Assembler::bnel_op:
470 case Assembler::blezl_op:
471 case Assembler::bgtzl_op:
472 PRINT_ORRL(Assembler::ops_name[opcode]);
473 break;
475 case Assembler::ldl_op:
476 case Assembler::ldr_op:
477 case Assembler::lb_op:
478 case Assembler::lh_op:
479 case Assembler::lwl_op:
480 case Assembler::lw_op:
481 case Assembler::lbu_op:
482 case Assembler::lhu_op:
483 case Assembler::lwr_op:
484 case Assembler::lwu_op:
485 case Assembler::sb_op:
486 case Assembler::sh_op:
487 case Assembler::swl_op:
488 case Assembler::sw_op:
489 case Assembler::sdl_op:
490 case Assembler::sdr_op:
491 case Assembler::swr_op:
492 case Assembler::ll_op:
493 case Assembler::lld_op:
494 case Assembler::ld_op:
495 case Assembler::sc_op:
496 case Assembler::scd_op:
497 case Assembler::sd_op:
498 PRINT_OROB(Assembler::ops_name[opcode]);
499 break;
500 case Assembler::sdc1_op:
501 case Assembler::ldc1_op:
502 case Assembler::lwc1_op:
503 case Assembler::swc1_op:
504 PRINT_OFOB(Assembler::ops_name[opcode]);
505 break;
507 default:
508 //tty->print_cr("0x%x(%x)", insn, opcode);
509 //Unimplemented();
510 env->print("0x%x\n", insn);
511 }
513 return start+4;
514 }
516 /*
517 void Disassembler::decode(address start, address end, outputStream* st, CodeComments c) {
518 if (!load_library()) return;
519 decode_env env(CodeCache::find_blob_unsafe(start), st, c);
520 env.decode_instructions(start, end);
521 }*/
523 void Disassembler::decode(CodeBlob* cb, outputStream* st) {
524 #ifndef CORE
525 st = st ? st : tty;
526 st->print_cr("Decoding CodeBlob " INTPTR_FORMAT, cb);
527 decode(cb->content_begin(), cb->content_end(), st);
528 #endif
529 }
532 void Disassembler::decode(u_char* begin, u_char* end, outputStream* st) {
533 st = st ? st : tty;
535 const int show_bytes = false; // for disassembler debugging
537 mips32_env env(NULL, st);
538 unsigned char* p = (unsigned char*) begin;
539 CodeBlob* cb = CodeCache::find_blob_unsafe(begin);
540 while (p < (unsigned char*) end) {
541 if (cb != NULL) {
542 cb->print_block_comment(st, (unsigned char*)(p - cb->content_begin()));
543 }
546 unsigned char* p0 = p;
547 st->print(" "INTPTR_FORMAT ": ", p);
548 p = decode_instruction(p, &env);
549 if (show_bytes) {
550 st->print("\t\t\t");
551 while (p0 < p) st->print("%x ", *p0++);
552 }
553 st->cr();
554 }
555 }
558 void Disassembler::decode(nmethod* nm, outputStream* st) {
559 #ifndef CORE
560 st = st ? st : tty;
562 st->print_cr("Decoding compiled method " INTPTR_FORMAT ":", nm);
563 st->print("Code:");
564 st->cr();
566 mips32_env env(nm, st);
567 #ifdef COMPILER1
568 unsigned char* p = nm->code_begin();
569 #else
570 unsigned char* p = nm->content_begin();
571 #endif
572 unsigned char* end = nm->content_end();
573 while (p < end) {
574 if (p == nm->entry_point()) st->print_cr("[Entry Point]");
575 if (p == nm->verified_entry_point()) st->print_cr("[Verified Entry Point]");
576 if (p == nm->exception_begin()) st->print_cr("[Exception Handler]");
577 if (p == nm->stub_begin()) st->print_cr("[Stub Code]");
578 if (p == nm->consts_begin()) st->print_cr("[Constants]");
579 nm->print_block_comment(st, (unsigned char*)(p - nm->content_begin()));
580 unsigned char* p0 = p;
581 st->print(" " INTPTR_FORMAT ": ", p);
582 p = decode_instruction(p, &env);
583 nm->print_code_comment_on(st, 40, p0, p);
584 st->cr();
585 // Output pc bucket ticks if we have any
586 address bucket_pc = FlatProfiler::bucket_start_for(p);
587 if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p) {
588 int bucket_count = FlatProfiler::bucket_count_for(bucket_pc);
589 tty->print_cr("[%d]", bucket_count);
590 }
591 }
592 #endif
593 }
595 #endif // PRODUCT