Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(494)

Unified Diff: src/s390/disasm-s390.cc

Issue 1725243004: S390: Initial impl of S390 asm, masm, code-stubs,... (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Updated BUILD.gn + cpu-s390.cc to addr @jochen's comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/s390/disasm-s390.cc
diff --git a/src/s390/disasm-s390.cc b/src/s390/disasm-s390.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5617fa07e13aa317557b913feeaf5934b6355267
--- /dev/null
+++ b/src/s390/disasm-s390.cc
@@ -0,0 +1,1396 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A Disassembler object is used to disassemble a block of code instruction by
+// instruction. The default implementation of the NameConverter object can be
+// overriden to modify register names or to do symbol lookup on addresses.
+//
+// The example below will disassemble a block of code and print it to stdout.
+//
+// NameConverter converter;
+// Disassembler d(converter);
+// for (byte* pc = begin; pc < end;) {
+// v8::internal::EmbeddedVector<char, 256> buffer;
+// byte* prev_pc = pc;
+// pc += d.InstructionDecode(buffer, pc);
+// printf("%p %08x %s\n",
+// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
+// }
+//
+// The Disassembler class also has a convenience method to disassemble a block
+// of code into a FILE*, meaning that the above functionality could also be
+// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#if V8_TARGET_ARCH_S390
+
+#include "src/base/platform/platform.h"
+#include "src/disasm.h"
+#include "src/macro-assembler.h"
+#include "src/s390/constants-s390.h"
+
+namespace v8 {
+namespace internal {
+
+//------------------------------------------------------------------------------
+
+// Decoder decodes and disassembles instructions into an output buffer.
+// It uses the converter to convert register names and call destinations into
+// more informative description.
+class Decoder {
+ public:
+ Decoder(const disasm::NameConverter& converter, Vector<char> out_buffer)
+ : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) {
+ out_buffer_[out_buffer_pos_] = '\0';
+ }
+
+ ~Decoder() {}
+
+ // Writes one disassembled instruction into 'buffer' (0-terminated).
+ // Returns the length of the disassembled machine instruction in bytes.
+ int InstructionDecode(byte* instruction);
+
+ private:
+ // Bottleneck functions to print into the out_buffer.
+ void PrintChar(const char ch);
+ void Print(const char* str);
+
+ // Printing of common values.
+ void PrintRegister(int reg);
+ void PrintDRegister(int reg);
+ void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
+
+ // Handle formatting of instructions and their options.
+ int FormatRegister(Instruction* instr, const char* option);
+ int FormatFloatingRegister(Instruction* instr, const char* option);
+ int FormatMask(Instruction* instr, const char* option);
+ int FormatDisplacement(Instruction* instr, const char* option);
+ int FormatImmediate(Instruction* instr, const char* option);
+ int FormatOption(Instruction* instr, const char* option);
+ void Format(Instruction* instr, const char* format);
+ void Unknown(Instruction* instr);
+ void UnknownFormat(Instruction* instr, const char* opcname);
+
+ bool DecodeTwoByte(Instruction* instr);
+ bool DecodeFourByte(Instruction* instr);
+ bool DecodeSixByte(Instruction* instr);
+
+ const disasm::NameConverter& converter_;
+ Vector<char> out_buffer_;
+ int out_buffer_pos_;
+
+ DISALLOW_COPY_AND_ASSIGN(Decoder);
+};
+
+// Support for assertions in the Decoder formatting functions.
+#define STRING_STARTS_WITH(string, compare_string) \
+ (strncmp(string, compare_string, strlen(compare_string)) == 0)
+
+// Append the ch to the output buffer.
+void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
+
+// Append the str to the output buffer.
+void Decoder::Print(const char* str) {
+ char cur = *str++;
+ while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
+ PrintChar(cur);
+ cur = *str++;
+ }
+ out_buffer_[out_buffer_pos_] = 0;
+}
+
+// Print the register name according to the active name converter.
+void Decoder::PrintRegister(int reg) {
+ Print(converter_.NameOfCPURegister(reg));
+}
+
+// Print the double FP register name according to the active name converter.
+void Decoder::PrintDRegister(int reg) {
+ Print(DoubleRegister::from_code(reg).ToString());
+}
+
+// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
+// the FormatOption method.
+void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
+ switch (svc) {
+ case kCallRtRedirected:
+ Print("call rt redirected");
+ return;
+ case kBreakpoint:
+ Print("breakpoint");
+ return;
+ default:
+ if (svc >= kStopCode) {
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x",
+ svc & kStopCodeMask, svc & kStopCodeMask);
+ } else {
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc);
+ }
+ return;
+ }
+}
+
+// Handle all register based formatting in this function to reduce the
+// complexity of FormatOption.
+int Decoder::FormatRegister(Instruction* instr, const char* format) {
+ DCHECK(format[0] == 'r');
+
+ if (format[1] == '1') { // 'r1: register resides in bit 8-11
+ RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr);
+ int reg = rrinstr->R1Value();
+ PrintRegister(reg);
+ return 2;
+ } else if (format[1] == '2') { // 'r2: register resides in bit 12-15
+ RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr);
+ int reg = rrinstr->R2Value();
+ // indicating it is a r0 for displacement, in which case the offset
+ // should be 0.
+ if (format[2] == 'd') {
+ if (reg == 0) return 4;
+ PrintRegister(reg);
+ return 3;
+ } else {
+ PrintRegister(reg);
+ return 2;
+ }
+ } else if (format[1] == '3') { // 'r3: register resides in bit 16-19
+ RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr);
+ int reg = rsinstr->B2Value();
+ PrintRegister(reg);
+ return 2;
+ } else if (format[1] == '4') { // 'r4: register resides in bit 20-23
+ RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr);
+ int reg = rsinstr->B2Value();
+ PrintRegister(reg);
+ return 2;
+ } else if (format[1] == '5') { // 'r5: register resides in bit 24-28
+ RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr);
+ int reg = rreinstr->R1Value();
+ PrintRegister(reg);
+ return 2;
+ } else if (format[1] == '6') { // 'r6: register resides in bit 29-32
+ RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr);
+ int reg = rreinstr->R2Value();
+ PrintRegister(reg);
+ return 2;
+ } else if (format[1] == '7') { // 'r6: register resides in bit 32-35
+ SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr);
+ int reg = ssinstr->B2Value();
+ PrintRegister(reg);
+ return 2;
+ }
+
+ UNREACHABLE();
+ return -1;
+}
+
+int Decoder::FormatFloatingRegister(Instruction* instr, const char* format) {
+ DCHECK(format[0] == 'f');
+
+ // reuse 1, 5 and 6 because it is coresponding
+ if (format[1] == '1') { // 'r1: register resides in bit 8-11
+ RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr);
+ int reg = rrinstr->R1Value();
+ PrintDRegister(reg);
+ return 2;
+ } else if (format[1] == '2') { // 'f2: register resides in bit 12-15
+ RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr);
+ int reg = rrinstr->R2Value();
+ PrintDRegister(reg);
+ return 2;
+ } else if (format[1] == '3') { // 'f3: register resides in bit 16-19
+ RRDInstruction* rrdinstr = reinterpret_cast<RRDInstruction*>(instr);
+ int reg = rrdinstr->R1Value();
+ PrintDRegister(reg);
+ return 2;
+ } else if (format[1] == '5') { // 'f5: register resides in bit 24-28
+ RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr);
+ int reg = rreinstr->R1Value();
+ PrintDRegister(reg);
+ return 2;
+ } else if (format[1] == '6') { // 'f6: register resides in bit 29-32
+ RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr);
+ int reg = rreinstr->R2Value();
+ PrintDRegister(reg);
+ return 2;
+ }
+ UNREACHABLE();
+ return -1;
+}
+
+// FormatOption takes a formatting string and interprets it based on
+// the current instructions. The format string points to the first
+// character of the option string (the option escape has already been
+// consumed by the caller.) FormatOption returns the number of
+// characters that were consumed from the formatting string.
+int Decoder::FormatOption(Instruction* instr, const char* format) {
+ switch (format[0]) {
+ case 'o': {
+ if (instr->Bit(10) == 1) {
+ Print("o");
+ }
+ return 1;
+ }
+ case '.': {
+ if (instr->Bit(0) == 1) {
+ Print(".");
+ } else {
+ Print(" "); // ensure consistent spacing
+ }
+ return 1;
+ }
+ case 'r': {
+ return FormatRegister(instr, format);
+ }
+ case 'f': {
+ return FormatFloatingRegister(instr, format);
+ }
+ case 'i': { // int16
+ return FormatImmediate(instr, format);
+ }
+ case 'u': { // uint16
+ int32_t value = instr->Bits(15, 0);
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 6;
+ }
+ case 'l': {
+ // Link (LK) Bit 0
+ if (instr->Bit(0) == 1) {
+ Print("l");
+ }
+ return 1;
+ }
+ case 'a': {
+ // Absolute Address Bit 1
+ if (instr->Bit(1) == 1) {
+ Print("a");
+ }
+ return 1;
+ }
+ case 't': { // 'target: target of branch instructions
+ // target26 or target16
+ DCHECK(STRING_STARTS_WITH(format, "target"));
+ if ((format[6] == '2') && (format[7] == '6')) {
+ int off = ((instr->Bits(25, 2)) << 8) >> 6;
+ out_buffer_pos_ += SNPrintF(
+ out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
+ return 8;
+ } else if ((format[6] == '1') && (format[7] == '6')) {
+ int off = ((instr->Bits(15, 2)) << 18) >> 16;
+ out_buffer_pos_ += SNPrintF(
+ out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
+ return 8;
+ }
+ case 'm': {
+ return FormatMask(instr, format);
+ }
+ }
+ case 'd': { // ds value for offset
+ return FormatDisplacement(instr, format);
+ }
+ default: {
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ UNREACHABLE();
+ return -1;
+}
+
+int Decoder::FormatMask(Instruction* instr, const char* format) {
+ DCHECK(format[0] == 'm');
+ int32_t value = 0;
+ if ((format[1] == '1')) { // prints the mask format in bit 8-12
+ value = reinterpret_cast<RRInstruction*>(instr)->R1Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value);
+ return 2;
+ } else if (format[1] == '2') { // mask format in bit 16 - 19
+ value = reinterpret_cast<RXInstruction*>(instr)->B2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value);
+ return 2;
+ }
+
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+}
+
+int Decoder::FormatDisplacement(Instruction* instr, const char* format) {
+ DCHECK(format[0] == 'd');
+
+ if (format[1] == '1') { // displacement in 20-31
+ RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr);
+ uint16_t value = rsinstr->D2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+
+ return 2;
+ } else if (format[1] == '2') { // displacement in 20-39
+ RXYInstruction* rxyinstr = reinterpret_cast<RXYInstruction*>(instr);
+ int32_t value = rxyinstr->D2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '4') { // SS displacement 2 36-47
+ SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
+ uint16_t value = ssInstr->D2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '3') { // SS displacement 1 20 - 32
+ SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
+ uint16_t value = ssInstr->D1Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else { // s390 specific
+ int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 1;
+ }
+}
+
+int Decoder::FormatImmediate(Instruction* instr, const char* format) {
+ DCHECK(format[0] == 'i');
+
+ if (format[1] == '1') { // immediate in 16-31
+ RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr);
+ int16_t value = riinstr->I2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '2') { // immediate in 16-48
+ RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
+ int32_t value = rilinstr->I2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '3') { // immediate in I format
+ IInstruction* iinstr = reinterpret_cast<IInstruction*>(instr);
+ int8_t value = iinstr->IValue();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '4') { // immediate in 16-31, but outputs as offset
+ RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr);
+ int16_t value = riinstr->I2Value() * 2;
+ if (value >= 0)
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "*+");
+ else
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "*");
+
+ out_buffer_pos_ += SNPrintF(
+ out_buffer_ + out_buffer_pos_, "%d -> %s", value,
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + value));
+ return 2;
+ } else if (format[1] == '5') { // immediate in 16-31, but outputs as offset
+ RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
+ int32_t value = rilinstr->I2Value() * 2;
+ if (value >= 0)
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "*+");
+ else
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "*");
+
+ out_buffer_pos_ += SNPrintF(
+ out_buffer_ + out_buffer_pos_, "%d -> %s", value,
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + value));
+ return 2;
+ } else if (format[1] == '6') { // unsigned immediate in 16-31
+ RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr);
+ uint16_t value = riinstr->I2UnsignedValue();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '7') { // unsigned immediate in 16-47
+ RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
+ uint32_t value = rilinstr->I2UnsignedValue();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '8') { // unsigned immediate in 8-15
+ SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr);
+ uint8_t value = ssinstr->Length();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == '9') { // unsigned immediate in 16-23
+ RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr);
+ uint8_t value = rie_instr->I3Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == 'a') { // unsigned immediate in 24-31
+ RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr);
+ uint8_t value = rie_instr->I4Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == 'b') { // unsigned immediate in 32-39
+ RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr);
+ uint8_t value = rie_instr->I5Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == 'c') { // signed immediate in 8-15
+ SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr);
+ int8_t value = ssinstr->Length();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == 'd') { // signed immediate in 32-47
+ SILInstruction* silinstr = reinterpret_cast<SILInstruction*>(instr);
+ int16_t value = silinstr->I2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
+ return 2;
+ } else if (format[1] == 'e') { // immediate in 16-47, but outputs as offset
+ RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
+ int32_t value = rilinstr->I2Value() * 2;
+ if (value >= 0)
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "*+");
+ else
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "*");
+
+ out_buffer_pos_ += SNPrintF(
+ out_buffer_ + out_buffer_pos_, "%d -> %s", value,
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + value));
+ return 2;
+ }
+
+ UNREACHABLE();
+ return -1;
+}
+
+// Format takes a formatting string for a whole instruction and prints it into
+// the output buffer. All escaped options are handed to FormatOption to be
+// parsed further.
+void Decoder::Format(Instruction* instr, const char* format) {
+ char cur = *format++;
+ while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
+ if (cur == '\'') { // Single quote is used as the formatting escape.
+ format += FormatOption(instr, format);
+ } else {
+ out_buffer_[out_buffer_pos_++] = cur;
+ }
+ cur = *format++;
+ }
+ out_buffer_[out_buffer_pos_] = '\0';
+}
+
+// The disassembler may end up decoding data inlined in the code. We do not want
+// it to crash if the data does not ressemble any known instruction.
+#define VERIFY(condition) \
+ if (!(condition)) { \
+ Unknown(instr); \
+ return; \
+ }
+
+// For currently unimplemented decodings the disassembler calls Unknown(instr)
+// which will just print "unknown" of the instruction bits.
+void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); }
+
+// For currently unimplemented decodings the disassembler calls
+// UnknownFormat(instr) which will just print opcode name of the
+// instruction bits.
+void Decoder::UnknownFormat(Instruction* instr, const char* name) {
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name);
+ Format(instr, buffer);
+}
+
+// Disassembles Two Byte S390 Instructions
+// @return true if successfully decoded
+bool Decoder::DecodeTwoByte(Instruction* instr) {
+ // Print the Instruction bits.
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%04x ",
+ instr->InstructionBits<TwoByteInstr>());
+
+ Opcode opcode = instr->S390OpcodeValue();
+ switch (opcode) {
+ case AR:
+ Format(instr, "ar\t'r1,'r2");
+ break;
+ case SR:
+ Format(instr, "sr\t'r1,'r2");
+ break;
+ case MR:
+ Format(instr, "mr\t'r1,'r2");
+ break;
+ case DR:
+ Format(instr, "dr\t'r1,'r2");
+ break;
+ case OR:
+ Format(instr, "or\t'r1,'r2");
+ break;
+ case NR:
+ Format(instr, "nr\t'r1,'r2");
+ break;
+ case XR:
+ Format(instr, "xr\t'r1,'r2");
+ break;
+ case LR:
+ Format(instr, "lr\t'r1,'r2");
+ break;
+ case CR:
+ Format(instr, "cr\t'r1,'r2");
+ break;
+ case CLR:
+ Format(instr, "clr\t'r1,'r2");
+ break;
+ case BCR:
+ Format(instr, "bcr\t'm1,'r2");
+ break;
+ case LTR:
+ Format(instr, "ltr\t'r1,'r2");
+ break;
+ case ALR:
+ Format(instr, "alr\t'r1,'r2");
+ break;
+ case SLR:
+ Format(instr, "slr\t'r1,'r2");
+ break;
+ case LNR:
+ Format(instr, "lnr\t'r1,'r2");
+ break;
+ case LCR:
+ Format(instr, "lcr\t'r1,'r2");
+ break;
+ case BASR:
+ Format(instr, "basr\t'r1,'r2");
+ break;
+ case LDR:
+ Format(instr, "ldr\t'f1,'f2");
+ break;
+ case BKPT:
+ Format(instr, "bkpt");
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+// Disassembles Four Byte S390 Instructions
+// @return true if successfully decoded
+bool Decoder::DecodeFourByte(Instruction* instr) {
+ // Print the Instruction bits.
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ",
+ instr->InstructionBits<FourByteInstr>());
+
+ Opcode opcode = instr->S390OpcodeValue();
+ switch (opcode) {
+ case AHI:
+ Format(instr, "ahi\t'r1,'i1");
+ break;
+ case AGHI:
+ Format(instr, "aghi\t'r1,'i1");
+ break;
+ case LHI:
+ Format(instr, "lhi\t'r1,'i1");
+ break;
+ case LGHI:
+ Format(instr, "lghi\t'r1,'i1");
+ break;
+ case MHI:
+ Format(instr, "mhi\t'r1,'i1");
+ break;
+ case MGHI:
+ Format(instr, "mghi\t'r1,'i1");
+ break;
+ case CHI:
+ Format(instr, "chi\t'r1,'i1");
+ break;
+ case CGHI:
+ Format(instr, "cghi\t'r1,'i1");
+ break;
+ case BRAS:
+ Format(instr, "bras\t'r1,'i1");
+ break;
+ case BRC:
+ Format(instr, "brc\t'm1,'i4");
+ break;
+ case BRCT:
+ Format(instr, "brct\t'r1,'i4");
+ break;
+ case BRCTG:
+ Format(instr, "brctg\t'r1,'i4");
+ break;
+ case IIHH:
+ Format(instr, "iihh\t'r1,'i1");
+ break;
+ case IIHL:
+ Format(instr, "iihl\t'r1,'i1");
+ break;
+ case IILH:
+ Format(instr, "iilh\t'r1,'i1");
+ break;
+ case IILL:
+ Format(instr, "iill\t'r1,'i1");
+ break;
+ case OILL:
+ Format(instr, "oill\t'r1,'i1");
+ break;
+ case TMLL:
+ Format(instr, "tmll\t'r1,'i1");
+ break;
+ case STM:
+ Format(instr, "stm\t'r1,'r2,'d1('r3)");
+ break;
+ case LM:
+ Format(instr, "lm\t'r1,'r2,'d1('r3)");
+ break;
+ case SLL:
+ Format(instr, "sll\t'r1,'d1('r3)");
+ break;
+ case SRL:
+ Format(instr, "srl\t'r1,'d1('r3)");
+ break;
+ case SLA:
+ Format(instr, "sla\t'r1,'d1('r3)");
+ break;
+ case SRA:
+ Format(instr, "sra\t'r1,'d1('r3)");
+ break;
+ case AGR:
+ Format(instr, "agr\t'r5,'r6");
+ break;
+ case AGFR:
+ Format(instr, "agfr\t'r5,'r6");
+ break;
+ case ARK:
+ Format(instr, "ark\t'r5,'r6,'r3");
+ break;
+ case AGRK:
+ Format(instr, "agrk\t'r5,'r6,'r3");
+ break;
+ case SGR:
+ Format(instr, "sgr\t'r5,'r6");
+ break;
+ case SGFR:
+ Format(instr, "sgfr\t'r5,'r6");
+ break;
+ case SRK:
+ Format(instr, "srk\t'r5,'r6,'r3");
+ break;
+ case SGRK:
+ Format(instr, "sgrk\t'r5,'r6,'r3");
+ break;
+ case NGR:
+ Format(instr, "ngr\t'r5,'r6");
+ break;
+ case NRK:
+ Format(instr, "nrk\t'r5,'r6,'r3");
+ break;
+ case NGRK:
+ Format(instr, "ngrk\t'r5,'r6,'r3");
+ break;
+ case NILL:
+ Format(instr, "nill\t'r1,'i1");
+ break;
+ case NILH:
+ Format(instr, "nilh\t'r1,'i1");
+ break;
+ case OGR:
+ Format(instr, "ogr\t'r5,'r6");
+ break;
+ case ORK:
+ Format(instr, "ork\t'r5,'r6,'r3");
+ break;
+ case OGRK:
+ Format(instr, "ogrk\t'r5,'r6,'r3");
+ break;
+ case XGR:
+ Format(instr, "xgr\t'r5,'r6");
+ break;
+ case XRK:
+ Format(instr, "xrk\t'r5,'r6,'r3");
+ break;
+ case XGRK:
+ Format(instr, "xgrk\t'r5,'r6,'r3");
+ break;
+ case CGR:
+ Format(instr, "cgr\t'r5,'r6");
+ break;
+ case CLGR:
+ Format(instr, "clgr\t'r5,'r6");
+ break;
+ case LLGFR:
+ Format(instr, "llgfr\t'r5,'r6");
+ break;
+ case LBR:
+ Format(instr, "lbr\t'r5,'r6");
+ break;
+ case LEDBR:
+ Format(instr, "ledbr\t'f5,'f6");
+ break;
+ case LDEBR:
+ Format(instr, "ldebr\t'f5,'f6");
+ break;
+ case LTGR:
+ Format(instr, "ltgr\t'r5,'r6");
+ break;
+ case LTDBR:
+ Format(instr, "ltdbr\t'f5,'f6");
+ break;
+ case LTEBR:
+ Format(instr, "ltebr\t'f5,'f6");
+ break;
+ case LGR:
+ Format(instr, "lgr\t'r5,'r6");
+ break;
+ case LGDR:
+ Format(instr, "lgdr\t'r5,'f6");
+ break;
+ case LGFR:
+ Format(instr, "lgfr\t'r5,'r6");
+ break;
+ case LTGFR:
+ Format(instr, "ltgfr\t'r5,'r6");
+ break;
+ case LCGR:
+ Format(instr, "lcgr\t'r5,'r6");
+ break;
+ case MSR:
+ Format(instr, "msr\t'r5,'r6");
+ break;
+ case LGBR:
+ Format(instr, "lgbr\t'r5,'r6");
+ break;
+ case LGHR:
+ Format(instr, "lghr\t'r5,'r6");
+ break;
+ case MSGR:
+ Format(instr, "msgr\t'r5,'r6");
+ break;
+ case DSGR:
+ Format(instr, "dsgr\t'r5,'r6");
+ break;
+ case LZDR:
+ Format(instr, "lzdr\t'f5");
+ break;
+ case MLR:
+ Format(instr, "mlr\t'r5,'r6");
+ break;
+ case MLGR:
+ Format(instr, "mlgr\t'r5,'r6");
+ break;
+ case ALGR:
+ Format(instr, "algr\t'r5,'r6");
+ break;
+ case ALRK:
+ Format(instr, "alrk\t'r5,'r6,'r3");
+ break;
+ case ALGRK:
+ Format(instr, "algrk\t'r5,'r6,'r3");
+ break;
+ case SLGR:
+ Format(instr, "slgr\t'r5,'r6");
+ break;
+ case DLR:
+ Format(instr, "dlr\t'r1,'r2");
+ break;
+ case DLGR:
+ Format(instr, "dlgr\t'r5,'r6");
+ break;
+ case SLRK:
+ Format(instr, "slrk\t'r5,'r6,'r3");
+ break;
+ case SLGRK:
+ Format(instr, "slgrk\t'r5,'r6,'r3");
+ break;
+ case LHR:
+ Format(instr, "lhr\t'r5,'r6");
+ break;
+ case LLHR:
+ Format(instr, "llhr\t'r5,'r6");
+ break;
+ case LLGHR:
+ Format(instr, "llghr\t'r5,'r6");
+ break;
+ case LNGR:
+ Format(instr, "lngr\t'r5,'r6");
+ break;
+ case A:
+ Format(instr, "a\t'r1,'d1('r2d,'r3)");
+ break;
+ case S:
+ Format(instr, "s\t'r1,'d1('r2d,'r3)");
+ break;
+ case M:
+ Format(instr, "m\t'r1,'d1('r2d,'r3)");
+ break;
+ case D:
+ Format(instr, "d\t'r1,'d1('r2d,'r3)");
+ break;
+ case O:
+ Format(instr, "o\t'r1,'d1('r2d,'r3)");
+ break;
+ case N:
+ Format(instr, "n\t'r1,'d1('r2d,'r3)");
+ break;
+ case L:
+ Format(instr, "l\t'r1,'d1('r2d,'r3)");
+ break;
+ case C:
+ Format(instr, "c\t'r1,'d1('r2d,'r3)");
+ break;
+ case AH:
+ Format(instr, "ah\t'r1,'d1('r2d,'r3)");
+ break;
+ case SH:
+ Format(instr, "sh\t'r1,'d1('r2d,'r3)");
+ break;
+ case MH:
+ Format(instr, "mh\t'r1,'d1('r2d,'r3)");
+ break;
+ case AL:
+ Format(instr, "al\t'r1,'d1('r2d,'r3)");
+ break;
+ case SL:
+ Format(instr, "sl\t'r1,'d1('r2d,'r3)");
+ break;
+ case LA:
+ Format(instr, "la\t'r1,'d1('r2d,'r3)");
+ break;
+ case CH:
+ Format(instr, "ch\t'r1,'d1('r2d,'r3)");
+ break;
+ case CL:
+ Format(instr, "cl\t'r1,'d1('r2d,'r3)");
+ break;
+ case CLI:
+ Format(instr, "cli\t'd1('r3),'i8");
+ break;
+ case TM:
+ Format(instr, "tm\t'd1('r3),'i8");
+ break;
+ case BC:
+ Format(instr, "bc\t'm1,'d1('r2d,'r3)");
+ break;
+ case BCT:
+ Format(instr, "bct\t'r1,'d1('r2d,'r3)");
+ break;
+ case ST:
+ Format(instr, "st\t'r1,'d1('r2d,'r3)");
+ break;
+ case STC:
+ Format(instr, "stc\t'r1,'d1('r2d,'r3)");
+ break;
+ case IC_z:
+ Format(instr, "ic\t'r1,'d1('r2d,'r3)");
+ break;
+ case LD:
+ Format(instr, "ld\t'f1,'d1('r2d,'r3)");
+ break;
+ case LE:
+ Format(instr, "le\t'f1,'d1('r2d,'r3)");
+ break;
+ case LDGR:
+ Format(instr, "ldgr\t'f5,'r6");
+ break;
+ case STE:
+ Format(instr, "ste\t'f1,'d1('r2d,'r3)");
+ break;
+ case STD:
+ Format(instr, "std\t'f1,'d1('r2d,'r3)");
+ break;
+ case CFDBR:
+ Format(instr, "cfdbr\t'r5,'m2,'f6");
+ break;
+ case CDFBR:
+ Format(instr, "cdfbr\t'f5,'m2,'r6");
+ break;
+ case CFEBR:
+ Format(instr, "cfebr\t'r5,'m2,'f6");
+ break;
+ case CEFBR:
+ Format(instr, "cefbr\t'f5,'m2,'r6");
+ break;
+ case CGEBR:
+ Format(instr, "cgebr\t'r5,'m2,'f6");
+ break;
+ case CGDBR:
+ Format(instr, "cgdbr\t'r5,'m2,'f6");
+ break;
+ case CEGBR:
+ Format(instr, "cegbr\t'f5,'m2,'r6");
+ break;
+ case CDGBR:
+ Format(instr, "cdgbr\t'f5,'m2,'r6");
+ break;
+ case CDLFBR:
+ Format(instr, "cdlfbr\t'f5,'m2,'r6");
+ break;
+ case CDLGBR:
+ Format(instr, "cdlgbr\t'f5,'m2,'r6");
+ break;
+ case CELGBR:
+ Format(instr, "celgbr\t'f5,'m2,'r6");
+ break;
+ case CLFDBR:
+ Format(instr, "clfdbr\t'r5,'m2,'f6");
+ break;
+ case CLGDBR:
+ Format(instr, "clgdbr\t'r5,'m2,'f6");
+ break;
+ case AEBR:
+ Format(instr, "aebr\t'f5,'f6");
+ break;
+ case SEBR:
+ Format(instr, "sebr\t'f5,'f6");
+ break;
+ case MEEBR:
+ Format(instr, "meebr\t'f5,'f6");
+ break;
+ case DEBR:
+ Format(instr, "debr\t'f5,'f6");
+ break;
+ case ADBR:
+ Format(instr, "adbr\t'f5,'f6");
+ break;
+ case SDBR:
+ Format(instr, "sdbr\t'f5,'f6");
+ break;
+ case MDBR:
+ Format(instr, "mdbr\t'f5,'f6");
+ break;
+ case DDBR:
+ Format(instr, "ddbr\t'f5,'f6");
+ break;
+ case CDBR:
+ Format(instr, "cdbr\t'f5,'f6");
+ break;
+ case SQDBR:
+ Format(instr, "sqdbr\t'f5,'f6");
+ break;
+ case LCDBR:
+ Format(instr, "lcdbr\t'f5,'f6");
+ break;
+ case STH:
+ Format(instr, "sth\t'r1,'d1('r2d,'r3)");
+ break;
+ case SRDA:
+ Format(instr, "srda\t'r1,'d1");
+ break;
+ case SRDL:
+ Format(instr, "srdl\t'r1,'d1");
+ break;
+ case MADBR:
+ Format(instr, "madbr\t'f3,'f5,'f6");
+ break;
+ case MSDBR:
+ Format(instr, "msdbr\t'f3,'f5,'f6");
+ break;
+ case FLOGR:
+ Format(instr, "flogr\t'r5,'r6");
+ break;
+ // TRAP4 is used in calling to native function. it will not be generated
+ // in native code.
+ case TRAP4: {
+ Format(instr, "trap4");
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+// Disassembles Six Byte S390 Instructions
+// @return true if successfully decoded
+bool Decoder::DecodeSixByte(Instruction* instr) {
+ // Print the Instruction bits.
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%012" PRIx64 " ",
+ instr->InstructionBits<SixByteInstr>());
+
+ Opcode opcode = instr->S390OpcodeValue();
+ switch (opcode) {
+ case LLILF:
+ Format(instr, "llilf\t'r1,'i7");
+ break;
+ case LLIHF:
+ Format(instr, "llihf\t'r1,'i7");
+ break;
+ case AFI:
+ Format(instr, "afi\t'r1,'i7");
+ break;
+ case ASI:
+ Format(instr, "asi\t'd2('r3),'ic");
+ break;
+ case AGSI:
+ Format(instr, "agsi\t'd2('r3),'ic");
+ break;
+ case ALFI:
+ Format(instr, "alfi\t'r1,'i7");
+ break;
+ case AHIK:
+ Format(instr, "ahik\t'r1,'r2,'i1");
+ break;
+ case AGHIK:
+ Format(instr, "aghik\t'r1,'r2,'i1");
+ break;
+ case CLGFI:
+ Format(instr, "clgfi\t'r1,'i7");
+ break;
+ case CLFI:
+ Format(instr, "clfi\t'r1,'i7");
+ break;
+ case CFI:
+ Format(instr, "cfi\t'r1,'i2");
+ break;
+ case CGFI:
+ Format(instr, "cgfi\t'r1,'i2");
+ break;
+ case BRASL:
+ Format(instr, "brasl\t'r1,'ie");
+ break;
+ case BRCL:
+ Format(instr, "brcl\t'm1,'i5");
+ break;
+ case IIHF:
+ Format(instr, "iihf\t'r1,'i7");
+ break;
+ case IILF:
+ Format(instr, "iilf\t'r1,'i7");
+ break;
+ case XIHF:
+ Format(instr, "xihf\t'r1,'i7");
+ break;
+ case XILF:
+ Format(instr, "xilf\t'r1,'i7");
+ break;
+ case SLLK:
+ Format(instr, "sllk\t'r1,'r2,'d2('r3)");
+ break;
+ case SLLG:
+ Format(instr, "sllg\t'r1,'r2,'d2('r3)");
+ break;
+ case RLL:
+ Format(instr, "rll\t'r1,'r2,'d2('r3)");
+ break;
+ case RLLG:
+ Format(instr, "rllg\t'r1,'r2,'d2('r3)");
+ break;
+ case SRLK:
+ Format(instr, "srlk\t'r1,'r2,'d2('r3)");
+ break;
+ case SRLG:
+ Format(instr, "srlg\t'r1,'r2,'d2('r3)");
+ break;
+ case SLAK:
+ Format(instr, "slak\t'r1,'r2,'d2('r3)");
+ break;
+ case SLAG:
+ Format(instr, "slag\t'r1,'r2,'d2('r3)");
+ break;
+ case SRAK:
+ Format(instr, "srak\t'r1,'r2,'d2('r3)");
+ break;
+ case SRAG:
+ Format(instr, "srag\t'r1,'r2,'d2('r3)");
+ break;
+ case RISBG:
+ Format(instr, "risbg\t'r1,'r2,'i9,'ia,'ib");
+ break;
+ case RISBGN:
+ Format(instr, "risbgn\t'r1,'r2,'i9,'ia,'ib");
+ break;
+ case LMY:
+ Format(instr, "lmy\t'r1,'r2,'d2('r3)");
+ break;
+ case LMG:
+ Format(instr, "lmg\t'r1,'r2,'d2('r3)");
+ break;
+ case STMY:
+ Format(instr, "stmy\t'r1,'r2,'d2('r3)");
+ break;
+ case STMG:
+ Format(instr, "stmg\t'r1,'r2,'d2('r3)");
+ break;
+ case LT:
+ Format(instr, "lt\t'r1,'d2('r2d,'r3)");
+ break;
+ case LTG:
+ Format(instr, "ltg\t'r1,'d2('r2d,'r3)");
+ break;
+ case ML:
+ Format(instr, "ml\t'r1,'d2('r2d,'r3)");
+ break;
+ case AY:
+ Format(instr, "ay\t'r1,'d2('r2d,'r3)");
+ break;
+ case SY:
+ Format(instr, "sy\t'r1,'d2('r2d,'r3)");
+ break;
+ case NY:
+ Format(instr, "ny\t'r1,'d2('r2d,'r3)");
+ break;
+ case OY:
+ Format(instr, "oy\t'r1,'d2('r2d,'r3)");
+ break;
+ case XY:
+ Format(instr, "xy\t'r1,'d2('r2d,'r3)");
+ break;
+ case CY:
+ Format(instr, "cy\t'r1,'d2('r2d,'r3)");
+ break;
+ case AHY:
+ Format(instr, "ahy\t'r1,'d2('r2d,'r3)");
+ break;
+ case SHY:
+ Format(instr, "shy\t'r1,'d2('r2d,'r3)");
+ break;
+ case LGH:
+ Format(instr, "lgh\t'r1,'d2('r2d,'r3)");
+ break;
+ case AG:
+ Format(instr, "ag\t'r1,'d2('r2d,'r3)");
+ break;
+ case AGF:
+ Format(instr, "agf\t'r1,'d2('r2d,'r3)");
+ break;
+ case SG:
+ Format(instr, "sg\t'r1,'d2('r2d,'r3)");
+ break;
+ case NG:
+ Format(instr, "ng\t'r1,'d2('r2d,'r3)");
+ break;
+ case OG:
+ Format(instr, "og\t'r1,'d2('r2d,'r3)");
+ break;
+ case XG:
+ Format(instr, "xg\t'r1,'d2('r2d,'r3)");
+ break;
+ case CG:
+ Format(instr, "cg\t'r1,'d2('r2d,'r3)");
+ break;
+ case LB:
+ Format(instr, "lb\t'r1,'d2('r2d,'r3)");
+ break;
+ case LG:
+ Format(instr, "lg\t'r1,'d2('r2d,'r3)");
+ break;
+ case LGF:
+ Format(instr, "lgf\t'r1,'d2('r2d,'r3)");
+ break;
+ case LLGF:
+ Format(instr, "llgf\t'r1,'d2('r2d,'r3)");
+ break;
+ case LY:
+ Format(instr, "ly\t'r1,'d2('r2d,'r3)");
+ break;
+ case ALY:
+ Format(instr, "aly\t'r1,'d2('r2d,'r3)");
+ break;
+ case ALG:
+ Format(instr, "alg\t'r1,'d2('r2d,'r3)");
+ break;
+ case SLG:
+ Format(instr, "slg\t'r1,'d2('r2d,'r3)");
+ break;
+ case SGF:
+ Format(instr, "sgf\t'r1,'d2('r2d,'r3)");
+ break;
+ case SLY:
+ Format(instr, "sly\t'r1,'d2('r2d,'r3)");
+ break;
+ case LLH:
+ Format(instr, "llh\t'r1,'d2('r2d,'r3)");
+ break;
+ case LLGH:
+ Format(instr, "llgh\t'r1,'d2('r2d,'r3)");
+ break;
+ case LLC:
+ Format(instr, "llc\t'r1,'d2('r2d,'r3)");
+ break;
+ case LLGC:
+ Format(instr, "llgc\t'r1,'d2('r2d,'r3)");
+ break;
+ case LDEB:
+ Format(instr, "ldeb\t'f1,'d2('r2d,'r3)");
+ break;
+ case LAY:
+ Format(instr, "lay\t'r1,'d2('r2d,'r3)");
+ break;
+ case LARL:
+ Format(instr, "larl\t'r1,'i5");
+ break;
+ case LGB:
+ Format(instr, "lgb\t'r1,'d2('r2d,'r3)");
+ break;
+ case CHY:
+ Format(instr, "chy\t'r1,'d2('r2d,'r3)");
+ break;
+ case CLY:
+ Format(instr, "cly\t'r1,'d2('r2d,'r3)");
+ break;
+ case CLIY:
+ Format(instr, "cliy\t'd2('r3),'i8");
+ break;
+ case TMY:
+ Format(instr, "tmy\t'd2('r3),'i8");
+ break;
+ case CLG:
+ Format(instr, "clg\t'r1,'d2('r2d,'r3)");
+ break;
+ case BCTG:
+ Format(instr, "bctg\t'r1,'d2('r2d,'r3)");
+ break;
+ case STY:
+ Format(instr, "sty\t'r1,'d2('r2d,'r3)");
+ break;
+ case STG:
+ Format(instr, "stg\t'r1,'d2('r2d,'r3)");
+ break;
+ case ICY:
+ Format(instr, "icy\t'r1,'d2('r2d,'r3)");
+ break;
+ case MVC:
+ Format(instr, "mvc\t'd3('i8,'r3),'d4('r7)");
+ break;
+ case MVHI:
+ Format(instr, "mvhi\t'd3('r3),'id");
+ break;
+ case MVGHI:
+ Format(instr, "mvghi\t'd3('r3),'id");
+ break;
+ case ALGFI:
+ Format(instr, "algfi\t'r1,'i7");
+ break;
+ case SLGFI:
+ Format(instr, "slgfi\t'r1,'i7");
+ break;
+ case SLFI:
+ Format(instr, "slfi\t'r1,'i7");
+ break;
+ case NIHF:
+ Format(instr, "nihf\t'r1,'i7");
+ break;
+ case NILF:
+ Format(instr, "nilf\t'r1,'i7");
+ break;
+ case OIHF:
+ Format(instr, "oihf\t'r1,'i7");
+ break;
+ case OILF:
+ Format(instr, "oilf\t'r1,'i7");
+ break;
+ case MSFI:
+ Format(instr, "msfi\t'r1,'i7");
+ break;
+ case MSGFI:
+ Format(instr, "msgfi\t'r1,'i7");
+ break;
+ case LDY:
+ Format(instr, "ldy\t'f1,'d2('r2d,'r3)");
+ break;
+ case LEY:
+ Format(instr, "ley\t'f1,'d2('r2d,'r3)");
+ break;
+ case STEY:
+ Format(instr, "stey\t'f1,'d2('r2d,'r3)");
+ break;
+ case STDY:
+ Format(instr, "stdy\t'f1,'d2('r2d,'r3)");
+ break;
+ case ADB:
+ Format(instr, "adb\t'r1,'d1('r2d, 'r3)");
+ break;
+ case SDB:
+ Format(instr, "sdb\t'r1,'d1('r2d, 'r3)");
+ break;
+ case MDB:
+ Format(instr, "mdb\t'r1,'d1('r2d, 'r3)");
+ break;
+ case DDB:
+ Format(instr, "ddb\t'r1,'d1('r2d, 'r3)");
+ break;
+ case SQDB:
+ Format(instr, "sqdb\t'r1,'d1('r2d, 'r3)");
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+#undef VERIFIY
+
+// Disassemble the instruction at *instr_ptr into the output buffer.
+int Decoder::InstructionDecode(byte* instr_ptr) {
+ Instruction* instr = Instruction::At(instr_ptr);
+ int instrLength = instr->InstructionLength();
+
+ if (2 == instrLength)
+ DecodeTwoByte(instr);
+ else if (4 == instrLength)
+ DecodeFourByte(instr);
+ else
+ DecodeSixByte(instr);
+
+ return instrLength;
+}
+
+} // namespace internal
+} // namespace v8
+
+//------------------------------------------------------------------------------
+
+namespace disasm {
+
+const char* NameConverter::NameOfAddress(byte* addr) const {
+ v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+ return tmp_buffer_.start();
+}
+
+const char* NameConverter::NameOfConstant(byte* addr) const {
+ return NameOfAddress(addr);
+}
+
+const char* NameConverter::NameOfCPURegister(int reg) const {
+ return v8::internal::Register::from_code(reg).ToString();
+}
+
+const char* NameConverter::NameOfByteCPURegister(int reg) const {
+ UNREACHABLE(); // S390 does not have the concept of a byte register
+ return "nobytereg";
+}
+
+const char* NameConverter::NameOfXMMRegister(int reg) const {
+ // S390 does not have XMM register
+ // TODO(joransiu): Consider update this for Vector Regs
+ UNREACHABLE();
+ return "noxmmreg";
+}
+
+const char* NameConverter::NameInCode(byte* addr) const {
+ // The default name converter is called for unknown code. So we will not try
+ // to access any memory.
+ return "";
+}
+
+//------------------------------------------------------------------------------
+
+Disassembler::Disassembler(const NameConverter& converter)
+ : converter_(converter) {}
+
+Disassembler::~Disassembler() {}
+
+int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
+ byte* instruction) {
+ v8::internal::Decoder d(converter_, buffer);
+ return d.InstructionDecode(instruction);
+}
+
+// The S390 assembler does not currently use constant pools.
+int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
+
+void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
+ NameConverter converter;
+ Disassembler d(converter);
+ for (byte* pc = begin; pc < end;) {
+ v8::internal::EmbeddedVector<char, 128> buffer;
+ buffer[0] = '\0';
+ byte* prev_pc = pc;
+ pc += d.InstructionDecode(buffer, pc);
+ v8::internal::PrintF(f, "%p %08x %s\n", prev_pc,
+ *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+ }
+}
+
+} // namespace disasm
+
+#endif // V8_TARGET_ARCH_S390

Powered by Google App Engine
This is Rietveld 408576698