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