src/cpu/mips/vm/disassembler_mips.cpp

Tue, 26 Jul 2016 11:15:09 +0800

author
fujie
date
Tue, 26 Jul 2016 11:15:09 +0800
changeset 38
f0e26f502a50
parent 11
0691182d36ec
child 41
d885f8d65c58
permissions
-rw-r--r--

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

mercurial