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