v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
disasm-s390.cc
Go to the documentation of this file.
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// A Disassembler object is used to disassemble a block of code instruction by
6// instruction. The default implementation of the NameConverter object can be
7// overriden to modify register names or to do symbol lookup on addresses.
8//
9// The example below will disassemble a block of code and print it to stdout.
10//
11// NameConverter converter;
12// Disassembler d(converter);
13// for (uint8_t* pc = begin; pc < end;) {
14// v8::base::EmbeddedVector<char, 256> buffer;
15// uint8_t* prev_pc = pc;
16// pc += d.InstructionDecode(buffer, pc);
17// printf("%p %08x %s\n",
18// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
19// }
20//
21// The Disassembler class also has a convenience method to disassemble a block
22// of code into a FILE*, meaning that the above functionality could also be
23// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
24
25#include <assert.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <string.h>
29
30#if V8_TARGET_ARCH_S390X
31
33#include "src/base/strings.h"
34#include "src/base/vector.h"
39
40namespace v8 {
41namespace internal {
42
43//------------------------------------------------------------------------------
44
45// Decoder decodes and disassembles instructions into an output buffer.
46// It uses the converter to convert register names and call destinations into
47// more informative description.
48class Decoder {
49 public:
50 Decoder(const disasm::NameConverter& converter, base::Vector<char> out_buffer)
51 : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) {
53 }
54
55 ~Decoder() {}
56
57 Decoder(const Decoder&) = delete;
58 Decoder& operator=(const Decoder&) = delete;
59
60 // Writes one disassembled instruction into 'buffer' (0-terminated).
61 // Returns the length of the disassembled machine instruction in bytes.
62 int InstructionDecode(uint8_t* instruction);
63
64 private:
65 // Bottleneck functions to print into the out_buffer.
66 void PrintChar(const char ch);
67 void Print(const char* str);
68
69 // Printing of common values.
70 void PrintRegister(int reg);
71 void PrintDRegister(int reg);
72 void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
73
74 // Handle formatting of instructions and their options.
75 int FormatRegister(Instruction* instr, const char* option);
76 int FormatFloatingRegister(Instruction* instr, const char* option);
77 int FormatMask(Instruction* instr, const char* option);
78 int FormatDisplacement(Instruction* instr, const char* option);
79 int FormatImmediate(Instruction* instr, const char* option);
80 int FormatOption(Instruction* instr, const char* option);
81 void Format(Instruction* instr, const char* format);
82 void Unknown(Instruction* instr);
83 void UnknownFormat(Instruction* instr, const char* opcname);
84
85 bool DecodeSpecial(Instruction* instr);
86 bool DecodeGeneric(Instruction* instr);
87
89 base::Vector<char> out_buffer_;
91};
92
93// Support for assertions in the Decoder formatting functions.
94#define STRING_STARTS_WITH(string, compare_string) \
95 (strncmp(string, compare_string, strlen(compare_string)) == 0)
96
97// Append the ch to the output buffer.
98void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
99
100// Append the str to the output buffer.
101void Decoder::Print(const char* str) {
102 char cur = *str++;
103 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
104 PrintChar(cur);
105 cur = *str++;
106 }
108}
109
110// Print the register name according to the active name converter.
111void Decoder::PrintRegister(int reg) {
112 Print(converter_.NameOfCPURegister(reg));
113}
114
115// Print the double FP register name according to the active name converter.
116void Decoder::PrintDRegister(int reg) {
117 Print(RegisterName(DoubleRegister::from_code(reg)));
118}
119
120// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
121// the FormatOption method.
122void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
123 switch (svc) {
125 Print("call rt redirected");
126 return;
127 case kBreakpoint:
128 Print("breakpoint");
129 return;
130 default:
131 if (svc >= kStopCode) {
134 svc & kStopCodeMask, svc & kStopCodeMask);
135 } else {
138 }
139 return;
140 }
141}
142
143// Handle all register based formatting in this function to reduce the
144// complexity of FormatOption.
145int Decoder::FormatRegister(Instruction* instr, const char* format) {
146 DCHECK_EQ(format[0], 'r');
147
148 if (format[1] == '1') { // 'r1: register resides in bit 8-11
149 int reg = instr->Bits<SixByteInstr, int>(39, 36);
151 return 2;
152 } else if (format[1] == '2') { // 'r2: register resides in bit 12-15
153 int reg = instr->Bits<SixByteInstr, int>(35, 32);
154 // indicating it is a r0 for displacement, in which case the offset
155 // should be 0.
156 if (format[2] == 'd') {
157 if (reg == 0) return 4;
159 return 3;
160 } else {
162 return 2;
163 }
164 } else if (format[1] == '3') { // 'r3: register resides in bit 16-19
165 int reg = instr->Bits<SixByteInstr, int>(31, 28);
167 return 2;
168 } else if (format[1] == '4') { // 'r4: register resides in bit 20-23
169 int reg = instr->Bits<SixByteInstr, int>(27, 24);
171 return 2;
172 } else if (format[1] == '5') { // 'r5: register resides in bit 24-27
173 int reg = instr->Bits<SixByteInstr, int>(23, 20);
175 return 2;
176 } else if (format[1] == '6') { // 'r6: register resides in bit 28-31
177 int reg = instr->Bits<SixByteInstr, int>(19, 16);
179 return 2;
180 } else if (format[1] == '7') { // 'r6: register resides in bit 32-35
181 int reg = instr->Bits<SixByteInstr, int>(15, 12);
183 return 2;
184 }
185
186 UNREACHABLE();
187}
188
189int Decoder::FormatFloatingRegister(Instruction* instr, const char* format) {
190 DCHECK_EQ(format[0], 'f');
191
192 // reuse 1, 5 and 6 because it is coresponding
193 if (format[1] == '1') { // 'r1: register resides in bit 8-11
194 RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr);
195 int reg = rrinstr->R1Value();
196 PrintDRegister(reg);
197 return 2;
198 } else if (format[1] == '2') { // 'f2: register resides in bit 12-15
199 RRInstruction* rrinstr = reinterpret_cast<RRInstruction*>(instr);
200 int reg = rrinstr->R2Value();
201 PrintDRegister(reg);
202 return 2;
203 } else if (format[1] == '3') { // 'f3: register resides in bit 16-19
204 RRDInstruction* rrdinstr = reinterpret_cast<RRDInstruction*>(instr);
205 int reg = rrdinstr->R1Value();
206 PrintDRegister(reg);
207 return 2;
208 } else if (format[1] == '5') { // 'f5: register resides in bit 24-28
209 RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr);
210 int reg = rreinstr->R1Value();
211 PrintDRegister(reg);
212 return 2;
213 } else if (format[1] == '6') { // 'f6: register resides in bit 29-32
214 RREInstruction* rreinstr = reinterpret_cast<RREInstruction*>(instr);
215 int reg = rreinstr->R2Value();
216 PrintDRegister(reg);
217 return 2;
218 } else if (format[1] == '4') {
219 VRR_E_Instruction* vrreinstr = reinterpret_cast<VRR_E_Instruction*>(instr);
220 int reg = vrreinstr->R4Value();
221 PrintDRegister(reg);
222 return 2;
223 }
224 UNREACHABLE();
225}
226
227// FormatOption takes a formatting string and interprets it based on
228// the current instructions. The format string points to the first
229// character of the option string (the option escape has already been
230// consumed by the caller.) FormatOption returns the number of
231// characters that were consumed from the formatting string.
232int Decoder::FormatOption(Instruction* instr, const char* format) {
233 switch (format[0]) {
234 case 'o': {
235 if (instr->Bit(10) == 1) {
236 Print("o");
237 }
238 return 1;
239 }
240 case '.': {
241 if (instr->Bit(0) == 1) {
242 Print(".");
243 } else {
244 Print(" "); // ensure consistent spacing
245 }
246 return 1;
247 }
248 case 'r': {
249 return FormatRegister(instr, format);
250 }
251 case 'f': {
252 return FormatFloatingRegister(instr, format);
253 }
254 case 'i': { // int16
255 return FormatImmediate(instr, format);
256 }
257 case 'u': { // uint16
258 int32_t value = instr->Bits(15, 0);
261 return 6;
262 }
263 case 'l': {
264 // Link (LK) Bit 0
265 if (instr->Bit(0) == 1) {
266 Print("l");
267 }
268 return 1;
269 }
270 case 'a': {
271 // Absolute Address Bit 1
272 if (instr->Bit(1) == 1) {
273 Print("a");
274 }
275 return 1;
276 }
277 case 't': { // 'target: target of branch instructions
278 // target26 or target16
279 DCHECK(STRING_STARTS_WITH(format, "target"));
280 if ((format[6] == '2') && (format[7] == '6')) {
281 int off = ((instr->Bits(25, 2)) << 8) >> 6;
283 out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
284 converter_.NameOfAddress(reinterpret_cast<uint8_t*>(instr) + off));
285 return 8;
286 } else if ((format[6] == '1') && (format[7] == '6')) {
287 int off = ((instr->Bits(15, 2)) << 18) >> 16;
289 out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
290 converter_.NameOfAddress(reinterpret_cast<uint8_t*>(instr) + off));
291 return 8;
292 }
293 break;
294 case 'm': {
295 return FormatMask(instr, format);
296 }
297 }
298 case 'd': { // ds value for offset
299 return FormatDisplacement(instr, format);
300 }
301 default: {
302 UNREACHABLE();
303 }
304 }
305
306 UNREACHABLE();
307}
308
309int Decoder::FormatMask(Instruction* instr, const char* format) {
310 DCHECK_EQ(format[0], 'm');
311 int32_t value = 0;
312 if ((format[1] == '1')) { // prints the mask format in bits 8-12
313 value = reinterpret_cast<RRInstruction*>(instr)->R1Value();
316 return 2;
317 } else if (format[1] == '2') { // mask format in bits 16-19
318 value = reinterpret_cast<RXInstruction*>(instr)->B2Value();
321 return 2;
322 } else if (format[1] == '3') { // mask format in bits 20-23
323 value = reinterpret_cast<RRFInstruction*>(instr)->M4Value();
326 return 2;
327 } else if (format[1] == '4') { // mask format in bits 32-35
328 value = reinterpret_cast<VRR_C_Instruction*>(instr)->M4Value();
331 return 2;
332 } else if (format[1] == '5') { // mask format in bits 28-31
333 value = reinterpret_cast<VRR_C_Instruction*>(instr)->M5Value();
336 return 2;
337 } else if (format[1] == '6') { // mask format in bits 24-27
338 value = reinterpret_cast<VRR_C_Instruction*>(instr)->M6Value();
341 return 2;
342 }
344 return 2;
345}
346
347int Decoder::FormatDisplacement(Instruction* instr, const char* format) {
348 DCHECK_EQ(format[0], 'd');
349
350 if (format[1] == '1') { // displacement in 20-31
351 RSInstruction* rsinstr = reinterpret_cast<RSInstruction*>(instr);
352 uint16_t value = rsinstr->D2Value();
355
356 return 2;
357 } else if (format[1] == '2') { // displacement in 20-39
358 RXYInstruction* rxyinstr = reinterpret_cast<RXYInstruction*>(instr);
359 int32_t value = rxyinstr->D2Value();
362 return 2;
363 } else if (format[1] == '4') { // SS displacement 2 36-47
364 SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
365 uint16_t value = ssInstr->D2Value();
368 return 2;
369 } else if (format[1] == '3') { // SS displacement 1 20 - 32
370 SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
371 uint16_t value = ssInstr->D1Value();
374 return 2;
375 } else { // s390 specific
376 int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
379 return 1;
380 }
381}
382
383int Decoder::FormatImmediate(Instruction* instr, const char* format) {
384 DCHECK_EQ(format[0], 'i');
385
386 if (format[1] == '1') { // immediate in 16-31
387 RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr);
388 int16_t value = riinstr->I2Value();
391 return 2;
392 } else if (format[1] == '2') { // immediate in 16-48
393 RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
394 int32_t value = rilinstr->I2Value();
397 return 2;
398 } else if (format[1] == '3') { // immediate in I format
399 IInstruction* iinstr = reinterpret_cast<IInstruction*>(instr);
400 int8_t value = iinstr->IValue();
403 return 2;
404 } else if (format[1] == '4') { // immediate in 16-31, but outputs as offset
405 RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr);
406 int16_t value = riinstr->I2Value() * 2;
407 if (value >= 0)
409 else
411
413 out_buffer_ + out_buffer_pos_, "%d -> %s", value,
414 converter_.NameOfAddress(reinterpret_cast<uint8_t*>(instr) + value));
415 return 2;
416 } else if (format[1] == '5') { // immediate in 16-31, but outputs as offset
417 RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
418 int32_t value = rilinstr->I2Value() * 2;
419 if (value >= 0)
421 else
423
425 out_buffer_ + out_buffer_pos_, "%d -> %s", value,
426 converter_.NameOfAddress(reinterpret_cast<uint8_t*>(instr) + value));
427 return 2;
428 } else if (format[1] == '6') { // unsigned immediate in 16-31
429 RIInstruction* riinstr = reinterpret_cast<RIInstruction*>(instr);
430 uint16_t value = riinstr->I2UnsignedValue();
433 return 2;
434 } else if (format[1] == '7') { // unsigned immediate in 16-47
435 RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
436 uint32_t value = rilinstr->I2UnsignedValue();
439 return 2;
440 } else if (format[1] == '8') { // unsigned immediate in 8-15
441 SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr);
442 uint8_t value = ssinstr->Length();
445 return 2;
446 } else if (format[1] == '9') { // unsigned immediate in 16-23
447 RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr);
448 uint8_t value = rie_instr->I3Value();
451 return 2;
452 } else if (format[1] == 'a') { // unsigned immediate in 24-31
453 RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr);
454 uint8_t value = rie_instr->I4Value();
457 return 2;
458 } else if (format[1] == 'b') { // unsigned immediate in 32-39
459 RIEInstruction* rie_instr = reinterpret_cast<RIEInstruction*>(instr);
460 uint8_t value = rie_instr->I5Value();
463 return 2;
464 } else if (format[1] == 'c') { // signed immediate in 8-15
465 SSInstruction* ssinstr = reinterpret_cast<SSInstruction*>(instr);
466 int8_t value = ssinstr->Length();
469 return 2;
470 } else if (format[1] == 'd') { // signed immediate in 32-47
471 SILInstruction* silinstr = reinterpret_cast<SILInstruction*>(instr);
472 int16_t value = silinstr->I2Value();
475 return 2;
476 } else if (format[1] == 'e') { // immediate in 16-47, but outputs as offset
477 RILInstruction* rilinstr = reinterpret_cast<RILInstruction*>(instr);
478 int32_t value = rilinstr->I2Value() * 2;
479 if (value >= 0)
481 else
483
485 out_buffer_ + out_buffer_pos_, "%d -> %s", value,
486 converter_.NameOfAddress(reinterpret_cast<uint8_t*>(instr) + value));
487 return 2;
488 }
489
490 UNREACHABLE();
491}
492
493// Format takes a formatting string for a whole instruction and prints it into
494// the output buffer. All escaped options are handed to FormatOption to be
495// parsed further.
496void Decoder::Format(Instruction* instr, const char* format) {
497 char cur = *format++;
498 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
499 if (cur == '\'') { // Single quote is used as the formatting escape.
500 format += FormatOption(instr, format);
501 } else {
503 }
504 cur = *format++;
505 }
507}
508
509// The disassembler may end up decoding data inlined in the code. We do not want
510// it to crash if the data does not resemble any known instruction.
511#define VERIFY(condition) \
512 if (!(condition)) { \
513 Unknown(instr); \
514 return; \
515 }
516
517// For currently unimplemented decodings the disassembler calls Unknown(instr)
518// which will just print "unknown" of the instruction bits.
519void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); }
520
521// For currently unimplemented decodings the disassembler calls
522// UnknownFormat(instr) which will just print opcode name of the
523// instruction bits.
524void Decoder::UnknownFormat(Instruction* instr, const char* name) {
525 char buffer[100];
526 snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name);
527 Format(instr, buffer);
528}
529
530#undef VERIFY
531#undef STRING_STARTS_WITH
532
533// Handles special cases of instructions;
534// @return true if successfully decoded
535bool Decoder::DecodeSpecial(Instruction* instr) {
536 Opcode opcode = instr->S390OpcodeValue();
537 switch (opcode) {
538 case BKPT:
539 Format(instr, "bkpt");
540 break;
541 case DUMY:
542 Format(instr, "dumy\t'r1, 'd2 ( 'r2d, 'r3 )");
543 break;
544 /* RR format */
545 case LDR:
546 Format(instr, "ldr\t'f1,'f2");
547 break;
548 case BCR:
549 Format(instr, "bcr\t'm1,'r2");
550 break;
551 case OR:
552 Format(instr, "or\t'r1,'r2");
553 break;
554 case CR:
555 Format(instr, "cr\t'r1,'r2");
556 break;
557 case MR:
558 Format(instr, "mr\t'r1,'r2");
559 break;
560 case HER_Z:
561 Format(instr, "her\t'r1,'r2");
562 break;
563 /* RI-b format */
564 case BRAS:
565 Format(instr, "bras\t'r1,'i1");
566 break;
567 /* RRE format */
568 case MDBR:
569 Format(instr, "mdbr\t'f5,'f6");
570 break;
571 case SDBR:
572 Format(instr, "sdbr\t'f5,'f6");
573 break;
574 case ADBR:
575 Format(instr, "adbr\t'f5,'f6");
576 break;
577 case CDBR:
578 Format(instr, "cdbr\t'f5,'f6");
579 break;
580 case MEEBR:
581 Format(instr, "meebr\t'f5,'f6");
582 break;
583 case SQDBR:
584 Format(instr, "sqdbr\t'f5,'f6");
585 break;
586 case SQEBR:
587 Format(instr, "sqebr\t'f5,'f6");
588 break;
589 case LCDBR:
590 Format(instr, "lcdbr\t'f5,'f6");
591 break;
592 case LCEBR:
593 Format(instr, "lcebr\t'f5,'f6");
594 break;
595 case LTEBR:
596 Format(instr, "ltebr\t'f5,'f6");
597 break;
598 case LDEBR:
599 Format(instr, "ldebr\t'f5,'f6");
600 break;
601 case CEBR:
602 Format(instr, "cebr\t'f5,'f6");
603 break;
604 case AEBR:
605 Format(instr, "aebr\t'f5,'f6");
606 break;
607 case SEBR:
608 Format(instr, "sebr\t'f5,'f6");
609 break;
610 case DEBR:
611 Format(instr, "debr\t'f5,'f6");
612 break;
613 case LTDBR:
614 Format(instr, "ltdbr\t'f5,'f6");
615 break;
616 case LDGR:
617 Format(instr, "ldgr\t'f5,'f6");
618 break;
619 case DDBR:
620 Format(instr, "ddbr\t'f5,'f6");
621 break;
622 case LZDR:
623 Format(instr, "lzdr\t'f5");
624 break;
625 /* RRF-e format */
626 case FIEBRA:
627 Format(instr, "fiebra\t'f5,'m2,'f6,'m3");
628 break;
629 case FIDBRA:
630 Format(instr, "fidbra\t'f5,'m2,'f6,'m3");
631 break;
632 /* RX-a format */
633 case IC_z:
634 Format(instr, "ic\t'r1,'d1('r2d,'r3)");
635 break;
636 case AL:
637 Format(instr, "al\t'r1,'d1('r2d,'r3)");
638 break;
639 case LE:
640 Format(instr, "le\t'f1,'d1('r2d,'r3)");
641 break;
642 case LD:
643 Format(instr, "ld\t'f1,'d1('r2d,'r3)");
644 break;
645 case STE:
646 Format(instr, "ste\t'f1,'d1('r2d,'r3)");
647 break;
648 case STD:
649 Format(instr, "std\t'f1,'d1('r2d,'r3)");
650 break;
651 /* S format */
652 // TRAP4 is used in calling to native function. it will not be generated
653 // in native code.
654 case TRAP4:
655 Format(instr, "trap4");
656 break;
657 /* RIL-a format */
658 case CFI:
659 Format(instr, "cfi\t'r1,'i2");
660 break;
661 case CGFI:
662 Format(instr, "cgfi\t'r1,'i2");
663 break;
664 case AFI:
665 Format(instr, "afi\t'r1,'i2");
666 break;
667 case AGFI:
668 Format(instr, "agfi\t'r1,'i2");
669 break;
670 case MSFI:
671 Format(instr, "msfi\t'r1,'i2");
672 break;
673 case MSGFI:
674 Format(instr, "msgfi\t'r1,'i2");
675 break;
676 case ALSIH:
677 Format(instr, "alsih\t'r1,'i2");
678 break;
679 case ALSIHN:
680 Format(instr, "alsihn\t'r1,'i2");
681 break;
682 case CIH:
683 Format(instr, "cih\t'r1,'i2");
684 break;
685 case AIH:
686 Format(instr, "aih\t'r1,'i2");
687 break;
688 case LGFI:
689 Format(instr, "lgfi\t'r1,'i2");
690 break;
691 /* SIY format */
692 case ASI:
693 Format(instr, "asi\t'd2('r3),'ic");
694 break;
695 case AGSI:
696 Format(instr, "agsi\t'd2('r3),'ic");
697 break;
698 /* RXY-a format */
699 case LT:
700 Format(instr, "lt\t'r1,'d2('r2d,'r3)");
701 break;
702 case LDY:
703 Format(instr, "ldy\t'f1,'d2('r2d,'r3)");
704 break;
705 case LEY:
706 Format(instr, "ley\t'f1,'d2('r2d,'r3)");
707 break;
708 case STDY:
709 Format(instr, "stdy\t'f1,'d2('r2d,'r3)");
710 break;
711 case STEY:
712 Format(instr, "stey\t'f1,'d2('r2d,'r3)");
713 break;
714 /* RXE format */
715 case LDEB:
716 Format(instr, "ldeb\t'f1,'d2('r2d,'r3)");
717 break;
718 default:
719 return false;
720 }
721 return true;
722}
723
724// Handles common cases of instructions;
725// @return true if successfully decoded
726bool Decoder::DecodeGeneric(Instruction* instr) {
727 Opcode opcode = instr->S390OpcodeValue();
728 switch (opcode) {
729 /* 2 bytes */
730#define DECODE_RR_INSTRUCTIONS(name, opcode_name, opcode_value) \
731 case opcode_name: \
732 Format(instr, #name "\t'r1,'r2"); \
733 break;
734 S390_RR_OPCODE_LIST(DECODE_RR_INSTRUCTIONS)
735#undef DECODE_RR_INSTRUCTIONS
736
737 /* 4 bytes */
738#define DECODE_RS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
739 case opcode_name: \
740 Format(instr, #name "\t'r1,'r2,'d1('r3)"); \
741 break;
742 S390_RS_A_OPCODE_LIST(DECODE_RS_A_INSTRUCTIONS)
743#undef DECODE_RS_A_INSTRUCTIONS
744
745#define DECODE_RSI_INSTRUCTIONS(name, opcode_name, opcode_value) \
746 case opcode_name: \
747 Format(instr, #name "\t'r1,'r2,'i4"); \
748 break;
749 S390_RSI_OPCODE_LIST(DECODE_RSI_INSTRUCTIONS)
750#undef DECODE_RSI_INSTRUCTIONS
751
752#define DECODE_RI_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
753 case opcode_name: \
754 Format(instr, #name "\t'r1,'i1"); \
755 break;
756 S390_RI_A_OPCODE_LIST(DECODE_RI_A_INSTRUCTIONS)
757#undef DECODE_RI_A_INSTRUCTIONS
758
759#define DECODE_RI_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
760 case opcode_name: \
761 Format(instr, #name "\t'r1,'i4"); \
762 break;
763 S390_RI_B_OPCODE_LIST(DECODE_RI_B_INSTRUCTIONS)
764#undef DECODE_RI_B_INSTRUCTIONS
765
766#define DECODE_RI_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
767 case opcode_name: \
768 Format(instr, #name "\t'm1,'i4"); \
769 break;
770 S390_RI_C_OPCODE_LIST(DECODE_RI_C_INSTRUCTIONS)
771#undef DECODE_RI_C_INSTRUCTIONS
772
773#define DECODE_RRE_INSTRUCTIONS(name, opcode_name, opcode_value) \
774 case opcode_name: \
775 Format(instr, #name "\t'r5,'r6"); \
776 break;
777 S390_RRE_OPCODE_LIST(DECODE_RRE_INSTRUCTIONS)
778#undef DECODE_RRE_INSTRUCTIONS
779
780#define DECODE_RRF_A_INSTRUCTIONS(name, opcode_name, opcode_val) \
781 case opcode_name: \
782 Format(instr, #name "\t'r5,'r6,'r3"); \
783 break;
784 S390_RRF_A_OPCODE_LIST(DECODE_RRF_A_INSTRUCTIONS)
785#undef DECODE_RRF_A_INSTRUCTIONS
786
787#define DECODE_RRF_C_INSTRUCTIONS(name, opcode_name, opcode_val) \
788 case opcode_name: \
789 Format(instr, #name "\t'r5,'r6,'m2"); \
790 break;
791 S390_RRF_C_OPCODE_LIST(DECODE_RRF_C_INSTRUCTIONS)
792#undef DECODE_RRF_C_INSTRUCTIONS
793
794#define DECODE_RRF_E_INSTRUCTIONS(name, opcode_name, opcode_val) \
795 case opcode_name: \
796 Format(instr, #name "\t'r5,'m2,'f6"); \
797 break;
798 S390_RRF_E_OPCODE_LIST(DECODE_RRF_E_INSTRUCTIONS)
799#undef DECODE_RRF_E_INSTRUCTIONS
800
801#define DECODE_RX_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
802 case opcode_name: \
803 Format(instr, #name "\t'r1,'d1('r2d,'r3)"); \
804 break;
805 S390_RX_A_OPCODE_LIST(DECODE_RX_A_INSTRUCTIONS)
806#undef DECODE_RX_A_INSTRUCTIONS
807
808#define DECODE_RX_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
809 case opcode_name: \
810 Format(instr, #name "\t'm1,'d1('r2d,'r3)"); \
811 break;
812 S390_RX_B_OPCODE_LIST(DECODE_RX_B_INSTRUCTIONS)
813#undef DECODE_RX_B_INSTRUCTIONS
814
815#define DECODE_RRD_INSTRUCTIONS(name, opcode_name, opcode_value) \
816 case opcode_name: \
817 Format(instr, #name "\t'f3,'f5,'f6"); \
818 break;
819 S390_RRD_OPCODE_LIST(DECODE_RRD_INSTRUCTIONS)
820#undef DECODE_RRD_INSTRUCTIONS
821
822#define DECODE_SI_INSTRUCTIONS(name, opcode_name, opcode_value) \
823 case opcode_name: \
824 Format(instr, #name "\t'd1('r3),'i8"); \
825 break;
826 S390_SI_OPCODE_LIST(DECODE_SI_INSTRUCTIONS)
827#undef DECODE_SI_INSTRUCTIONS
828
829 /* 6 bytes */
830#define DECODE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
831 case opcode_name: \
832 Format(instr, #name "\t'f1,'f2,'m4,'m5,'m6"); \
833 break;
834 S390_VRR_A_OPCODE_LIST(DECODE_VRR_A_INSTRUCTIONS)
835#undef DECODE_VRR_A_INSTRUCTIONS
836
837#define DECODE_VRR_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
838 case opcode_name: \
839 Format(instr, #name "\t'f1,'f2,'f3,'m4,'m6"); \
840 break;
841 S390_VRR_B_OPCODE_LIST(DECODE_VRR_B_INSTRUCTIONS)
842#undef DECODE_VRR_B_INSTRUCTIONS
843
844#define DECODE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
845 case opcode_name: \
846 Format(instr, #name "\t'f1,'f2,'f3,'m4"); \
847 break;
848 S390_VRR_C_OPCODE_LIST(DECODE_VRR_C_INSTRUCTIONS)
849#undef DECODE_VRR_C_INSTRUCTIONS
850
851#define DECODE_VRR_E_INSTRUCTIONS(name, opcode_name, opcode_value) \
852 case opcode_name: \
853 Format(instr, #name "\t'f1,'f2,'f3,'f4,'m5,'m3"); \
854 break;
855 S390_VRR_E_OPCODE_LIST(DECODE_VRR_E_INSTRUCTIONS)
856#undef DECODE_VRR_E_INSTRUCTIONS
857
858#define DECODE_VRR_F_INSTRUCTIONS(name, opcode_name, opcode_value) \
859 case opcode_name: \
860 Format(instr, #name "\t'f1,'r1,'r2"); \
861 break;
862 S390_VRR_F_OPCODE_LIST(DECODE_VRR_F_INSTRUCTIONS)
863#undef DECODE_VRR_F_INSTRUCTIONS
864
865#define DECODE_VRX_INSTRUCTIONS(name, opcode_name, opcode_value) \
866 case opcode_name: \
867 Format(instr, #name "\t'f1,'d1('r2d,'r3),'m4"); \
868 break;
869 S390_VRX_OPCODE_LIST(DECODE_VRX_INSTRUCTIONS)
870#undef DECODE_VRX_INSTRUCTIONS
871
872#define DECODE_VRS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
873 case opcode_name: \
874 Format(instr, #name "\t'f1,'f2,'d1('r3),'m4"); \
875 break;
876 S390_VRS_A_OPCODE_LIST(DECODE_VRS_A_INSTRUCTIONS)
877#undef DECODE_VRS_A_INSTRUCTIONS
878
879#define DECODE_VRS_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
880 case opcode_name: \
881 Format(instr, #name "\t'f1,'r2,'d1('r3),'m4"); \
882 break;
883 S390_VRS_B_OPCODE_LIST(DECODE_VRS_B_INSTRUCTIONS)
884#undef DECODE_VRS_B_INSTRUCTIONS
885
886#define DECODE_VRS_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
887 case opcode_name: \
888 Format(instr, #name "\t'r1,'f2,'d1('r3),'m4"); \
889 break;
890 S390_VRS_C_OPCODE_LIST(DECODE_VRS_C_INSTRUCTIONS)
891#undef DECODE_VRS_C_INSTRUCTIONS
892
893#define DECODE_VRI_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
894 case opcode_name: \
895 Format(instr, #name "\t'f1,'i1,'m4"); \
896 break;
897 S390_VRI_A_OPCODE_LIST(DECODE_VRI_A_INSTRUCTIONS)
898#undef DECODE_VRI_A_INSTRUCTIONS
899
900#define DECODE_VRI_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
901 case opcode_name: \
902 Format(instr, #name "\t'f1,'f2,'i1,'m4"); \
903 break;
904 S390_VRI_C_OPCODE_LIST(DECODE_VRI_C_INSTRUCTIONS)
905#undef DECODE_VRI_C_INSTRUCTIONS
906
907#define DECODE_RIL_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
908 case opcode_name: \
909 Format(instr, #name "\t'r1,'i7"); \
910 break;
911 S390_RIL_A_OPCODE_LIST(DECODE_RIL_A_INSTRUCTIONS)
912#undef DECODE_RIL_A_INSTRUCTIONS
913
914#define DECODE_RIL_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
915 case opcode_name: \
916 Format(instr, #name "\t'r1,'ie"); \
917 break;
918 S390_RIL_B_OPCODE_LIST(DECODE_RIL_B_INSTRUCTIONS)
919#undef DECODE_RIL_B_INSTRUCTIONS
920
921#define DECODE_RIL_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
922 case opcode_name: \
923 Format(instr, #name "\t'm1,'ie"); \
924 break;
925 S390_RIL_C_OPCODE_LIST(DECODE_RIL_C_INSTRUCTIONS)
926#undef DECODE_RIL_C_INSTRUCTIONS
927
928#define DECODE_SIY_INSTRUCTIONS(name, opcode_name, opcode_value) \
929 case opcode_name: \
930 Format(instr, #name "\t'd2('r3),'i8"); \
931 break;
932 S390_SIY_OPCODE_LIST(DECODE_SIY_INSTRUCTIONS)
933#undef DECODE_SIY_INSTRUCTIONS
934
935#define DECODE_RIE_D_INSTRUCTIONS(name, opcode_name, opcode_value) \
936 case opcode_name: \
937 Format(instr, #name "\t'r1,'r2,'i1"); \
938 break;
939 S390_RIE_D_OPCODE_LIST(DECODE_RIE_D_INSTRUCTIONS)
940#undef DECODE_RIE_D_INSTRUCTIONS
941
942#define DECODE_RIE_E_INSTRUCTIONS(name, opcode_name, opcode_value) \
943 case opcode_name: \
944 Format(instr, #name "\t'r1,'r2,'i4"); \
945 break;
946 S390_RIE_E_OPCODE_LIST(DECODE_RIE_E_INSTRUCTIONS)
947#undef DECODE_RIE_E_INSTRUCTIONS
948
949#define DECODE_RIE_F_INSTRUCTIONS(name, opcode_name, opcode_value) \
950 case opcode_name: \
951 Format(instr, #name "\t'r1,'r2,'i9,'ia,'ib"); \
952 break;
953 S390_RIE_F_OPCODE_LIST(DECODE_RIE_F_INSTRUCTIONS)
954#undef DECODE_RIE_F_INSTRUCTIONS
955
956#define DECODE_RSY_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
957 case opcode_name: \
958 Format(instr, #name "\t'r1,'r2,'d2('r3)"); \
959 break;
960 S390_RSY_A_OPCODE_LIST(DECODE_RSY_A_INSTRUCTIONS)
961#undef DECODE_RSY_A_INSTRUCTIONS
962
963#define DECODE_RSY_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
964 case opcode_name: \
965 Format(instr, #name "\t'm2,'r1,'d2('r3)"); \
966 break;
967 S390_RSY_B_OPCODE_LIST(DECODE_RSY_B_INSTRUCTIONS)
968#undef DECODE_RSY_B_INSTRUCTIONS
969
970#define DECODE_RXY_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
971 case opcode_name: \
972 Format(instr, #name "\t'r1,'d2('r2d,'r3)"); \
973 break;
974 S390_RXY_A_OPCODE_LIST(DECODE_RXY_A_INSTRUCTIONS)
975#undef DECODE_RXY_A_INSTRUCTIONS
976
977#define DECODE_RXY_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
978 case opcode_name: \
979 Format(instr, #name "\t'm1,'d2('r2d,'r3)"); \
980 break;
981 S390_RXY_B_OPCODE_LIST(DECODE_RXY_B_INSTRUCTIONS)
982#undef DECODE_RXY_B_INSTRUCTIONS
983
984#define DECODE_RXE_INSTRUCTIONS(name, opcode_name, opcode_value) \
985 case opcode_name: \
986 Format(instr, #name "\t'f1,'d1('r2d, 'r3)"); \
987 break;
988 S390_RXE_OPCODE_LIST(DECODE_RXE_INSTRUCTIONS)
989#undef DECODE_RXE_INSTRUCTIONS
990
991#define DECODE_SIL_INSTRUCTIONS(name, opcode_name, opcode_value) \
992 case opcode_name: \
993 Format(instr, #name "\t'd3('r3),'id"); \
994 break;
995 S390_SIL_OPCODE_LIST(DECODE_SIL_INSTRUCTIONS)
996#undef DECODE_SIL_INSTRUCTIONS
997
998#define DECODE_SS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
999 case opcode_name: \
1000 Format(instr, #name "\t'd3('i8,'r3),'d4('r7)"); \
1001 break;
1002 S390_SS_A_OPCODE_LIST(DECODE_SS_A_INSTRUCTIONS)
1003#undef DECODE_SS_A_INSTRUCTIONS
1004
1005 default:
1006 return false;
1007 }
1008 return true;
1009}
1010
1011// Disassemble the instruction at *instr_ptr into the output buffer.
1012int Decoder::InstructionDecode(uint8_t* instr_ptr) {
1013 Instruction* instr = Instruction::At(instr_ptr);
1014 int instrLength = instr->InstructionLength();
1015
1016 // Print the Instruction bits.
1017 if (instrLength == 2) {
1020 instr->InstructionBits<TwoByteInstr>());
1021 } else if (instrLength == 4) {
1024 instr->InstructionBits<FourByteInstr>());
1025 } else {
1027 base::SNPrintF(out_buffer_ + out_buffer_pos_, "%012" PRIx64 " ",
1028 instr->InstructionBits<SixByteInstr>());
1029 }
1030
1031 bool decoded = DecodeSpecial(instr);
1032 if (!decoded) decoded = DecodeGeneric(instr);
1033 if (!decoded) Unknown(instr);
1034 return instrLength;
1035}
1036
1037} // namespace internal
1038} // namespace v8
1039
1040//------------------------------------------------------------------------------
1041
1042namespace disasm {
1043
1044const char* NameConverter::NameOfAddress(uint8_t* addr) const {
1045 v8::base::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
1046 return tmp_buffer_.begin();
1047}
1048
1049const char* NameConverter::NameOfConstant(uint8_t* addr) const {
1050 return NameOfAddress(addr);
1051}
1052
1053const char* NameConverter::NameOfCPURegister(int reg) const {
1054 return RegisterName(i::Register::from_code(reg));
1055}
1056
1057const char* NameConverter::NameOfByteCPURegister(int reg) const {
1058 UNREACHABLE(); // S390 does not have the concept of a byte register
1059}
1060
1061const char* NameConverter::NameOfXMMRegister(int reg) const {
1062 // S390 does not have XMM register
1063 // TODO(joransiu): Consider update this for Vector Regs
1064 UNREACHABLE();
1065}
1066
1067const char* NameConverter::NameInCode(uint8_t* addr) const {
1068 // The default name converter is called for unknown code. So we will not try
1069 // to access any memory.
1070 return "";
1071}
1072
1073//------------------------------------------------------------------------------
1074
1076 uint8_t* instruction) {
1078 return d.InstructionDecode(instruction);
1079}
1080
1081// The S390 assembler does not currently use constant pools.
1082int Disassembler::ConstantPoolSizeAt(uint8_t* instruction) { return -1; }
1083
1084void Disassembler::Disassemble(FILE* f, uint8_t* begin, uint8_t* end,
1085 UnimplementedOpcodeAction unimplemented_action) {
1086 NameConverter converter;
1087 Disassembler d(converter, unimplemented_action);
1088 for (uint8_t* pc = begin; pc < end;) {
1090 buffer[0] = '\0';
1091 uint8_t* prev_pc = pc;
1092 pc += d.InstructionDecode(buffer, pc);
1093 v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc),
1094 *reinterpret_cast<int32_t*>(prev_pc), buffer.begin());
1095 }
1096}
1097
1098} // namespace disasm
1099
1100#endif // V8_TARGET_ARCH_S390X
static V8_EXPORT_PRIVATE void Disassemble(FILE *f, uint8_t *begin, uint8_t *end, UnimplementedOpcodeAction unimplemented_action=kAbortOnUnimplementedOpcode)
V8_EXPORT_PRIVATE int InstructionDecode(v8::base::Vector< char > buffer, uint8_t *instruction)
int ConstantPoolSizeAt(uint8_t *instruction)
Disassembler(const NameConverter &converter, UnimplementedOpcodeAction unimplemented_opcode_action=kAbortOnUnimplementedOpcode)
Definition disasm.h:44
const NameConverter & converter_
Definition disasm.h:71
virtual const char * NameOfAddress(uint8_t *addr) const
virtual const char * NameOfXMMRegister(int reg) const
virtual const char * NameInCode(uint8_t *addr) const
virtual const char * NameOfConstant(uint8_t *addr) const
v8::base::EmbeddedVector< char, 128 > tmp_buffer_
Definition disasm.h:32
virtual const char * NameOfByteCPURegister(int reg) const
virtual const char * NameOfCPURegister(int reg) const
int length() const
Definition vector.h:64
constexpr T * begin() const
Definition vector.h:96
void Format(Instruction *instr, const char *format)
int InstructionDecode(uint8_t *instruction)
void Unknown(Instruction *instr)
const disasm::NameConverter & converter_
void PrintRegister(int reg)
void PrintChar(const char ch)
v8::base::Vector< char > out_buffer_
int FormatOption(Instruction *instr, const char *option)
int FormatRegister(Instruction *instr, const char *option)
void Print(const char *str)
Decoder & operator=(const Decoder &)=delete
static Instruction * At(Address pc)
static constexpr DwVfpRegister from_code(int8_t code)
#define SIGN_EXT_IMM16(imm)
#define S390_RIE_E_OPCODE_LIST(V)
#define S390_RRD_OPCODE_LIST(V)
#define S390_RX_B_OPCODE_LIST(V)
#define S390_VRR_E_OPCODE_LIST(V)
#define S390_SIY_OPCODE_LIST(V)
#define S390_RRF_A_OPCODE_LIST(V)
#define S390_VRI_A_OPCODE_LIST(V)
#define S390_VRI_C_OPCODE_LIST(V)
#define S390_RRF_C_OPCODE_LIST(V)
#define S390_RRE_OPCODE_LIST(V)
#define S390_VRR_C_OPCODE_LIST(V)
#define S390_SS_A_OPCODE_LIST(V)
#define S390_RSY_B_OPCODE_LIST(V)
#define S390_RXE_OPCODE_LIST(V)
#define S390_VRS_A_OPCODE_LIST(V)
#define S390_RIE_F_OPCODE_LIST(V)
#define S390_VRR_A_OPCODE_LIST(V)
#define S390_RXY_A_OPCODE_LIST(V)
#define S390_VRS_B_OPCODE_LIST(V)
#define S390_RI_B_OPCODE_LIST(V)
#define S390_RS_A_OPCODE_LIST(V)
#define S390_RSY_A_OPCODE_LIST(V)
#define S390_RI_A_OPCODE_LIST(V)
#define S390_VRR_F_OPCODE_LIST(V)
#define S390_VRR_B_OPCODE_LIST(V)
#define S390_SIL_OPCODE_LIST(V)
#define S390_RXY_B_OPCODE_LIST(V)
#define S390_RIL_A_OPCODE_LIST(V)
#define S390_RIL_B_OPCODE_LIST(V)
#define S390_VRS_C_OPCODE_LIST(V)
#define S390_RRF_E_OPCODE_LIST(V)
#define S390_RIL_C_OPCODE_LIST(V)
#define S390_RIE_D_OPCODE_LIST(V)
#define S390_VRX_OPCODE_LIST(V)
#define S390_RI_C_OPCODE_LIST(V)
#define S390_RX_A_OPCODE_LIST(V)
#define S390_SI_OPCODE_LIST(V)
#define S390_RSI_OPCODE_LIST(V)
#define S390_RR_OPCODE_LIST(V)
int end
#define STRING_STARTS_WITH(string, compare_string)
Instruction * instr
LiftoffRegister reg
int int32_t
Definition unicode.cc:40
unsigned short uint16_t
Definition unicode.cc:39
signed short int16_t
Definition unicode.cc:38
int SNPrintF(Vector< char > str, const char *format,...)
Definition strings.cc:20
constexpr Opcode LDR
uint64_t SixByteInstr
uint32_t FourByteInstr
constexpr BarrierOption LD
constexpr SoftwareInterruptCodes kStopCode
void PrintF(const char *format,...)
Definition utils.cc:39
constexpr MiscInstructionsBits74 BKPT
constexpr SoftwareInterruptCodes kBreakpoint
constexpr SoftwareInterruptCodes kCallRtRedirected
uint16_t TwoByteInstr
constexpr uint32_t kStopCodeMask
#define UNREACHABLE()
Definition logging.h:67
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485