1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // A Disassembler object is used to disassemble a block of code instruction by
6 // instruction. The default implementation of the NameConverter object can be
7 // overriden to modify register names or to do symbol lookup on addresses.
9 // The example below will disassemble a block of code and print it to stdout.
11 // NameConverter converter;
12 // Disassembler d(converter);
13 // for (byte* pc = begin; pc < end;) {
14 // v8::internal::EmbeddedVector<char, 256> buffer;
15 // byte* prev_pc = pc;
16 // pc += d.InstructionDecode(buffer, pc);
17 // printf("%p %08x %s\n",
18 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
21 // The Disassembler class also has a convenience method to disassemble a block
22 // of code into a FILE*, meaning that the above functionality could also be
23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
33 #if V8_TARGET_ARCH_PPC
35 #include "src/base/platform/platform.h"
36 #include "src/disasm.h"
37 #include "src/macro-assembler.h"
38 #include "src/ppc/constants-ppc.h"
45 //------------------------------------------------------------------------------
47 // Decoder decodes and disassembles instructions into an output buffer.
48 // It uses the converter to convert register names and call destinations into
49 // more informative description.
52 Decoder(const disasm::NameConverter& converter, Vector<char> out_buffer)
53 : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) {
54 out_buffer_[out_buffer_pos_] = '\0';
59 // Writes one disassembled instruction into 'buffer' (0-terminated).
60 // Returns the length of the disassembled machine instruction in bytes.
61 int InstructionDecode(byte* instruction);
64 // Bottleneck functions to print into the out_buffer.
65 void PrintChar(const char ch);
66 void Print(const char* str);
68 // Printing of common values.
69 void PrintRegister(int reg);
70 void PrintDRegister(int reg);
71 int FormatFPRegister(Instruction* instr, const char* format);
72 void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
74 // Handle formatting of instructions and their options.
75 int FormatRegister(Instruction* instr, const char* option);
76 int FormatOption(Instruction* instr, const char* option);
77 void Format(Instruction* instr, const char* format);
78 void Unknown(Instruction* instr);
79 void UnknownFormat(Instruction* instr, const char* opcname);
81 void DecodeExt1(Instruction* instr);
82 void DecodeExt2(Instruction* instr);
83 void DecodeExt4(Instruction* instr);
84 void DecodeExt5(Instruction* instr);
86 const disasm::NameConverter& converter_;
87 Vector<char> out_buffer_;
90 DISALLOW_COPY_AND_ASSIGN(Decoder);
94 // Support for assertions in the Decoder formatting functions.
95 #define STRING_STARTS_WITH(string, compare_string) \
96 (strncmp(string, compare_string, strlen(compare_string)) == 0)
99 // Append the ch to the output buffer.
100 void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
103 // Append the str to the output buffer.
104 void Decoder::Print(const char* str) {
106 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
110 out_buffer_[out_buffer_pos_] = 0;
114 // Print the register name according to the active name converter.
115 void Decoder::PrintRegister(int reg) {
116 Print(converter_.NameOfCPURegister(reg));
120 // Print the double FP register name according to the active name converter.
121 void Decoder::PrintDRegister(int reg) { Print(FPRegisters::Name(reg)); }
124 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
125 // the FormatOption method.
126 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
128 case kCallRtRedirected:
129 Print("call rt redirected");
135 if (svc >= kStopCode) {
136 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x",
137 svc & kStopCodeMask, svc & kStopCodeMask);
139 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc);
146 // Handle all register based formatting in this function to reduce the
147 // complexity of FormatOption.
148 int Decoder::FormatRegister(Instruction* instr, const char* format) {
149 DCHECK(format[0] == 'r');
151 if ((format[1] == 't') || (format[1] == 's')) { // 'rt & 'rs register
152 int reg = instr->RTValue();
155 } else if (format[1] == 'a') { // 'ra: RA register
156 int reg = instr->RAValue();
159 } else if (format[1] == 'b') { // 'rb: RB register
160 int reg = instr->RBValue();
170 // Handle all FP register based formatting in this function to reduce the
171 // complexity of FormatOption.
172 int Decoder::FormatFPRegister(Instruction* instr, const char* format) {
173 DCHECK(format[0] == 'D');
177 if (format[1] == 't') {
178 reg = instr->RTValue();
179 } else if (format[1] == 'a') {
180 reg = instr->RAValue();
181 } else if (format[1] == 'b') {
182 reg = instr->RBValue();
183 } else if (format[1] == 'c') {
184 reg = instr->RCValue();
195 // FormatOption takes a formatting string and interprets it based on
196 // the current instructions. The format string points to the first
197 // character of the option string (the option escape has already been
198 // consumed by the caller.) FormatOption returns the number of
199 // characters that were consumed from the formatting string.
200 int Decoder::FormatOption(Instruction* instr, const char* format) {
203 if (instr->Bit(10) == 1) {
209 if (instr->Bit(0) == 1) {
212 Print(" "); // ensure consistent spacing
217 return FormatRegister(instr, format);
220 return FormatFPRegister(instr, format);
223 int32_t value = (instr->Bits(15, 0) << 16) >> 16;
224 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
227 case 'u': { // uint16
228 int32_t value = instr->Bits(15, 0);
229 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
234 if (instr->Bit(0) == 1) {
240 // Absolute Address Bit 1
241 if (instr->Bit(1) == 1) {
246 case 't': { // 'target: target of branch instructions
247 // target26 or target16
248 DCHECK(STRING_STARTS_WITH(format, "target"));
249 if ((format[6] == '2') && (format[7] == '6')) {
250 int off = ((instr->Bits(25, 2)) << 8) >> 6;
251 out_buffer_pos_ += SNPrintF(
252 out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
253 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
255 } else if ((format[6] == '1') && (format[7] == '6')) {
256 int off = ((instr->Bits(15, 2)) << 18) >> 16;
257 out_buffer_pos_ += SNPrintF(
258 out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
259 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
263 DCHECK(format[1] == 'h');
265 int32_t opcode = instr->OpcodeValue() << 26;
266 int32_t sh = instr->Bits(15, 11);
267 if (opcode == EXT5 ||
268 (opcode == EXT2 && instr->Bits(10, 2) << 2 == SRADIX)) {
269 // SH Bits 1 and 15-11 (split field)
270 value = (sh | (instr->Bit(1) << 5));
273 value = (sh << 26) >> 26;
275 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
280 if (format[1] == 'e') {
281 if (instr->OpcodeValue() << 26 != EXT5) {
283 value = (instr->Bits(10, 6) << 26) >> 26;
285 // ME Bits 5 and 10-6 (split field)
286 value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
288 } else if (format[1] == 'b') {
289 if (instr->OpcodeValue() << 26 != EXT5) {
291 value = (instr->Bits(5, 1) << 26) >> 26;
293 // MB Bits 5 and 10-6 (split field)
294 value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
297 UNREACHABLE(); // bad format
299 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
303 #if V8_TARGET_ARCH_PPC64
304 case 'd': { // ds value for offset
305 int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
306 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
321 // Format takes a formatting string for a whole instruction and prints it into
322 // the output buffer. All escaped options are handed to FormatOption to be
324 void Decoder::Format(Instruction* instr, const char* format) {
325 char cur = *format++;
326 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
327 if (cur == '\'') { // Single quote is used as the formatting escape.
328 format += FormatOption(instr, format);
330 out_buffer_[out_buffer_pos_++] = cur;
334 out_buffer_[out_buffer_pos_] = '\0';
338 // The disassembler may end up decoding data inlined in the code. We do not want
339 // it to crash if the data does not ressemble any known instruction.
340 #define VERIFY(condition) \
341 if (!(condition)) { \
347 // For currently unimplemented decodings the disassembler calls Unknown(instr)
348 // which will just print "unknown" of the instruction bits.
349 void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); }
352 // For currently unimplemented decodings the disassembler calls
353 // UnknownFormat(instr) which will just print opcode name of the
355 void Decoder::UnknownFormat(Instruction* instr, const char* name) {
357 snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name);
358 Format(instr, buffer);
362 void Decoder::DecodeExt1(Instruction* instr) {
363 switch (instr->Bits(10, 1) << 1) {
365 UnknownFormat(instr, "mcrf"); // not used by V8
369 switch (instr->Bits(25, 21) << 21) {
371 UnknownFormat(instr, "bclrx-dcbnzf");
375 UnknownFormat(instr, "bclrx-dcbezf");
379 UnknownFormat(instr, "bclrx-bf");
383 UnknownFormat(instr, "bclrx-dcbbzt");
387 UnknownFormat(instr, "bclrx-dcbnezt");
391 UnknownFormat(instr, "bclrx-bt");
395 UnknownFormat(instr, "bclrx-dcbnz");
399 UnknownFormat(instr, "bclrx-dcbez"); // not used by V8
403 if (instr->Bit(0) == 1) {
404 Format(instr, "blrl");
406 Format(instr, "blr");
414 switch (instr->Bits(25, 21) << 21) {
416 UnknownFormat(instr, "bcctrx-dcbnzf");
420 UnknownFormat(instr, "bcctrx-dcbezf");
424 UnknownFormat(instr, "bcctrx-bf");
428 UnknownFormat(instr, "bcctrx-dcbnzt");
432 UnknownFormat(instr, "bcctrx-dcbezf");
436 UnknownFormat(instr, "bcctrx-bt");
440 UnknownFormat(instr, "bcctrx-dcbnz");
444 UnknownFormat(instr, "bcctrx-dcbez");
448 if (instr->Bit(0) == 1) {
449 Format(instr, "bctrl");
451 Format(instr, "bctr");
455 default: { UNREACHABLE(); }
460 Format(instr, "crnor (stuff)");
464 Format(instr, "rfi (stuff)");
468 Format(instr, "crandc (stuff)");
472 Format(instr, "isync (stuff)");
476 Format(instr, "crxor (stuff)");
480 UnknownFormat(instr, "crnand");
484 UnknownFormat(instr, "crand");
488 UnknownFormat(instr, "creqv");
492 UnknownFormat(instr, "crorc");
496 UnknownFormat(instr, "cror");
500 Unknown(instr); // not used by V8
506 void Decoder::DecodeExt2(Instruction* instr) {
507 // Some encodings are 10-1 bits, handle those first
508 switch (instr->Bits(10, 1) << 1) {
510 Format(instr, "srw'. 'ra, 'rs, 'rb");
513 #if V8_TARGET_ARCH_PPC64
515 Format(instr, "srd'. 'ra, 'rs, 'rb");
520 Format(instr, "sraw'. 'ra, 'rs, 'rb");
523 #if V8_TARGET_ARCH_PPC64
525 Format(instr, "srad'. 'ra, 'rs, 'rb");
530 Format(instr, "srawi'. 'ra,'rs,'sh");
534 Format(instr, "extsh'. 'ra, 'rs");
537 #if V8_TARGET_ARCH_PPC64
539 Format(instr, "extsw'. 'ra, 'rs");
544 Format(instr, "extsb'. 'ra, 'rs");
548 Format(instr, "lfsx 'rt, 'ra, 'rb");
552 Format(instr, "lfsux 'rt, 'ra, 'rb");
556 Format(instr, "lfdx 'rt, 'ra, 'rb");
560 Format(instr, "lfdux 'rt, 'ra, 'rb");
564 Format(instr, "stfsx 'rs, 'ra, 'rb");
568 Format(instr, "stfsux 'rs, 'ra, 'rb");
572 Format(instr, "stfdx 'rs, 'ra, 'rb");
576 Format(instr, "stfdux 'rs, 'ra, 'rb");
581 switch (instr->Bits(10, 2) << 2) {
583 Format(instr, "sradi'. 'ra,'rs,'sh");
588 // ?? are all of these xo_form?
589 switch (instr->Bits(9, 1) << 1) {
591 #if V8_TARGET_ARCH_PPC64
592 if (instr->Bit(21)) {
594 Format(instr, "cmp 'ra, 'rb");
595 #if V8_TARGET_ARCH_PPC64
597 Format(instr, "cmpw 'ra, 'rb");
603 Format(instr, "slw'. 'ra, 'rs, 'rb");
606 #if V8_TARGET_ARCH_PPC64
608 Format(instr, "sld'. 'ra, 'rs, 'rb");
613 Format(instr, "subfc'. 'rt, 'ra, 'rb");
617 Format(instr, "addc'. 'rt, 'ra, 'rb");
621 Format(instr, "cntlzw'. 'ra, 'rs");
624 #if V8_TARGET_ARCH_PPC64
626 Format(instr, "cntlzd'. 'ra, 'rs");
631 Format(instr, "and'. 'ra, 'rs, 'rb");
635 Format(instr, "andc'. 'ra, 'rs, 'rb");
639 #if V8_TARGET_ARCH_PPC64
640 if (instr->Bit(21)) {
642 Format(instr, "cmpl 'ra, 'rb");
643 #if V8_TARGET_ARCH_PPC64
645 Format(instr, "cmplw 'ra, 'rb");
651 Format(instr, "neg'. 'rt, 'ra");
655 Format(instr, "nor'. 'rt, 'ra, 'rb");
659 Format(instr, "subf'. 'rt, 'ra, 'rb");
663 Format(instr, "mulhw'o'. 'rt, 'ra, 'rb");
667 Format(instr, "addze'. 'rt, 'ra");
671 Format(instr, "mullw'o'. 'rt, 'ra, 'rb");
674 #if V8_TARGET_ARCH_PPC64
676 Format(instr, "mulld'o'. 'rt, 'ra, 'rb");
681 Format(instr, "divw'o'. 'rt, 'ra, 'rb");
685 Format(instr, "divwu'o'. 'rt, 'ra, 'rb");
688 #if V8_TARGET_ARCH_PPC64
690 Format(instr, "divd'o'. 'rt, 'ra, 'rb");
695 Format(instr, "add'o 'rt, 'ra, 'rb");
699 Format(instr, "xor'. 'ra, 'rs, 'rb");
703 if (instr->RTValue() == instr->RBValue()) {
704 Format(instr, "mr 'ra, 'rb");
706 Format(instr, "or 'ra, 'rs, 'rb");
711 int spr = instr->Bits(20, 11);
713 Format(instr, "mflr 'rt");
715 Format(instr, "mfspr 'rt ??");
720 int spr = instr->Bits(20, 11);
722 Format(instr, "mtlr 'rt");
723 } else if (288 == spr) {
724 Format(instr, "mtctr 'rt");
726 Format(instr, "mtspr 'rt ??");
731 Format(instr, "mfcr 'rt");
735 Format(instr, "stwx 'rs, 'ra, 'rb");
739 Format(instr, "stwux 'rs, 'ra, 'rb");
743 Format(instr, "stbx 'rs, 'ra, 'rb");
747 Format(instr, "stbux 'rs, 'ra, 'rb");
751 Format(instr, "sthx 'rs, 'ra, 'rb");
755 Format(instr, "sthux 'rs, 'ra, 'rb");
759 Format(instr, "lwzx 'rt, 'ra, 'rb");
763 Format(instr, "lwzux 'rt, 'ra, 'rb");
767 Format(instr, "lwax 'rt, 'ra, 'rb");
771 Format(instr, "lbzx 'rt, 'ra, 'rb");
775 Format(instr, "lbzux 'rt, 'ra, 'rb");
779 Format(instr, "lhzx 'rt, 'ra, 'rb");
783 Format(instr, "lhzux 'rt, 'ra, 'rb");
787 Format(instr, "lhax 'rt, 'ra, 'rb");
790 #if V8_TARGET_ARCH_PPC64
792 Format(instr, "ldx 'rt, 'ra, 'rb");
796 Format(instr, "ldux 'rt, 'ra, 'rb");
800 Format(instr, "stdx 'rt, 'ra, 'rb");
804 Format(instr, "stdux 'rt, 'ra, 'rb");
808 Format(instr, "mffprd 'ra, 'Dt");
812 Format(instr, "mffprwz 'ra, 'Dt");
816 Format(instr, "mtfprd 'Dt, 'ra");
820 Format(instr, "mtfprwa 'Dt, 'ra");
824 Format(instr, "mtfprwz 'Dt, 'ra");
830 switch (instr->Bits(5, 1) << 1) {
832 Format(instr, "isel 'rt, 'ra, 'rb");
836 Unknown(instr); // not used by V8
842 void Decoder::DecodeExt4(Instruction* instr) {
843 switch (instr->Bits(5, 1) << 1) {
845 Format(instr, "fdiv'. 'Dt, 'Da, 'Db");
849 Format(instr, "fsub'. 'Dt, 'Da, 'Db");
853 Format(instr, "fadd'. 'Dt, 'Da, 'Db");
857 Format(instr, "fsqrt'. 'Dt, 'Db");
861 Format(instr, "fsel'. 'Dt, 'Da, 'Dc, 'Db");
865 Format(instr, "fmul'. 'Dt, 'Da, 'Dc");
869 Format(instr, "fmsub'. 'Dt, 'Da, 'Dc, 'Db");
873 Format(instr, "fmadd'. 'Dt, 'Da, 'Dc, 'Db");
878 switch (instr->Bits(10, 1) << 1) {
880 Format(instr, "fcmpu 'Da, 'Db");
884 Format(instr, "frsp'. 'Dt, 'Db");
888 Format(instr, "fcfid'. 'Dt, 'Db");
892 Format(instr, "fctid 'Dt, 'Db");
896 Format(instr, "fctidz 'Dt, 'Db");
900 Format(instr, "fctiw'. 'Dt, 'Db");
904 Format(instr, "fctiwz'. 'Dt, 'Db");
908 Format(instr, "fmr'. 'Dt, 'Db");
912 Format(instr, "mtfsfi'. ?,?");
916 Format(instr, "mffs'. 'Dt");
920 Format(instr, "mtfsf'. 'Db ?,?,?");
924 Format(instr, "fabs'. 'Dt, 'Db");
928 Format(instr, "frin. 'Dt, 'Db");
932 Format(instr, "friz. 'Dt, 'Db");
936 Format(instr, "frip. 'Dt, 'Db");
940 Format(instr, "frim. 'Dt, 'Db");
944 Format(instr, "fneg'. 'Dt, 'Db");
948 Unknown(instr); // not used by V8
954 void Decoder::DecodeExt5(Instruction* instr) {
955 switch (instr->Bits(4, 2) << 2) {
957 Format(instr, "rldicl'. 'ra, 'rs, 'sh, 'mb");
961 Format(instr, "rldicr'. 'ra, 'rs, 'sh, 'me");
965 Format(instr, "rldic'. 'ra, 'rs, 'sh, 'mb");
969 Format(instr, "rldimi'. 'ra, 'rs, 'sh, 'mb");
973 switch (instr->Bits(4, 1) << 1) {
975 Format(instr, "rldcl'. 'ra, 'rs, 'sb, 'mb");
979 Unknown(instr); // not used by V8
984 // Disassemble the instruction at *instr_ptr into the output buffer.
985 int Decoder::InstructionDecode(byte* instr_ptr) {
986 Instruction* instr = Instruction::At(instr_ptr);
987 // Print raw instruction bytes.
988 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ",
989 instr->InstructionBits());
991 #if ABI_USES_FUNCTION_DESCRIPTORS
992 // The first field will be identified as a jump table entry. We emit the rest
993 // of the structure as zero, so just skip past them.
994 if (instr->InstructionBits() == 0) {
995 Format(instr, "constant");
996 return Instruction::kInstrSize;
1000 switch (instr->OpcodeValue() << 26) {
1002 PrintSoftwareInterrupt(instr->SvcValue());
1006 UnknownFormat(instr, "mulli");
1010 Format(instr, "subfic 'rt, 'ra, 'int16");
1014 #if V8_TARGET_ARCH_PPC64
1015 if (instr->Bit(21)) {
1017 Format(instr, "cmpli 'ra, 'uint16");
1018 #if V8_TARGET_ARCH_PPC64
1020 Format(instr, "cmplwi 'ra, 'uint16");
1026 #if V8_TARGET_ARCH_PPC64
1027 if (instr->Bit(21)) {
1029 Format(instr, "cmpi 'ra, 'int16");
1030 #if V8_TARGET_ARCH_PPC64
1032 Format(instr, "cmpwi 'ra, 'int16");
1038 Format(instr, "addic 'rt, 'ra, 'int16");
1042 UnknownFormat(instr, "addicx");
1046 if (instr->RAValue() == 0) {
1047 // this is load immediate
1048 Format(instr, "li 'rt, 'int16");
1050 Format(instr, "addi 'rt, 'ra, 'int16");
1055 if (instr->RAValue() == 0) {
1056 Format(instr, "lis 'rt, 'int16");
1058 Format(instr, "addis 'rt, 'ra, 'int16");
1063 int bo = instr->Bits(25, 21) << 21;
1064 int bi = instr->Bits(20, 16);
1069 Format(instr, "beq'l'a 'target16");
1073 Format(instr, "bne'l'a 'target16");
1076 Format(instr, "bc'l'a 'target16");
1080 Format(instr, "bgt'l'a 'target16");
1084 Format(instr, "ble'l'a 'target16");
1087 Format(instr, "bc'l'a 'target16");
1091 Format(instr, "blt'l'a 'target16");
1095 Format(instr, "bge'l'a 'target16");
1098 Format(instr, "bc'l'a 'target16");
1101 Format(instr, "bc'l'a 'target16");
1107 UnknownFormat(instr, "sc");
1111 Format(instr, "b'l'a 'target26");
1119 Format(instr, "rlwimi'. 'ra, 'rs, 'sh, 'me, 'mb");
1123 Format(instr, "rlwinm'. 'ra, 'rs, 'sh, 'me, 'mb");
1127 Format(instr, "rlwnm'. 'ra, 'rs, 'rb, 'me, 'mb");
1131 Format(instr, "ori 'ra, 'rs, 'uint16");
1135 Format(instr, "oris 'ra, 'rs, 'uint16");
1139 Format(instr, "xori 'ra, 'rs, 'uint16");
1143 Format(instr, "xoris 'ra, 'rs, 'uint16");
1147 Format(instr, "andi. 'ra, 'rs, 'uint16");
1151 Format(instr, "andis. 'ra, 'rs, 'uint16");
1159 Format(instr, "lwz 'rt, 'int16('ra)");
1163 Format(instr, "lwzu 'rt, 'int16('ra)");
1167 Format(instr, "lbz 'rt, 'int16('ra)");
1171 Format(instr, "lbzu 'rt, 'int16('ra)");
1175 Format(instr, "stw 'rs, 'int16('ra)");
1179 Format(instr, "stwu 'rs, 'int16('ra)");
1183 Format(instr, "stb 'rs, 'int16('ra)");
1187 Format(instr, "stbu 'rs, 'int16('ra)");
1191 Format(instr, "lhz 'rt, 'int16('ra)");
1195 Format(instr, "lhzu 'rt, 'int16('ra)");
1199 Format(instr, "lha 'rt, 'int16('ra)");
1203 Format(instr, "lhau 'rt, 'int16('ra)");
1207 Format(instr, "sth 'rs, 'int16('ra)");
1211 Format(instr, "sthu 'rs, 'int16('ra)");
1215 UnknownFormat(instr, "lmw");
1219 UnknownFormat(instr, "stmw");
1223 Format(instr, "lfs 'Dt, 'int16('ra)");
1227 Format(instr, "lfsu 'Dt, 'int16('ra)");
1231 Format(instr, "lfd 'Dt, 'int16('ra)");
1235 Format(instr, "lfdu 'Dt, 'int16('ra)");
1239 Format(instr, "stfs 'Dt, 'int16('ra)");
1243 Format(instr, "stfsu 'Dt, 'int16('ra)");
1247 Format(instr, "stfd 'Dt, 'int16('ra)");
1251 Format(instr, "stfdu 'Dt, 'int16('ra)");
1263 #if V8_TARGET_ARCH_PPC64
1265 switch (instr->Bits(1, 0)) {
1267 Format(instr, "ld 'rt, 'd('ra)");
1270 Format(instr, "ldu 'rt, 'd('ra)");
1273 Format(instr, "lwa 'rt, 'd('ra)");
1278 case STD: { // could be STD or STDU
1279 if (instr->Bit(0) == 0) {
1280 Format(instr, "std 'rs, 'd('ra)");
1282 Format(instr, "stdu 'rs, 'd('ra)");
1293 return Instruction::kInstrSize;
1296 } // namespace v8::internal
1299 //------------------------------------------------------------------------------
1304 const char* NameConverter::NameOfAddress(byte* addr) const {
1305 v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1306 return tmp_buffer_.start();
1310 const char* NameConverter::NameOfConstant(byte* addr) const {
1311 return NameOfAddress(addr);
1315 const char* NameConverter::NameOfCPURegister(int reg) const {
1316 return v8::internal::Registers::Name(reg);
1319 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1320 UNREACHABLE(); // PPC does not have the concept of a byte register
1325 const char* NameConverter::NameOfXMMRegister(int reg) const {
1326 UNREACHABLE(); // PPC does not have any XMM registers
1330 const char* NameConverter::NameInCode(byte* addr) const {
1331 // The default name converter is called for unknown code. So we will not try
1332 // to access any memory.
1337 //------------------------------------------------------------------------------
1339 Disassembler::Disassembler(const NameConverter& converter)
1340 : converter_(converter) {}
1343 Disassembler::~Disassembler() {}
1346 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1347 byte* instruction) {
1348 v8::internal::Decoder d(converter_, buffer);
1349 return d.InstructionDecode(instruction);
1353 // The PPC assembler does not currently use constant pools.
1354 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1357 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1358 NameConverter converter;
1359 Disassembler d(converter);
1360 for (byte* pc = begin; pc < end;) {
1361 v8::internal::EmbeddedVector<char, 128> buffer;
1364 pc += d.InstructionDecode(buffer, pc);
1365 v8::internal::PrintF(f, "%p %08x %s\n", prev_pc,
1366 *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1371 } // namespace disasm
1373 #endif // V8_TARGET_ARCH_PPC