summaryrefslogtreecommitdiff
path: root/deps/v8/src/diagnostics/ppc/disasm-ppc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/diagnostics/ppc/disasm-ppc.cc')
-rw-r--r--deps/v8/src/diagnostics/ppc/disasm-ppc.cc146
1 files changed, 141 insertions, 5 deletions
diff --git a/deps/v8/src/diagnostics/ppc/disasm-ppc.cc b/deps/v8/src/diagnostics/ppc/disasm-ppc.cc
index 03868d5357..012e2ae400 100644
--- a/deps/v8/src/diagnostics/ppc/disasm-ppc.cc
+++ b/deps/v8/src/diagnostics/ppc/disasm-ppc.cc
@@ -61,6 +61,16 @@ class Decoder {
// Returns the length of the disassembled machine instruction in bytes.
int InstructionDecode(byte* instruction);
+ // Prefixed instructions.
+ enum PrefixType { not_prefixed, is_prefixed };
+ // static is used to retain values even with new instances.
+ static PrefixType PrefixStatus;
+ static uint64_t PrefixValue;
+ uint64_t GetPrefixValue();
+ void SetAsPrefixed(uint64_t v);
+ void ResetPrefix();
+ bool IsPrefixed();
+
private:
// Bottleneck functions to print into the out_buffer.
void PrintChar(const char ch);
@@ -82,6 +92,7 @@ class Decoder {
void Unknown(Instruction* instr);
void UnknownFormat(Instruction* instr, const char* opcname);
+ void DecodeExtP(Instruction* instr);
void DecodeExt0(Instruction* instr);
void DecodeExt1(Instruction* instr);
void DecodeExt2(Instruction* instr);
@@ -95,6 +106,25 @@ class Decoder {
int out_buffer_pos_;
};
+// Define Prefix functions and values.
+// static
+Decoder::PrefixType Decoder::PrefixStatus = not_prefixed;
+uint64_t Decoder::PrefixValue = 0;
+
+uint64_t Decoder::GetPrefixValue() { return PrefixValue; }
+
+void Decoder::SetAsPrefixed(uint64_t v) {
+ PrefixStatus = is_prefixed;
+ PrefixValue = v;
+}
+
+void Decoder::ResetPrefix() {
+ PrefixStatus = not_prefixed;
+ PrefixValue = 0;
+}
+
+bool Decoder::IsPrefixed() { return PrefixStatus == is_prefixed; }
+
// Support for assertions in the Decoder formatting functions.
#define STRING_STARTS_WITH(string, compare_string) \
(strncmp(string, compare_string, strlen(compare_string)) == 0)
@@ -255,9 +285,16 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
return FormatVectorRegister(instr, format);
}
case 'i': { // int16
- int32_t value = (instr->Bits(15, 0) << 16) >> 16;
+ int64_t value;
+ uint32_t imm_value = instr->Bits(15, 0);
+ if (IsPrefixed()) {
+ uint64_t prefix_value = GetPrefixValue();
+ value = SIGN_EXT_IMM34((prefix_value << 16) | imm_value);
+ } else {
+ value = (static_cast<int64_t>(imm_value) << 48) >> 48;
+ }
out_buffer_pos_ +=
- base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ base::SNPrintF(out_buffer_ + out_buffer_pos_, "%ld", value);
return 5;
}
case 'I': { // IMM8
@@ -425,6 +462,83 @@ void Decoder::UnknownFormat(Instruction* instr, const char* name) {
Format(instr, buffer);
}
+void Decoder::DecodeExtP(Instruction* instr) {
+ switch (EXTP | (instr->BitField(25, 25))) {
+ case PLOAD_STORE_8LS:
+ case PLOAD_STORE_MLS: {
+ // TODO(miladfarca): Decode the R bit.
+ DCHECK_NE(instr->Bit(20), 1);
+ // Read prefix.
+ SetAsPrefixed(instr->Bits(17, 0));
+ // Read suffix (next instruction).
+ Instruction* next_instr =
+ bit_cast<Instruction*>(bit_cast<intptr_t>(instr) + kInstrSize);
+ switch (next_instr->OpcodeBase()) {
+ // Prefixed ADDI.
+ case (ADDI): {
+ if (next_instr->RAValue() == 0) {
+ // This is load immediate prefixed.
+ Format(instr, "pli");
+ Format(next_instr, " 'rt, ");
+ } else {
+ Format(instr, "paddi");
+ Format(next_instr, " 'rt, 'ra, ");
+ }
+ Format(next_instr, "'int34");
+ break;
+ }
+ // Prefixed LBZ.
+ case LBZ: {
+ Format(next_instr, "plbz 'rt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LHZ.
+ case LHZ: {
+ Format(next_instr, "plhz 'rt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LHA.
+ case LHA: {
+ Format(next_instr, "plha 'rt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LWZ.
+ case LWZ: {
+ Format(next_instr, "plwz 'rt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LWA.
+ case PPLWA: {
+ Format(next_instr, "plwa 'rt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LD.
+ case PPLD: {
+ Format(next_instr, "pld 'rt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LFS.
+ case LFS: {
+ Format(next_instr, "plfs 'Dt, 'int34('ra)");
+ break;
+ }
+ // Prefixed LFD.
+ case LFD: {
+ Format(next_instr, "plfd 'Dt, 'int34('ra)");
+ break;
+ }
+ default: {
+ Unknown(instr);
+ }
+ }
+ break;
+ }
+ default: {
+ Unknown(instr);
+ }
+ }
+}
+
void Decoder::DecodeExt0(Instruction* instr) {
// Some encodings have integers hard coded in the middle, handle those first.
switch (EXT0 | (instr->BitField(20, 16)) | (instr->BitField(10, 0))) {
@@ -1432,9 +1546,21 @@ void Decoder::DecodeExt6(Instruction* instr) {
// Disassemble the instruction at *instr_ptr into the output buffer.
int Decoder::InstructionDecode(byte* instr_ptr) {
Instruction* instr = Instruction::At(instr_ptr);
+
+ uint32_t opcode = instr->OpcodeValue() << 26;
// Print raw instruction bytes.
- out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
- "%08x ", instr->InstructionBits());
+ if (opcode != EXTP) {
+ out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_,
+ "%08x ", instr->InstructionBits());
+ } else {
+ // Prefixed instructions have a 4-byte prefix and a 4-byte suffix. Print
+ // both on the same line.
+ Instruction* next_instr =
+ bit_cast<Instruction*>(bit_cast<intptr_t>(instr) + kInstrSize);
+ out_buffer_pos_ +=
+ base::SNPrintF(out_buffer_ + out_buffer_pos_, "%08x|%08x ",
+ instr->InstructionBits(), next_instr->InstructionBits());
+ }
if (ABI_USES_FUNCTION_DESCRIPTORS && instr->InstructionBits() == 0) {
// The first field will be identified as a jump table entry. We
@@ -1443,7 +1569,6 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
return kInstrSize;
}
- uint32_t opcode = instr->OpcodeValue() << 26;
switch (opcode) {
case TWI: {
PrintSoftwareInterrupt(instr->SvcValue());
@@ -1563,6 +1688,10 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
Format(instr, "b'l'a 'target26");
break;
}
+ case EXTP: {
+ DecodeExtP(instr);
+ break;
+ }
case EXT0: {
DecodeExt0(instr);
break;
@@ -1753,6 +1882,13 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
}
}
+ if (IsPrefixed()) {
+ // The next instruction (suffix) should have already been decoded as part of
+ // prefix decoding.
+ ResetPrefix();
+ return 2 * kInstrSize;
+ }
+
return kInstrSize;
}
} // namespace internal