11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci// A Disassembler object is used to disassemble a block of code instruction by 61cb0ef41Sopenharmony_ci// instruction. The default implementation of the NameConverter object can be 71cb0ef41Sopenharmony_ci// overriden to modify register names or to do symbol lookup on addresses. 81cb0ef41Sopenharmony_ci// 91cb0ef41Sopenharmony_ci// The example below will disassemble a block of code and print it to stdout. 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// NameConverter converter; 121cb0ef41Sopenharmony_ci// Disassembler d(converter); 131cb0ef41Sopenharmony_ci// for (byte* pc = begin; pc < end;) { 141cb0ef41Sopenharmony_ci// v8::base::EmbeddedVector<char, 256> buffer; 151cb0ef41Sopenharmony_ci// byte* prev_pc = pc; 161cb0ef41Sopenharmony_ci// pc += d.InstructionDecode(buffer, pc); 171cb0ef41Sopenharmony_ci// printf("%p %08x %s\n", 181cb0ef41Sopenharmony_ci// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); 191cb0ef41Sopenharmony_ci// } 201cb0ef41Sopenharmony_ci// 211cb0ef41Sopenharmony_ci// The Disassembler class also has a convenience method to disassemble a block 221cb0ef41Sopenharmony_ci// of code into a FILE*, meaning that the above functionality could also be 231cb0ef41Sopenharmony_ci// achieved by just calling Disassembler::Disassemble(stdout, begin, end); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci#include <assert.h> 261cb0ef41Sopenharmony_ci#include <stdarg.h> 271cb0ef41Sopenharmony_ci#include <stdio.h> 281cb0ef41Sopenharmony_ci#include <string.h> 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_S390 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h" 331cb0ef41Sopenharmony_ci#include "src/base/strings.h" 341cb0ef41Sopenharmony_ci#include "src/base/vector.h" 351cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 361cb0ef41Sopenharmony_ci#include "src/codegen/register-configuration.h" 371cb0ef41Sopenharmony_ci#include "src/codegen/s390/constants-s390.h" 381cb0ef41Sopenharmony_ci#include "src/diagnostics/disasm.h" 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cinamespace v8 { 411cb0ef41Sopenharmony_cinamespace internal { 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci//------------------------------------------------------------------------------ 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci// Decoder decodes and disassembles instructions into an output buffer. 461cb0ef41Sopenharmony_ci// It uses the converter to convert register names and call destinations into 471cb0ef41Sopenharmony_ci// more informative description. 481cb0ef41Sopenharmony_ciclass Decoder { 491cb0ef41Sopenharmony_ci public: 501cb0ef41Sopenharmony_ci Decoder(const disasm::NameConverter& converter, base::Vector<char> out_buffer) 511cb0ef41Sopenharmony_ci : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) { 521cb0ef41Sopenharmony_ci out_buffer_[out_buffer_pos_] = '\0'; 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci ~Decoder() {} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci Decoder(const Decoder&) = delete; 581cb0ef41Sopenharmony_ci Decoder& operator=(const Decoder&) = delete; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci // Writes one disassembled instruction into 'buffer' (0-terminated). 611cb0ef41Sopenharmony_ci // Returns the length of the disassembled machine instruction in bytes. 621cb0ef41Sopenharmony_ci int InstructionDecode(byte* instruction); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci private: 651cb0ef41Sopenharmony_ci // Bottleneck functions to print into the out_buffer. 661cb0ef41Sopenharmony_ci void PrintChar(const char ch); 671cb0ef41Sopenharmony_ci void Print(const char* str); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci // Printing of common values. 701cb0ef41Sopenharmony_ci void PrintRegister(int reg); 711cb0ef41Sopenharmony_ci void PrintDRegister(int reg); 721cb0ef41Sopenharmony_ci void PrintSoftwareInterrupt(SoftwareInterruptCodes svc); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci // Handle formatting of instructions and their options. 751cb0ef41Sopenharmony_ci int FormatRegister(Instruction* instr, const char* option); 761cb0ef41Sopenharmony_ci int FormatFloatingRegister(Instruction* instr, const char* option); 771cb0ef41Sopenharmony_ci int FormatMask(Instruction* instr, const char* option); 781cb0ef41Sopenharmony_ci int FormatDisplacement(Instruction* instr, const char* option); 791cb0ef41Sopenharmony_ci int FormatImmediate(Instruction* instr, const char* option); 801cb0ef41Sopenharmony_ci int FormatOption(Instruction* instr, const char* option); 811cb0ef41Sopenharmony_ci void Format(Instruction* instr, const char* format); 821cb0ef41Sopenharmony_ci void Unknown(Instruction* instr); 831cb0ef41Sopenharmony_ci void UnknownFormat(Instruction* instr, const char* opcname); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci bool DecodeSpecial(Instruction* instr); 861cb0ef41Sopenharmony_ci bool DecodeGeneric(Instruction* instr); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci const disasm::NameConverter& converter_; 891cb0ef41Sopenharmony_ci base::Vector<char> out_buffer_; 901cb0ef41Sopenharmony_ci int out_buffer_pos_; 911cb0ef41Sopenharmony_ci}; 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci// Support for assertions in the Decoder formatting functions. 941cb0ef41Sopenharmony_ci#define STRING_STARTS_WITH(string, compare_string) \ 951cb0ef41Sopenharmony_ci (strncmp(string, compare_string, strlen(compare_string)) == 0) 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci// Append the ch to the output buffer. 981cb0ef41Sopenharmony_civoid Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci// Append the str to the output buffer. 1011cb0ef41Sopenharmony_civoid Decoder::Print(const char* str) { 1021cb0ef41Sopenharmony_ci char cur = *str++; 1031cb0ef41Sopenharmony_ci while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 1041cb0ef41Sopenharmony_ci PrintChar(cur); 1051cb0ef41Sopenharmony_ci cur = *str++; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci out_buffer_[out_buffer_pos_] = 0; 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci// Print the register name according to the active name converter. 1111cb0ef41Sopenharmony_civoid Decoder::PrintRegister(int reg) { 1121cb0ef41Sopenharmony_ci Print(converter_.NameOfCPURegister(reg)); 1131cb0ef41Sopenharmony_ci} 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci// Print the double FP register name according to the active name converter. 1161cb0ef41Sopenharmony_civoid Decoder::PrintDRegister(int reg) { 1171cb0ef41Sopenharmony_ci Print(RegisterName(DoubleRegister::from_code(reg))); 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of 1211cb0ef41Sopenharmony_ci// the FormatOption method. 1221cb0ef41Sopenharmony_civoid Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) { 1231cb0ef41Sopenharmony_ci switch (svc) { 1241cb0ef41Sopenharmony_ci case kCallRtRedirected: 1251cb0ef41Sopenharmony_ci Print("call rt redirected"); 1261cb0ef41Sopenharmony_ci return; 1271cb0ef41Sopenharmony_ci case kBreakpoint: 1281cb0ef41Sopenharmony_ci Print("breakpoint"); 1291cb0ef41Sopenharmony_ci return; 1301cb0ef41Sopenharmony_ci default: 1311cb0ef41Sopenharmony_ci if (svc >= kStopCode) { 1321cb0ef41Sopenharmony_ci out_buffer_pos_ += 1331cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x", 1341cb0ef41Sopenharmony_ci svc & kStopCodeMask, svc & kStopCodeMask); 1351cb0ef41Sopenharmony_ci } else { 1361cb0ef41Sopenharmony_ci out_buffer_pos_ += 1371cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc); 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci return; 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci} 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci// Handle all register based formatting in this function to reduce the 1441cb0ef41Sopenharmony_ci// complexity of FormatOption. 1451cb0ef41Sopenharmony_ciint Decoder::FormatRegister(Instruction* instr, const char* format) { 1461cb0ef41Sopenharmony_ci DCHECK_EQ(format[0], 'r'); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci if (format[1] == '1') { // 'r1: register resides in bit 8-11 1491cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(39, 36); 1501cb0ef41Sopenharmony_ci PrintRegister(reg); 1511cb0ef41Sopenharmony_ci return 2; 1521cb0ef41Sopenharmony_ci } else if (format[1] == '2') { // 'r2: register resides in bit 12-15 1531cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(35, 32); 1541cb0ef41Sopenharmony_ci // indicating it is a r0 for displacement, in which case the offset 1551cb0ef41Sopenharmony_ci // should be 0. 1561cb0ef41Sopenharmony_ci if (format[2] == 'd') { 1571cb0ef41Sopenharmony_ci if (reg == 0) return 4; 1581cb0ef41Sopenharmony_ci PrintRegister(reg); 1591cb0ef41Sopenharmony_ci return 3; 1601cb0ef41Sopenharmony_ci } else { 1611cb0ef41Sopenharmony_ci PrintRegister(reg); 1621cb0ef41Sopenharmony_ci return 2; 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci } else if (format[1] == '3') { // 'r3: register resides in bit 16-19 1651cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(31, 28); 1661cb0ef41Sopenharmony_ci PrintRegister(reg); 1671cb0ef41Sopenharmony_ci return 2; 1681cb0ef41Sopenharmony_ci } else if (format[1] == '4') { // 'r4: register resides in bit 20-23 1691cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(27, 24); 1701cb0ef41Sopenharmony_ci PrintRegister(reg); 1711cb0ef41Sopenharmony_ci return 2; 1721cb0ef41Sopenharmony_ci } else if (format[1] == '5') { // 'r5: register resides in bit 24-27 1731cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(23, 20); 1741cb0ef41Sopenharmony_ci PrintRegister(reg); 1751cb0ef41Sopenharmony_ci return 2; 1761cb0ef41Sopenharmony_ci } else if (format[1] == '6') { // 'r6: register resides in bit 28-31 1771cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(19, 16); 1781cb0ef41Sopenharmony_ci PrintRegister(reg); 1791cb0ef41Sopenharmony_ci return 2; 1801cb0ef41Sopenharmony_ci } else if (format[1] == '7') { // 'r6: register resides in bit 32-35 1811cb0ef41Sopenharmony_ci int reg = instr->Bits<SixByteInstr, int>(15, 12); 1821cb0ef41Sopenharmony_ci PrintRegister(reg); 1831cb0ef41Sopenharmony_ci return 2; 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci UNREACHABLE(); 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ciint Decoder::FormatFloatingRegister(Instruction* instr, const char* format) { 1901cb0ef41Sopenharmony_ci DCHECK_EQ(format[0], 'f'); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // reuse 1, 5 and 6 because it is coresponding 1931cb0ef41Sopenharmony_ci if (format[1] == '1') { // 'r1: register resides in bit 8-11 1941cb0ef41Sopenharmony_ci RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr); 1951cb0ef41Sopenharmony_ci int reg = rrinstr->R1Value(); 1961cb0ef41Sopenharmony_ci PrintDRegister(reg); 1971cb0ef41Sopenharmony_ci return 2; 1981cb0ef41Sopenharmony_ci } else if (format[1] == '2') { // 'f2: register resides in bit 12-15 1991cb0ef41Sopenharmony_ci RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr); 2001cb0ef41Sopenharmony_ci int reg = rrinstr->R2Value(); 2011cb0ef41Sopenharmony_ci PrintDRegister(reg); 2021cb0ef41Sopenharmony_ci return 2; 2031cb0ef41Sopenharmony_ci } else if (format[1] == '3') { // 'f3: register resides in bit 16-19 2041cb0ef41Sopenharmony_ci RRDInstruction* rrdinstr = reinterpret_cast<RRDInstruction*>(instr); 2051cb0ef41Sopenharmony_ci int reg = rrdinstr->R1Value(); 2061cb0ef41Sopenharmony_ci PrintDRegister(reg); 2071cb0ef41Sopenharmony_ci return 2; 2081cb0ef41Sopenharmony_ci } else if (format[1] == '5') { // 'f5: register resides in bit 24-28 2091cb0ef41Sopenharmony_ci RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr); 2101cb0ef41Sopenharmony_ci int reg = rreinstr->R1Value(); 2111cb0ef41Sopenharmony_ci PrintDRegister(reg); 2121cb0ef41Sopenharmony_ci return 2; 2131cb0ef41Sopenharmony_ci } else if (format[1] == '6') { // 'f6: register resides in bit 29-32 2141cb0ef41Sopenharmony_ci RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr); 2151cb0ef41Sopenharmony_ci int reg = rreinstr->R2Value(); 2161cb0ef41Sopenharmony_ci PrintDRegister(reg); 2171cb0ef41Sopenharmony_ci return 2; 2181cb0ef41Sopenharmony_ci } else if (format[1] == '4') { 2191cb0ef41Sopenharmony_ci VRR_E_Instruction* vrreinstr = reinterpret_cast<VRR_E_Instruction*>(instr); 2201cb0ef41Sopenharmony_ci int reg = vrreinstr->R4Value(); 2211cb0ef41Sopenharmony_ci PrintDRegister(reg); 2221cb0ef41Sopenharmony_ci return 2; 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci UNREACHABLE(); 2251cb0ef41Sopenharmony_ci} 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci// FormatOption takes a formatting string and interprets it based on 2281cb0ef41Sopenharmony_ci// the current instructions. The format string points to the first 2291cb0ef41Sopenharmony_ci// character of the option string (the option escape has already been 2301cb0ef41Sopenharmony_ci// consumed by the caller.) FormatOption returns the number of 2311cb0ef41Sopenharmony_ci// characters that were consumed from the formatting string. 2321cb0ef41Sopenharmony_ciint Decoder::FormatOption(Instruction* instr, const char* format) { 2331cb0ef41Sopenharmony_ci switch (format[0]) { 2341cb0ef41Sopenharmony_ci case 'o': { 2351cb0ef41Sopenharmony_ci if (instr->Bit(10) == 1) { 2361cb0ef41Sopenharmony_ci Print("o"); 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci return 1; 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci case '.': { 2411cb0ef41Sopenharmony_ci if (instr->Bit(0) == 1) { 2421cb0ef41Sopenharmony_ci Print("."); 2431cb0ef41Sopenharmony_ci } else { 2441cb0ef41Sopenharmony_ci Print(" "); // ensure consistent spacing 2451cb0ef41Sopenharmony_ci } 2461cb0ef41Sopenharmony_ci return 1; 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci case 'r': { 2491cb0ef41Sopenharmony_ci return FormatRegister(instr, format); 2501cb0ef41Sopenharmony_ci } 2511cb0ef41Sopenharmony_ci case 'f': { 2521cb0ef41Sopenharmony_ci return FormatFloatingRegister(instr, format); 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci case 'i': { // int16 2551cb0ef41Sopenharmony_ci return FormatImmediate(instr, format); 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci case 'u': { // uint16 2581cb0ef41Sopenharmony_ci int32_t value = instr->Bits(15, 0); 2591cb0ef41Sopenharmony_ci out_buffer_pos_ += 2601cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 2611cb0ef41Sopenharmony_ci return 6; 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci case 'l': { 2641cb0ef41Sopenharmony_ci // Link (LK) Bit 0 2651cb0ef41Sopenharmony_ci if (instr->Bit(0) == 1) { 2661cb0ef41Sopenharmony_ci Print("l"); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci return 1; 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci case 'a': { 2711cb0ef41Sopenharmony_ci // Absolute Address Bit 1 2721cb0ef41Sopenharmony_ci if (instr->Bit(1) == 1) { 2731cb0ef41Sopenharmony_ci Print("a"); 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci return 1; 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci case 't': { // 'target: target of branch instructions 2781cb0ef41Sopenharmony_ci // target26 or target16 2791cb0ef41Sopenharmony_ci DCHECK(STRING_STARTS_WITH(format, "target")); 2801cb0ef41Sopenharmony_ci if ((format[6] == '2') && (format[7] == '6')) { 2811cb0ef41Sopenharmony_ci int off = ((instr->Bits(25, 2)) << 8) >> 6; 2821cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF( 2831cb0ef41Sopenharmony_ci out_buffer_ + out_buffer_pos_, "%+d -> %s", off, 2841cb0ef41Sopenharmony_ci converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off)); 2851cb0ef41Sopenharmony_ci return 8; 2861cb0ef41Sopenharmony_ci } else if ((format[6] == '1') && (format[7] == '6')) { 2871cb0ef41Sopenharmony_ci int off = ((instr->Bits(15, 2)) << 18) >> 16; 2881cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF( 2891cb0ef41Sopenharmony_ci out_buffer_ + out_buffer_pos_, "%+d -> %s", off, 2901cb0ef41Sopenharmony_ci converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off)); 2911cb0ef41Sopenharmony_ci return 8; 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci break; 2941cb0ef41Sopenharmony_ci case 'm': { 2951cb0ef41Sopenharmony_ci return FormatMask(instr, format); 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci case 'd': { // ds value for offset 2991cb0ef41Sopenharmony_ci return FormatDisplacement(instr, format); 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci default: { 3021cb0ef41Sopenharmony_ci UNREACHABLE(); 3031cb0ef41Sopenharmony_ci } 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci UNREACHABLE(); 3071cb0ef41Sopenharmony_ci} 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ciint Decoder::FormatMask(Instruction* instr, const char* format) { 3101cb0ef41Sopenharmony_ci DCHECK_EQ(format[0], 'm'); 3111cb0ef41Sopenharmony_ci int32_t value = 0; 3121cb0ef41Sopenharmony_ci if ((format[1] == '1')) { // prints the mask format in bits 8-12 3131cb0ef41Sopenharmony_ci value = reinterpret_cast<RRInstruction*>(instr)->R1Value(); 3141cb0ef41Sopenharmony_ci out_buffer_pos_ += 3151cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value); 3161cb0ef41Sopenharmony_ci return 2; 3171cb0ef41Sopenharmony_ci } else if (format[1] == '2') { // mask format in bits 16-19 3181cb0ef41Sopenharmony_ci value = reinterpret_cast<RXInstruction*>(instr)->B2Value(); 3191cb0ef41Sopenharmony_ci out_buffer_pos_ += 3201cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value); 3211cb0ef41Sopenharmony_ci return 2; 3221cb0ef41Sopenharmony_ci } else if (format[1] == '3') { // mask format in bits 20-23 3231cb0ef41Sopenharmony_ci value = reinterpret_cast<RRFInstruction*>(instr)->M4Value(); 3241cb0ef41Sopenharmony_ci out_buffer_pos_ += 3251cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value); 3261cb0ef41Sopenharmony_ci return 2; 3271cb0ef41Sopenharmony_ci } else if (format[1] == '4') { // mask format in bits 32-35 3281cb0ef41Sopenharmony_ci value = reinterpret_cast<VRR_C_Instruction*>(instr)->M4Value(); 3291cb0ef41Sopenharmony_ci out_buffer_pos_ += 3301cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value); 3311cb0ef41Sopenharmony_ci return 2; 3321cb0ef41Sopenharmony_ci } else if (format[1] == '5') { // mask format in bits 28-31 3331cb0ef41Sopenharmony_ci value = reinterpret_cast<VRR_C_Instruction*>(instr)->M5Value(); 3341cb0ef41Sopenharmony_ci out_buffer_pos_ += 3351cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value); 3361cb0ef41Sopenharmony_ci return 2; 3371cb0ef41Sopenharmony_ci } else if (format[1] == '6') { // mask format in bits 24-27 3381cb0ef41Sopenharmony_ci value = reinterpret_cast<VRR_C_Instruction*>(instr)->M6Value(); 3391cb0ef41Sopenharmony_ci out_buffer_pos_ += 3401cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value); 3411cb0ef41Sopenharmony_ci return 2; 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3441cb0ef41Sopenharmony_ci return 2; 3451cb0ef41Sopenharmony_ci} 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ciint Decoder::FormatDisplacement(Instruction* instr, const char* format) { 3481cb0ef41Sopenharmony_ci DCHECK_EQ(format[0], 'd'); 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci if (format[1] == '1') { // displacement in 20-31 3511cb0ef41Sopenharmony_ci RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr); 3521cb0ef41Sopenharmony_ci uint16_t value = rsinstr->D2Value(); 3531cb0ef41Sopenharmony_ci out_buffer_pos_ += 3541cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci return 2; 3571cb0ef41Sopenharmony_ci } else if (format[1] == '2') { // displacement in 20-39 3581cb0ef41Sopenharmony_ci RXYInstruction* rxyinstr = reinterpret_cast<RXYInstruction*>(instr); 3591cb0ef41Sopenharmony_ci int32_t value = rxyinstr->D2Value(); 3601cb0ef41Sopenharmony_ci out_buffer_pos_ += 3611cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3621cb0ef41Sopenharmony_ci return 2; 3631cb0ef41Sopenharmony_ci } else if (format[1] == '4') { // SS displacement 2 36-47 3641cb0ef41Sopenharmony_ci SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr); 3651cb0ef41Sopenharmony_ci uint16_t value = ssInstr->D2Value(); 3661cb0ef41Sopenharmony_ci out_buffer_pos_ += 3671cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3681cb0ef41Sopenharmony_ci return 2; 3691cb0ef41Sopenharmony_ci } else if (format[1] == '3') { // SS displacement 1 20 - 32 3701cb0ef41Sopenharmony_ci SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr); 3711cb0ef41Sopenharmony_ci uint16_t value = ssInstr->D1Value(); 3721cb0ef41Sopenharmony_ci out_buffer_pos_ += 3731cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3741cb0ef41Sopenharmony_ci return 2; 3751cb0ef41Sopenharmony_ci } else { // s390 specific 3761cb0ef41Sopenharmony_ci int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3); 3771cb0ef41Sopenharmony_ci out_buffer_pos_ += 3781cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3791cb0ef41Sopenharmony_ci return 1; 3801cb0ef41Sopenharmony_ci } 3811cb0ef41Sopenharmony_ci} 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ciint Decoder::FormatImmediate(Instruction* instr, const char* format) { 3841cb0ef41Sopenharmony_ci DCHECK_EQ(format[0], 'i'); 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci if (format[1] == '1') { // immediate in 16-31 3871cb0ef41Sopenharmony_ci RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr); 3881cb0ef41Sopenharmony_ci int16_t value = riinstr->I2Value(); 3891cb0ef41Sopenharmony_ci out_buffer_pos_ += 3901cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3911cb0ef41Sopenharmony_ci return 2; 3921cb0ef41Sopenharmony_ci } else if (format[1] == '2') { // immediate in 16-48 3931cb0ef41Sopenharmony_ci RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr); 3941cb0ef41Sopenharmony_ci int32_t value = rilinstr->I2Value(); 3951cb0ef41Sopenharmony_ci out_buffer_pos_ += 3961cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 3971cb0ef41Sopenharmony_ci return 2; 3981cb0ef41Sopenharmony_ci } else if (format[1] == '3') { // immediate in I format 3991cb0ef41Sopenharmony_ci IInstruction* iinstr = reinterpret_cast<IInstruction*>(instr); 4001cb0ef41Sopenharmony_ci int8_t value = iinstr->IValue(); 4011cb0ef41Sopenharmony_ci out_buffer_pos_ += 4021cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4031cb0ef41Sopenharmony_ci return 2; 4041cb0ef41Sopenharmony_ci } else if (format[1] == '4') { // immediate in 16-31, but outputs as offset 4051cb0ef41Sopenharmony_ci RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr); 4061cb0ef41Sopenharmony_ci int16_t value = riinstr->I2Value() * 2; 4071cb0ef41Sopenharmony_ci if (value >= 0) 4081cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "*+"); 4091cb0ef41Sopenharmony_ci else 4101cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "*"); 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF( 4131cb0ef41Sopenharmony_ci out_buffer_ + out_buffer_pos_, "%d -> %s", value, 4141cb0ef41Sopenharmony_ci converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + value)); 4151cb0ef41Sopenharmony_ci return 2; 4161cb0ef41Sopenharmony_ci } else if (format[1] == '5') { // immediate in 16-31, but outputs as offset 4171cb0ef41Sopenharmony_ci RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr); 4181cb0ef41Sopenharmony_ci int32_t value = rilinstr->I2Value() * 2; 4191cb0ef41Sopenharmony_ci if (value >= 0) 4201cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "*+"); 4211cb0ef41Sopenharmony_ci else 4221cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "*"); 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF( 4251cb0ef41Sopenharmony_ci out_buffer_ + out_buffer_pos_, "%d -> %s", value, 4261cb0ef41Sopenharmony_ci converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + value)); 4271cb0ef41Sopenharmony_ci return 2; 4281cb0ef41Sopenharmony_ci } else if (format[1] == '6') { // unsigned immediate in 16-31 4291cb0ef41Sopenharmony_ci RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr); 4301cb0ef41Sopenharmony_ci uint16_t value = riinstr->I2UnsignedValue(); 4311cb0ef41Sopenharmony_ci out_buffer_pos_ += 4321cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4331cb0ef41Sopenharmony_ci return 2; 4341cb0ef41Sopenharmony_ci } else if (format[1] == '7') { // unsigned immediate in 16-47 4351cb0ef41Sopenharmony_ci RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr); 4361cb0ef41Sopenharmony_ci uint32_t value = rilinstr->I2UnsignedValue(); 4371cb0ef41Sopenharmony_ci out_buffer_pos_ += 4381cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4391cb0ef41Sopenharmony_ci return 2; 4401cb0ef41Sopenharmony_ci } else if (format[1] == '8') { // unsigned immediate in 8-15 4411cb0ef41Sopenharmony_ci SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr); 4421cb0ef41Sopenharmony_ci uint8_t value = ssinstr->Length(); 4431cb0ef41Sopenharmony_ci out_buffer_pos_ += 4441cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4451cb0ef41Sopenharmony_ci return 2; 4461cb0ef41Sopenharmony_ci } else if (format[1] == '9') { // unsigned immediate in 16-23 4471cb0ef41Sopenharmony_ci RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr); 4481cb0ef41Sopenharmony_ci uint8_t value = rie_instr->I3Value(); 4491cb0ef41Sopenharmony_ci out_buffer_pos_ += 4501cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4511cb0ef41Sopenharmony_ci return 2; 4521cb0ef41Sopenharmony_ci } else if (format[1] == 'a') { // unsigned immediate in 24-31 4531cb0ef41Sopenharmony_ci RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr); 4541cb0ef41Sopenharmony_ci uint8_t value = rie_instr->I4Value(); 4551cb0ef41Sopenharmony_ci out_buffer_pos_ += 4561cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4571cb0ef41Sopenharmony_ci return 2; 4581cb0ef41Sopenharmony_ci } else if (format[1] == 'b') { // unsigned immediate in 32-39 4591cb0ef41Sopenharmony_ci RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr); 4601cb0ef41Sopenharmony_ci uint8_t value = rie_instr->I5Value(); 4611cb0ef41Sopenharmony_ci out_buffer_pos_ += 4621cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4631cb0ef41Sopenharmony_ci return 2; 4641cb0ef41Sopenharmony_ci } else if (format[1] == 'c') { // signed immediate in 8-15 4651cb0ef41Sopenharmony_ci SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr); 4661cb0ef41Sopenharmony_ci int8_t value = ssinstr->Length(); 4671cb0ef41Sopenharmony_ci out_buffer_pos_ += 4681cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4691cb0ef41Sopenharmony_ci return 2; 4701cb0ef41Sopenharmony_ci } else if (format[1] == 'd') { // signed immediate in 32-47 4711cb0ef41Sopenharmony_ci SILInstruction* silinstr = reinterpret_cast<SILInstruction*>(instr); 4721cb0ef41Sopenharmony_ci int16_t value = silinstr->I2Value(); 4731cb0ef41Sopenharmony_ci out_buffer_pos_ += 4741cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value); 4751cb0ef41Sopenharmony_ci return 2; 4761cb0ef41Sopenharmony_ci } else if (format[1] == 'e') { // immediate in 16-47, but outputs as offset 4771cb0ef41Sopenharmony_ci RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr); 4781cb0ef41Sopenharmony_ci int32_t value = rilinstr->I2Value() * 2; 4791cb0ef41Sopenharmony_ci if (value >= 0) 4801cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "*+"); 4811cb0ef41Sopenharmony_ci else 4821cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF(out_buffer_ + out_buffer_pos_, "*"); 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci out_buffer_pos_ += base::SNPrintF( 4851cb0ef41Sopenharmony_ci out_buffer_ + out_buffer_pos_, "%d -> %s", value, 4861cb0ef41Sopenharmony_ci converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + value)); 4871cb0ef41Sopenharmony_ci return 2; 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci UNREACHABLE(); 4911cb0ef41Sopenharmony_ci} 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci// Format takes a formatting string for a whole instruction and prints it into 4941cb0ef41Sopenharmony_ci// the output buffer. All escaped options are handed to FormatOption to be 4951cb0ef41Sopenharmony_ci// parsed further. 4961cb0ef41Sopenharmony_civoid Decoder::Format(Instruction* instr, const char* format) { 4971cb0ef41Sopenharmony_ci char cur = *format++; 4981cb0ef41Sopenharmony_ci while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 4991cb0ef41Sopenharmony_ci if (cur == '\'') { // Single quote is used as the formatting escape. 5001cb0ef41Sopenharmony_ci format += FormatOption(instr, format); 5011cb0ef41Sopenharmony_ci } else { 5021cb0ef41Sopenharmony_ci out_buffer_[out_buffer_pos_++] = cur; 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci cur = *format++; 5051cb0ef41Sopenharmony_ci } 5061cb0ef41Sopenharmony_ci out_buffer_[out_buffer_pos_] = '\0'; 5071cb0ef41Sopenharmony_ci} 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci// The disassembler may end up decoding data inlined in the code. We do not want 5101cb0ef41Sopenharmony_ci// it to crash if the data does not resemble any known instruction. 5111cb0ef41Sopenharmony_ci#define VERIFY(condition) \ 5121cb0ef41Sopenharmony_ci if (!(condition)) { \ 5131cb0ef41Sopenharmony_ci Unknown(instr); \ 5141cb0ef41Sopenharmony_ci return; \ 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci// For currently unimplemented decodings the disassembler calls Unknown(instr) 5181cb0ef41Sopenharmony_ci// which will just print "unknown" of the instruction bits. 5191cb0ef41Sopenharmony_civoid Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); } 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci// For currently unimplemented decodings the disassembler calls 5221cb0ef41Sopenharmony_ci// UnknownFormat(instr) which will just print opcode name of the 5231cb0ef41Sopenharmony_ci// instruction bits. 5241cb0ef41Sopenharmony_civoid Decoder::UnknownFormat(Instruction* instr, const char* name) { 5251cb0ef41Sopenharmony_ci char buffer[100]; 5261cb0ef41Sopenharmony_ci snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name); 5271cb0ef41Sopenharmony_ci Format(instr, buffer); 5281cb0ef41Sopenharmony_ci} 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ci#undef VERIFY 5311cb0ef41Sopenharmony_ci#undef STRING_STARTS_WITH 5321cb0ef41Sopenharmony_ci 5331cb0ef41Sopenharmony_ci// Handles special cases of instructions; 5341cb0ef41Sopenharmony_ci// @return true if successfully decoded 5351cb0ef41Sopenharmony_cibool Decoder::DecodeSpecial(Instruction* instr) { 5361cb0ef41Sopenharmony_ci Opcode opcode = instr->S390OpcodeValue(); 5371cb0ef41Sopenharmony_ci switch (opcode) { 5381cb0ef41Sopenharmony_ci case BKPT: 5391cb0ef41Sopenharmony_ci Format(instr, "bkpt"); 5401cb0ef41Sopenharmony_ci break; 5411cb0ef41Sopenharmony_ci case DUMY: 5421cb0ef41Sopenharmony_ci Format(instr, "dumy\t'r1, 'd2 ( 'r2d, 'r3 )"); 5431cb0ef41Sopenharmony_ci break; 5441cb0ef41Sopenharmony_ci /* RR format */ 5451cb0ef41Sopenharmony_ci case LDR: 5461cb0ef41Sopenharmony_ci Format(instr, "ldr\t'f1,'f2"); 5471cb0ef41Sopenharmony_ci break; 5481cb0ef41Sopenharmony_ci case BCR: 5491cb0ef41Sopenharmony_ci Format(instr, "bcr\t'm1,'r2"); 5501cb0ef41Sopenharmony_ci break; 5511cb0ef41Sopenharmony_ci case OR: 5521cb0ef41Sopenharmony_ci Format(instr, "or\t'r1,'r2"); 5531cb0ef41Sopenharmony_ci break; 5541cb0ef41Sopenharmony_ci case CR: 5551cb0ef41Sopenharmony_ci Format(instr, "cr\t'r1,'r2"); 5561cb0ef41Sopenharmony_ci break; 5571cb0ef41Sopenharmony_ci case MR: 5581cb0ef41Sopenharmony_ci Format(instr, "mr\t'r1,'r2"); 5591cb0ef41Sopenharmony_ci break; 5601cb0ef41Sopenharmony_ci case HER_Z: 5611cb0ef41Sopenharmony_ci Format(instr, "her\t'r1,'r2"); 5621cb0ef41Sopenharmony_ci break; 5631cb0ef41Sopenharmony_ci /* RI-b format */ 5641cb0ef41Sopenharmony_ci case BRAS: 5651cb0ef41Sopenharmony_ci Format(instr, "bras\t'r1,'i1"); 5661cb0ef41Sopenharmony_ci break; 5671cb0ef41Sopenharmony_ci /* RRE format */ 5681cb0ef41Sopenharmony_ci case MDBR: 5691cb0ef41Sopenharmony_ci Format(instr, "mdbr\t'f5,'f6"); 5701cb0ef41Sopenharmony_ci break; 5711cb0ef41Sopenharmony_ci case SDBR: 5721cb0ef41Sopenharmony_ci Format(instr, "sdbr\t'f5,'f6"); 5731cb0ef41Sopenharmony_ci break; 5741cb0ef41Sopenharmony_ci case ADBR: 5751cb0ef41Sopenharmony_ci Format(instr, "adbr\t'f5,'f6"); 5761cb0ef41Sopenharmony_ci break; 5771cb0ef41Sopenharmony_ci case CDBR: 5781cb0ef41Sopenharmony_ci Format(instr, "cdbr\t'f5,'f6"); 5791cb0ef41Sopenharmony_ci break; 5801cb0ef41Sopenharmony_ci case MEEBR: 5811cb0ef41Sopenharmony_ci Format(instr, "meebr\t'f5,'f6"); 5821cb0ef41Sopenharmony_ci break; 5831cb0ef41Sopenharmony_ci case SQDBR: 5841cb0ef41Sopenharmony_ci Format(instr, "sqdbr\t'f5,'f6"); 5851cb0ef41Sopenharmony_ci break; 5861cb0ef41Sopenharmony_ci case SQEBR: 5871cb0ef41Sopenharmony_ci Format(instr, "sqebr\t'f5,'f6"); 5881cb0ef41Sopenharmony_ci break; 5891cb0ef41Sopenharmony_ci case LCDBR: 5901cb0ef41Sopenharmony_ci Format(instr, "lcdbr\t'f5,'f6"); 5911cb0ef41Sopenharmony_ci break; 5921cb0ef41Sopenharmony_ci case LCEBR: 5931cb0ef41Sopenharmony_ci Format(instr, "lcebr\t'f5,'f6"); 5941cb0ef41Sopenharmony_ci break; 5951cb0ef41Sopenharmony_ci case LTEBR: 5961cb0ef41Sopenharmony_ci Format(instr, "ltebr\t'f5,'f6"); 5971cb0ef41Sopenharmony_ci break; 5981cb0ef41Sopenharmony_ci case LDEBR: 5991cb0ef41Sopenharmony_ci Format(instr, "ldebr\t'f5,'f6"); 6001cb0ef41Sopenharmony_ci break; 6011cb0ef41Sopenharmony_ci case CEBR: 6021cb0ef41Sopenharmony_ci Format(instr, "cebr\t'f5,'f6"); 6031cb0ef41Sopenharmony_ci break; 6041cb0ef41Sopenharmony_ci case AEBR: 6051cb0ef41Sopenharmony_ci Format(instr, "aebr\t'f5,'f6"); 6061cb0ef41Sopenharmony_ci break; 6071cb0ef41Sopenharmony_ci case SEBR: 6081cb0ef41Sopenharmony_ci Format(instr, "sebr\t'f5,'f6"); 6091cb0ef41Sopenharmony_ci break; 6101cb0ef41Sopenharmony_ci case DEBR: 6111cb0ef41Sopenharmony_ci Format(instr, "debr\t'f5,'f6"); 6121cb0ef41Sopenharmony_ci break; 6131cb0ef41Sopenharmony_ci case LTDBR: 6141cb0ef41Sopenharmony_ci Format(instr, "ltdbr\t'f5,'f6"); 6151cb0ef41Sopenharmony_ci break; 6161cb0ef41Sopenharmony_ci case LDGR: 6171cb0ef41Sopenharmony_ci Format(instr, "ldgr\t'f5,'f6"); 6181cb0ef41Sopenharmony_ci break; 6191cb0ef41Sopenharmony_ci case DDBR: 6201cb0ef41Sopenharmony_ci Format(instr, "ddbr\t'f5,'f6"); 6211cb0ef41Sopenharmony_ci break; 6221cb0ef41Sopenharmony_ci case LZDR: 6231cb0ef41Sopenharmony_ci Format(instr, "lzdr\t'f5"); 6241cb0ef41Sopenharmony_ci break; 6251cb0ef41Sopenharmony_ci /* RRF-e format */ 6261cb0ef41Sopenharmony_ci case FIEBRA: 6271cb0ef41Sopenharmony_ci Format(instr, "fiebra\t'f5,'m2,'f6,'m3"); 6281cb0ef41Sopenharmony_ci break; 6291cb0ef41Sopenharmony_ci case FIDBRA: 6301cb0ef41Sopenharmony_ci Format(instr, "fidbra\t'f5,'m2,'f6,'m3"); 6311cb0ef41Sopenharmony_ci break; 6321cb0ef41Sopenharmony_ci /* RX-a format */ 6331cb0ef41Sopenharmony_ci case IC_z: 6341cb0ef41Sopenharmony_ci Format(instr, "ic\t'r1,'d1('r2d,'r3)"); 6351cb0ef41Sopenharmony_ci break; 6361cb0ef41Sopenharmony_ci case AL: 6371cb0ef41Sopenharmony_ci Format(instr, "al\t'r1,'d1('r2d,'r3)"); 6381cb0ef41Sopenharmony_ci break; 6391cb0ef41Sopenharmony_ci case LE: 6401cb0ef41Sopenharmony_ci Format(instr, "le\t'f1,'d1('r2d,'r3)"); 6411cb0ef41Sopenharmony_ci break; 6421cb0ef41Sopenharmony_ci case LD: 6431cb0ef41Sopenharmony_ci Format(instr, "ld\t'f1,'d1('r2d,'r3)"); 6441cb0ef41Sopenharmony_ci break; 6451cb0ef41Sopenharmony_ci case STE: 6461cb0ef41Sopenharmony_ci Format(instr, "ste\t'f1,'d1('r2d,'r3)"); 6471cb0ef41Sopenharmony_ci break; 6481cb0ef41Sopenharmony_ci case STD: 6491cb0ef41Sopenharmony_ci Format(instr, "std\t'f1,'d1('r2d,'r3)"); 6501cb0ef41Sopenharmony_ci break; 6511cb0ef41Sopenharmony_ci /* S format */ 6521cb0ef41Sopenharmony_ci // TRAP4 is used in calling to native function. it will not be generated 6531cb0ef41Sopenharmony_ci // in native code. 6541cb0ef41Sopenharmony_ci case TRAP4: 6551cb0ef41Sopenharmony_ci Format(instr, "trap4"); 6561cb0ef41Sopenharmony_ci break; 6571cb0ef41Sopenharmony_ci /* RIL-a format */ 6581cb0ef41Sopenharmony_ci case CFI: 6591cb0ef41Sopenharmony_ci Format(instr, "cfi\t'r1,'i2"); 6601cb0ef41Sopenharmony_ci break; 6611cb0ef41Sopenharmony_ci case CGFI: 6621cb0ef41Sopenharmony_ci Format(instr, "cgfi\t'r1,'i2"); 6631cb0ef41Sopenharmony_ci break; 6641cb0ef41Sopenharmony_ci case AFI: 6651cb0ef41Sopenharmony_ci Format(instr, "afi\t'r1,'i2"); 6661cb0ef41Sopenharmony_ci break; 6671cb0ef41Sopenharmony_ci case AGFI: 6681cb0ef41Sopenharmony_ci Format(instr, "agfi\t'r1,'i2"); 6691cb0ef41Sopenharmony_ci break; 6701cb0ef41Sopenharmony_ci case MSFI: 6711cb0ef41Sopenharmony_ci Format(instr, "msfi\t'r1,'i2"); 6721cb0ef41Sopenharmony_ci break; 6731cb0ef41Sopenharmony_ci case MSGFI: 6741cb0ef41Sopenharmony_ci Format(instr, "msgfi\t'r1,'i2"); 6751cb0ef41Sopenharmony_ci break; 6761cb0ef41Sopenharmony_ci case ALSIH: 6771cb0ef41Sopenharmony_ci Format(instr, "alsih\t'r1,'i2"); 6781cb0ef41Sopenharmony_ci break; 6791cb0ef41Sopenharmony_ci case ALSIHN: 6801cb0ef41Sopenharmony_ci Format(instr, "alsihn\t'r1,'i2"); 6811cb0ef41Sopenharmony_ci break; 6821cb0ef41Sopenharmony_ci case CIH: 6831cb0ef41Sopenharmony_ci Format(instr, "cih\t'r1,'i2"); 6841cb0ef41Sopenharmony_ci break; 6851cb0ef41Sopenharmony_ci case AIH: 6861cb0ef41Sopenharmony_ci Format(instr, "aih\t'r1,'i2"); 6871cb0ef41Sopenharmony_ci break; 6881cb0ef41Sopenharmony_ci case LGFI: 6891cb0ef41Sopenharmony_ci Format(instr, "lgfi\t'r1,'i2"); 6901cb0ef41Sopenharmony_ci break; 6911cb0ef41Sopenharmony_ci /* SIY format */ 6921cb0ef41Sopenharmony_ci case ASI: 6931cb0ef41Sopenharmony_ci Format(instr, "asi\t'd2('r3),'ic"); 6941cb0ef41Sopenharmony_ci break; 6951cb0ef41Sopenharmony_ci case AGSI: 6961cb0ef41Sopenharmony_ci Format(instr, "agsi\t'd2('r3),'ic"); 6971cb0ef41Sopenharmony_ci break; 6981cb0ef41Sopenharmony_ci /* RXY-a format */ 6991cb0ef41Sopenharmony_ci case LT: 7001cb0ef41Sopenharmony_ci Format(instr, "lt\t'r1,'d2('r2d,'r3)"); 7011cb0ef41Sopenharmony_ci break; 7021cb0ef41Sopenharmony_ci case LDY: 7031cb0ef41Sopenharmony_ci Format(instr, "ldy\t'f1,'d2('r2d,'r3)"); 7041cb0ef41Sopenharmony_ci break; 7051cb0ef41Sopenharmony_ci case LEY: 7061cb0ef41Sopenharmony_ci Format(instr, "ley\t'f1,'d2('r2d,'r3)"); 7071cb0ef41Sopenharmony_ci break; 7081cb0ef41Sopenharmony_ci case STDY: 7091cb0ef41Sopenharmony_ci Format(instr, "stdy\t'f1,'d2('r2d,'r3)"); 7101cb0ef41Sopenharmony_ci break; 7111cb0ef41Sopenharmony_ci case STEY: 7121cb0ef41Sopenharmony_ci Format(instr, "stey\t'f1,'d2('r2d,'r3)"); 7131cb0ef41Sopenharmony_ci break; 7141cb0ef41Sopenharmony_ci /* RXE format */ 7151cb0ef41Sopenharmony_ci case LDEB: 7161cb0ef41Sopenharmony_ci Format(instr, "ldeb\t'f1,'d2('r2d,'r3)"); 7171cb0ef41Sopenharmony_ci break; 7181cb0ef41Sopenharmony_ci default: 7191cb0ef41Sopenharmony_ci return false; 7201cb0ef41Sopenharmony_ci } 7211cb0ef41Sopenharmony_ci return true; 7221cb0ef41Sopenharmony_ci} 7231cb0ef41Sopenharmony_ci 7241cb0ef41Sopenharmony_ci// Handles common cases of instructions; 7251cb0ef41Sopenharmony_ci// @return true if successfully decoded 7261cb0ef41Sopenharmony_cibool Decoder::DecodeGeneric(Instruction* instr) { 7271cb0ef41Sopenharmony_ci Opcode opcode = instr->S390OpcodeValue(); 7281cb0ef41Sopenharmony_ci switch (opcode) { 7291cb0ef41Sopenharmony_ci /* 2 bytes */ 7301cb0ef41Sopenharmony_ci#define DECODE_RR_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7311cb0ef41Sopenharmony_ci case opcode_name: \ 7321cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2"); \ 7331cb0ef41Sopenharmony_ci break; 7341cb0ef41Sopenharmony_ci S390_RR_OPCODE_LIST(DECODE_RR_INSTRUCTIONS) 7351cb0ef41Sopenharmony_ci#undef DECODE_RR_INSTRUCTIONS 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci /* 4 bytes */ 7381cb0ef41Sopenharmony_ci#define DECODE_RS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7391cb0ef41Sopenharmony_ci case opcode_name: \ 7401cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2,'d1('r3)"); \ 7411cb0ef41Sopenharmony_ci break; 7421cb0ef41Sopenharmony_ci S390_RS_A_OPCODE_LIST(DECODE_RS_A_INSTRUCTIONS) 7431cb0ef41Sopenharmony_ci#undef DECODE_RS_A_INSTRUCTIONS 7441cb0ef41Sopenharmony_ci 7451cb0ef41Sopenharmony_ci#define DECODE_RSI_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7461cb0ef41Sopenharmony_ci case opcode_name: \ 7471cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2,'i4"); \ 7481cb0ef41Sopenharmony_ci break; 7491cb0ef41Sopenharmony_ci S390_RSI_OPCODE_LIST(DECODE_RSI_INSTRUCTIONS) 7501cb0ef41Sopenharmony_ci#undef DECODE_RSI_INSTRUCTIONS 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci#define DECODE_RI_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7531cb0ef41Sopenharmony_ci case opcode_name: \ 7541cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'i1"); \ 7551cb0ef41Sopenharmony_ci break; 7561cb0ef41Sopenharmony_ci S390_RI_A_OPCODE_LIST(DECODE_RI_A_INSTRUCTIONS) 7571cb0ef41Sopenharmony_ci#undef DECODE_RI_A_INSTRUCTIONS 7581cb0ef41Sopenharmony_ci 7591cb0ef41Sopenharmony_ci#define DECODE_RI_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7601cb0ef41Sopenharmony_ci case opcode_name: \ 7611cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'i4"); \ 7621cb0ef41Sopenharmony_ci break; 7631cb0ef41Sopenharmony_ci S390_RI_B_OPCODE_LIST(DECODE_RI_B_INSTRUCTIONS) 7641cb0ef41Sopenharmony_ci#undef DECODE_RI_B_INSTRUCTIONS 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci#define DECODE_RI_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7671cb0ef41Sopenharmony_ci case opcode_name: \ 7681cb0ef41Sopenharmony_ci Format(instr, #name "\t'm1,'i4"); \ 7691cb0ef41Sopenharmony_ci break; 7701cb0ef41Sopenharmony_ci S390_RI_C_OPCODE_LIST(DECODE_RI_C_INSTRUCTIONS) 7711cb0ef41Sopenharmony_ci#undef DECODE_RI_C_INSTRUCTIONS 7721cb0ef41Sopenharmony_ci 7731cb0ef41Sopenharmony_ci#define DECODE_RRE_INSTRUCTIONS(name, opcode_name, opcode_value) \ 7741cb0ef41Sopenharmony_ci case opcode_name: \ 7751cb0ef41Sopenharmony_ci Format(instr, #name "\t'r5,'r6"); \ 7761cb0ef41Sopenharmony_ci break; 7771cb0ef41Sopenharmony_ci S390_RRE_OPCODE_LIST(DECODE_RRE_INSTRUCTIONS) 7781cb0ef41Sopenharmony_ci#undef DECODE_RRE_INSTRUCTIONS 7791cb0ef41Sopenharmony_ci 7801cb0ef41Sopenharmony_ci#define DECODE_RRF_A_INSTRUCTIONS(name, opcode_name, opcode_val) \ 7811cb0ef41Sopenharmony_ci case opcode_name: \ 7821cb0ef41Sopenharmony_ci Format(instr, #name "\t'r5,'r6,'r3"); \ 7831cb0ef41Sopenharmony_ci break; 7841cb0ef41Sopenharmony_ci S390_RRF_A_OPCODE_LIST(DECODE_RRF_A_INSTRUCTIONS) 7851cb0ef41Sopenharmony_ci#undef DECODE_RRF_A_INSTRUCTIONS 7861cb0ef41Sopenharmony_ci 7871cb0ef41Sopenharmony_ci#define DECODE_RRF_C_INSTRUCTIONS(name, opcode_name, opcode_val) \ 7881cb0ef41Sopenharmony_ci case opcode_name: \ 7891cb0ef41Sopenharmony_ci Format(instr, #name "\t'r5,'r6,'m2"); \ 7901cb0ef41Sopenharmony_ci break; 7911cb0ef41Sopenharmony_ci S390_RRF_C_OPCODE_LIST(DECODE_RRF_C_INSTRUCTIONS) 7921cb0ef41Sopenharmony_ci#undef DECODE_RRF_C_INSTRUCTIONS 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci#define DECODE_RRF_E_INSTRUCTIONS(name, opcode_name, opcode_val) \ 7951cb0ef41Sopenharmony_ci case opcode_name: \ 7961cb0ef41Sopenharmony_ci Format(instr, #name "\t'r5,'m2,'f6"); \ 7971cb0ef41Sopenharmony_ci break; 7981cb0ef41Sopenharmony_ci S390_RRF_E_OPCODE_LIST(DECODE_RRF_E_INSTRUCTIONS) 7991cb0ef41Sopenharmony_ci#undef DECODE_RRF_E_INSTRUCTIONS 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ci#define DECODE_RX_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8021cb0ef41Sopenharmony_ci case opcode_name: \ 8031cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'d1('r2d,'r3)"); \ 8041cb0ef41Sopenharmony_ci break; 8051cb0ef41Sopenharmony_ci S390_RX_A_OPCODE_LIST(DECODE_RX_A_INSTRUCTIONS) 8061cb0ef41Sopenharmony_ci#undef DECODE_RX_A_INSTRUCTIONS 8071cb0ef41Sopenharmony_ci 8081cb0ef41Sopenharmony_ci#define DECODE_RX_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8091cb0ef41Sopenharmony_ci case opcode_name: \ 8101cb0ef41Sopenharmony_ci Format(instr, #name "\t'm1,'d1('r2d,'r3)"); \ 8111cb0ef41Sopenharmony_ci break; 8121cb0ef41Sopenharmony_ci S390_RX_B_OPCODE_LIST(DECODE_RX_B_INSTRUCTIONS) 8131cb0ef41Sopenharmony_ci#undef DECODE_RX_B_INSTRUCTIONS 8141cb0ef41Sopenharmony_ci 8151cb0ef41Sopenharmony_ci#define DECODE_RRD_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8161cb0ef41Sopenharmony_ci case opcode_name: \ 8171cb0ef41Sopenharmony_ci Format(instr, #name "\t'f3,'f5,'f6"); \ 8181cb0ef41Sopenharmony_ci break; 8191cb0ef41Sopenharmony_ci S390_RRD_OPCODE_LIST(DECODE_RRD_INSTRUCTIONS) 8201cb0ef41Sopenharmony_ci#undef DECODE_RRD_INSTRUCTIONS 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci#define DECODE_SI_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8231cb0ef41Sopenharmony_ci case opcode_name: \ 8241cb0ef41Sopenharmony_ci Format(instr, #name "\t'd1('r3),'i8"); \ 8251cb0ef41Sopenharmony_ci break; 8261cb0ef41Sopenharmony_ci S390_SI_OPCODE_LIST(DECODE_SI_INSTRUCTIONS) 8271cb0ef41Sopenharmony_ci#undef DECODE_SI_INSTRUCTIONS 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci /* 6 bytes */ 8301cb0ef41Sopenharmony_ci#define DECODE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8311cb0ef41Sopenharmony_ci case opcode_name: \ 8321cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'f2,'m4,'m5,'m6"); \ 8331cb0ef41Sopenharmony_ci break; 8341cb0ef41Sopenharmony_ci S390_VRR_A_OPCODE_LIST(DECODE_VRR_A_INSTRUCTIONS) 8351cb0ef41Sopenharmony_ci#undef DECODE_VRR_A_INSTRUCTIONS 8361cb0ef41Sopenharmony_ci 8371cb0ef41Sopenharmony_ci#define DECODE_VRR_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8381cb0ef41Sopenharmony_ci case opcode_name: \ 8391cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'f2,'f3,'m4,'m6"); \ 8401cb0ef41Sopenharmony_ci break; 8411cb0ef41Sopenharmony_ci S390_VRR_B_OPCODE_LIST(DECODE_VRR_B_INSTRUCTIONS) 8421cb0ef41Sopenharmony_ci#undef DECODE_VRR_B_INSTRUCTIONS 8431cb0ef41Sopenharmony_ci 8441cb0ef41Sopenharmony_ci#define DECODE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8451cb0ef41Sopenharmony_ci case opcode_name: \ 8461cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'f2,'f3,'m4"); \ 8471cb0ef41Sopenharmony_ci break; 8481cb0ef41Sopenharmony_ci S390_VRR_C_OPCODE_LIST(DECODE_VRR_C_INSTRUCTIONS) 8491cb0ef41Sopenharmony_ci#undef DECODE_VRR_C_INSTRUCTIONS 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci#define DECODE_VRR_E_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8521cb0ef41Sopenharmony_ci case opcode_name: \ 8531cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'f2,'f3,'f4,'m5,'m3"); \ 8541cb0ef41Sopenharmony_ci break; 8551cb0ef41Sopenharmony_ci S390_VRR_E_OPCODE_LIST(DECODE_VRR_E_INSTRUCTIONS) 8561cb0ef41Sopenharmony_ci#undef DECODE_VRR_E_INSTRUCTIONS 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci#define DECODE_VRR_F_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8591cb0ef41Sopenharmony_ci case opcode_name: \ 8601cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'r1,'r2"); \ 8611cb0ef41Sopenharmony_ci break; 8621cb0ef41Sopenharmony_ci S390_VRR_F_OPCODE_LIST(DECODE_VRR_F_INSTRUCTIONS) 8631cb0ef41Sopenharmony_ci#undef DECODE_VRR_F_INSTRUCTIONS 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_ci#define DECODE_VRX_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8661cb0ef41Sopenharmony_ci case opcode_name: \ 8671cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'d1('r2d,'r3),'m4"); \ 8681cb0ef41Sopenharmony_ci break; 8691cb0ef41Sopenharmony_ci S390_VRX_OPCODE_LIST(DECODE_VRX_INSTRUCTIONS) 8701cb0ef41Sopenharmony_ci#undef DECODE_VRX_INSTRUCTIONS 8711cb0ef41Sopenharmony_ci 8721cb0ef41Sopenharmony_ci#define DECODE_VRS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8731cb0ef41Sopenharmony_ci case opcode_name: \ 8741cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'f2,'d1('r3),'m4"); \ 8751cb0ef41Sopenharmony_ci break; 8761cb0ef41Sopenharmony_ci S390_VRS_A_OPCODE_LIST(DECODE_VRS_A_INSTRUCTIONS) 8771cb0ef41Sopenharmony_ci#undef DECODE_VRS_A_INSTRUCTIONS 8781cb0ef41Sopenharmony_ci 8791cb0ef41Sopenharmony_ci#define DECODE_VRS_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8801cb0ef41Sopenharmony_ci case opcode_name: \ 8811cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'r2,'d1('r3),'m4"); \ 8821cb0ef41Sopenharmony_ci break; 8831cb0ef41Sopenharmony_ci S390_VRS_B_OPCODE_LIST(DECODE_VRS_B_INSTRUCTIONS) 8841cb0ef41Sopenharmony_ci#undef DECODE_VRS_B_INSTRUCTIONS 8851cb0ef41Sopenharmony_ci 8861cb0ef41Sopenharmony_ci#define DECODE_VRS_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8871cb0ef41Sopenharmony_ci case opcode_name: \ 8881cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'f2,'d1('r3),'m4"); \ 8891cb0ef41Sopenharmony_ci break; 8901cb0ef41Sopenharmony_ci S390_VRS_C_OPCODE_LIST(DECODE_VRS_C_INSTRUCTIONS) 8911cb0ef41Sopenharmony_ci#undef DECODE_VRS_C_INSTRUCTIONS 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ci#define DECODE_VRI_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 8941cb0ef41Sopenharmony_ci case opcode_name: \ 8951cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'i1,'m4"); \ 8961cb0ef41Sopenharmony_ci break; 8971cb0ef41Sopenharmony_ci S390_VRI_A_OPCODE_LIST(DECODE_VRI_A_INSTRUCTIONS) 8981cb0ef41Sopenharmony_ci#undef DECODE_VRI_A_INSTRUCTIONS 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci#define DECODE_VRI_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9011cb0ef41Sopenharmony_ci case opcode_name: \ 9021cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'f2,'i1,'m4"); \ 9031cb0ef41Sopenharmony_ci break; 9041cb0ef41Sopenharmony_ci S390_VRI_C_OPCODE_LIST(DECODE_VRI_C_INSTRUCTIONS) 9051cb0ef41Sopenharmony_ci#undef DECODE_VRI_C_INSTRUCTIONS 9061cb0ef41Sopenharmony_ci 9071cb0ef41Sopenharmony_ci#define DECODE_RIL_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9081cb0ef41Sopenharmony_ci case opcode_name: \ 9091cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'i7"); \ 9101cb0ef41Sopenharmony_ci break; 9111cb0ef41Sopenharmony_ci S390_RIL_A_OPCODE_LIST(DECODE_RIL_A_INSTRUCTIONS) 9121cb0ef41Sopenharmony_ci#undef DECODE_RIL_A_INSTRUCTIONS 9131cb0ef41Sopenharmony_ci 9141cb0ef41Sopenharmony_ci#define DECODE_RIL_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9151cb0ef41Sopenharmony_ci case opcode_name: \ 9161cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'ie"); \ 9171cb0ef41Sopenharmony_ci break; 9181cb0ef41Sopenharmony_ci S390_RIL_B_OPCODE_LIST(DECODE_RIL_B_INSTRUCTIONS) 9191cb0ef41Sopenharmony_ci#undef DECODE_RIL_B_INSTRUCTIONS 9201cb0ef41Sopenharmony_ci 9211cb0ef41Sopenharmony_ci#define DECODE_RIL_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9221cb0ef41Sopenharmony_ci case opcode_name: \ 9231cb0ef41Sopenharmony_ci Format(instr, #name "\t'm1,'ie"); \ 9241cb0ef41Sopenharmony_ci break; 9251cb0ef41Sopenharmony_ci S390_RIL_C_OPCODE_LIST(DECODE_RIL_C_INSTRUCTIONS) 9261cb0ef41Sopenharmony_ci#undef DECODE_RIL_C_INSTRUCTIONS 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci#define DECODE_SIY_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9291cb0ef41Sopenharmony_ci case opcode_name: \ 9301cb0ef41Sopenharmony_ci Format(instr, #name "\t'd2('r3),'i8"); \ 9311cb0ef41Sopenharmony_ci break; 9321cb0ef41Sopenharmony_ci S390_SIY_OPCODE_LIST(DECODE_SIY_INSTRUCTIONS) 9331cb0ef41Sopenharmony_ci#undef DECODE_SIY_INSTRUCTIONS 9341cb0ef41Sopenharmony_ci 9351cb0ef41Sopenharmony_ci#define DECODE_RIE_D_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9361cb0ef41Sopenharmony_ci case opcode_name: \ 9371cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2,'i1"); \ 9381cb0ef41Sopenharmony_ci break; 9391cb0ef41Sopenharmony_ci S390_RIE_D_OPCODE_LIST(DECODE_RIE_D_INSTRUCTIONS) 9401cb0ef41Sopenharmony_ci#undef DECODE_RIE_D_INSTRUCTIONS 9411cb0ef41Sopenharmony_ci 9421cb0ef41Sopenharmony_ci#define DECODE_RIE_E_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9431cb0ef41Sopenharmony_ci case opcode_name: \ 9441cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2,'i4"); \ 9451cb0ef41Sopenharmony_ci break; 9461cb0ef41Sopenharmony_ci S390_RIE_E_OPCODE_LIST(DECODE_RIE_E_INSTRUCTIONS) 9471cb0ef41Sopenharmony_ci#undef DECODE_RIE_E_INSTRUCTIONS 9481cb0ef41Sopenharmony_ci 9491cb0ef41Sopenharmony_ci#define DECODE_RIE_F_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9501cb0ef41Sopenharmony_ci case opcode_name: \ 9511cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2,'i9,'ia,'ib"); \ 9521cb0ef41Sopenharmony_ci break; 9531cb0ef41Sopenharmony_ci S390_RIE_F_OPCODE_LIST(DECODE_RIE_F_INSTRUCTIONS) 9541cb0ef41Sopenharmony_ci#undef DECODE_RIE_F_INSTRUCTIONS 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_ci#define DECODE_RSY_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9571cb0ef41Sopenharmony_ci case opcode_name: \ 9581cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'r2,'d2('r3)"); \ 9591cb0ef41Sopenharmony_ci break; 9601cb0ef41Sopenharmony_ci S390_RSY_A_OPCODE_LIST(DECODE_RSY_A_INSTRUCTIONS) 9611cb0ef41Sopenharmony_ci#undef DECODE_RSY_A_INSTRUCTIONS 9621cb0ef41Sopenharmony_ci 9631cb0ef41Sopenharmony_ci#define DECODE_RSY_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9641cb0ef41Sopenharmony_ci case opcode_name: \ 9651cb0ef41Sopenharmony_ci Format(instr, #name "\t'm2,'r1,'d2('r3)"); \ 9661cb0ef41Sopenharmony_ci break; 9671cb0ef41Sopenharmony_ci S390_RSY_B_OPCODE_LIST(DECODE_RSY_B_INSTRUCTIONS) 9681cb0ef41Sopenharmony_ci#undef DECODE_RSY_B_INSTRUCTIONS 9691cb0ef41Sopenharmony_ci 9701cb0ef41Sopenharmony_ci#define DECODE_RXY_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9711cb0ef41Sopenharmony_ci case opcode_name: \ 9721cb0ef41Sopenharmony_ci Format(instr, #name "\t'r1,'d2('r2d,'r3)"); \ 9731cb0ef41Sopenharmony_ci break; 9741cb0ef41Sopenharmony_ci S390_RXY_A_OPCODE_LIST(DECODE_RXY_A_INSTRUCTIONS) 9751cb0ef41Sopenharmony_ci#undef DECODE_RXY_A_INSTRUCTIONS 9761cb0ef41Sopenharmony_ci 9771cb0ef41Sopenharmony_ci#define DECODE_RXY_B_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9781cb0ef41Sopenharmony_ci case opcode_name: \ 9791cb0ef41Sopenharmony_ci Format(instr, #name "\t'm1,'d2('r2d,'r3)"); \ 9801cb0ef41Sopenharmony_ci break; 9811cb0ef41Sopenharmony_ci S390_RXY_B_OPCODE_LIST(DECODE_RXY_B_INSTRUCTIONS) 9821cb0ef41Sopenharmony_ci#undef DECODE_RXY_B_INSTRUCTIONS 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_ci#define DECODE_RXE_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9851cb0ef41Sopenharmony_ci case opcode_name: \ 9861cb0ef41Sopenharmony_ci Format(instr, #name "\t'f1,'d1('r2d, 'r3)"); \ 9871cb0ef41Sopenharmony_ci break; 9881cb0ef41Sopenharmony_ci S390_RXE_OPCODE_LIST(DECODE_RXE_INSTRUCTIONS) 9891cb0ef41Sopenharmony_ci#undef DECODE_RXE_INSTRUCTIONS 9901cb0ef41Sopenharmony_ci 9911cb0ef41Sopenharmony_ci#define DECODE_SIL_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9921cb0ef41Sopenharmony_ci case opcode_name: \ 9931cb0ef41Sopenharmony_ci Format(instr, #name "\t'd3('r3),'id"); \ 9941cb0ef41Sopenharmony_ci break; 9951cb0ef41Sopenharmony_ci S390_SIL_OPCODE_LIST(DECODE_SIL_INSTRUCTIONS) 9961cb0ef41Sopenharmony_ci#undef DECODE_SIL_INSTRUCTIONS 9971cb0ef41Sopenharmony_ci 9981cb0ef41Sopenharmony_ci#define DECODE_SS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 9991cb0ef41Sopenharmony_ci case opcode_name: \ 10001cb0ef41Sopenharmony_ci Format(instr, #name "\t'd3('i8,'r3),'d4('r7)"); \ 10011cb0ef41Sopenharmony_ci break; 10021cb0ef41Sopenharmony_ci S390_SS_A_OPCODE_LIST(DECODE_SS_A_INSTRUCTIONS) 10031cb0ef41Sopenharmony_ci#undef DECODE_SS_A_INSTRUCTIONS 10041cb0ef41Sopenharmony_ci 10051cb0ef41Sopenharmony_ci default: 10061cb0ef41Sopenharmony_ci return false; 10071cb0ef41Sopenharmony_ci } 10081cb0ef41Sopenharmony_ci return true; 10091cb0ef41Sopenharmony_ci} 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_ci// Disassemble the instruction at *instr_ptr into the output buffer. 10121cb0ef41Sopenharmony_ciint Decoder::InstructionDecode(byte* instr_ptr) { 10131cb0ef41Sopenharmony_ci Instruction* instr = Instruction::At(instr_ptr); 10141cb0ef41Sopenharmony_ci int instrLength = instr->InstructionLength(); 10151cb0ef41Sopenharmony_ci 10161cb0ef41Sopenharmony_ci // Print the Instruction bits. 10171cb0ef41Sopenharmony_ci if (instrLength == 2) { 10181cb0ef41Sopenharmony_ci out_buffer_pos_ += 10191cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%04x ", 10201cb0ef41Sopenharmony_ci instr->InstructionBits<TwoByteInstr>()); 10211cb0ef41Sopenharmony_ci } else if (instrLength == 4) { 10221cb0ef41Sopenharmony_ci out_buffer_pos_ += 10231cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ", 10241cb0ef41Sopenharmony_ci instr->InstructionBits<FourByteInstr>()); 10251cb0ef41Sopenharmony_ci } else { 10261cb0ef41Sopenharmony_ci out_buffer_pos_ += 10271cb0ef41Sopenharmony_ci base::SNPrintF(out_buffer_ + out_buffer_pos_, "%012" PRIx64 " ", 10281cb0ef41Sopenharmony_ci instr->InstructionBits<SixByteInstr>()); 10291cb0ef41Sopenharmony_ci } 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_ci bool decoded = DecodeSpecial(instr); 10321cb0ef41Sopenharmony_ci if (!decoded) decoded = DecodeGeneric(instr); 10331cb0ef41Sopenharmony_ci if (!decoded) Unknown(instr); 10341cb0ef41Sopenharmony_ci return instrLength; 10351cb0ef41Sopenharmony_ci} 10361cb0ef41Sopenharmony_ci 10371cb0ef41Sopenharmony_ci} // namespace internal 10381cb0ef41Sopenharmony_ci} // namespace v8 10391cb0ef41Sopenharmony_ci 10401cb0ef41Sopenharmony_ci//------------------------------------------------------------------------------ 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_cinamespace disasm { 10431cb0ef41Sopenharmony_ci 10441cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfAddress(byte* addr) const { 10451cb0ef41Sopenharmony_ci v8::base::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr)); 10461cb0ef41Sopenharmony_ci return tmp_buffer_.begin(); 10471cb0ef41Sopenharmony_ci} 10481cb0ef41Sopenharmony_ci 10491cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfConstant(byte* addr) const { 10501cb0ef41Sopenharmony_ci return NameOfAddress(addr); 10511cb0ef41Sopenharmony_ci} 10521cb0ef41Sopenharmony_ci 10531cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfCPURegister(int reg) const { 10541cb0ef41Sopenharmony_ci return RegisterName(i::Register::from_code(reg)); 10551cb0ef41Sopenharmony_ci} 10561cb0ef41Sopenharmony_ci 10571cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfByteCPURegister(int reg) const { 10581cb0ef41Sopenharmony_ci UNREACHABLE(); // S390 does not have the concept of a byte register 10591cb0ef41Sopenharmony_ci} 10601cb0ef41Sopenharmony_ci 10611cb0ef41Sopenharmony_ciconst char* NameConverter::NameOfXMMRegister(int reg) const { 10621cb0ef41Sopenharmony_ci // S390 does not have XMM register 10631cb0ef41Sopenharmony_ci // TODO(joransiu): Consider update this for Vector Regs 10641cb0ef41Sopenharmony_ci UNREACHABLE(); 10651cb0ef41Sopenharmony_ci} 10661cb0ef41Sopenharmony_ci 10671cb0ef41Sopenharmony_ciconst char* NameConverter::NameInCode(byte* addr) const { 10681cb0ef41Sopenharmony_ci // The default name converter is called for unknown code. So we will not try 10691cb0ef41Sopenharmony_ci // to access any memory. 10701cb0ef41Sopenharmony_ci return ""; 10711cb0ef41Sopenharmony_ci} 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ci//------------------------------------------------------------------------------ 10741cb0ef41Sopenharmony_ci 10751cb0ef41Sopenharmony_ciint Disassembler::InstructionDecode(v8::base::Vector<char> buffer, 10761cb0ef41Sopenharmony_ci byte* instruction) { 10771cb0ef41Sopenharmony_ci v8::internal::Decoder d(converter_, buffer); 10781cb0ef41Sopenharmony_ci return d.InstructionDecode(instruction); 10791cb0ef41Sopenharmony_ci} 10801cb0ef41Sopenharmony_ci 10811cb0ef41Sopenharmony_ci// The S390 assembler does not currently use constant pools. 10821cb0ef41Sopenharmony_ciint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } 10831cb0ef41Sopenharmony_ci 10841cb0ef41Sopenharmony_civoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end, 10851cb0ef41Sopenharmony_ci UnimplementedOpcodeAction unimplemented_action) { 10861cb0ef41Sopenharmony_ci NameConverter converter; 10871cb0ef41Sopenharmony_ci Disassembler d(converter, unimplemented_action); 10881cb0ef41Sopenharmony_ci for (byte* pc = begin; pc < end;) { 10891cb0ef41Sopenharmony_ci v8::base::EmbeddedVector<char, 128> buffer; 10901cb0ef41Sopenharmony_ci buffer[0] = '\0'; 10911cb0ef41Sopenharmony_ci byte* prev_pc = pc; 10921cb0ef41Sopenharmony_ci pc += d.InstructionDecode(buffer, pc); 10931cb0ef41Sopenharmony_ci v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc), 10941cb0ef41Sopenharmony_ci *reinterpret_cast<int32_t*>(prev_pc), buffer.begin()); 10951cb0ef41Sopenharmony_ci } 10961cb0ef41Sopenharmony_ci} 10971cb0ef41Sopenharmony_ci 10981cb0ef41Sopenharmony_ci} // namespace disasm 10991cb0ef41Sopenharmony_ci 11001cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_S390 1101