2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | (c) Copyright IBM Corporation 2015-2016 |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/ppc64-asm/decoder-ppc64.h"
21 #include "hphp/ppc64-asm/branch-ppc64.h"
22 #include "hphp/ppc64-asm/isa-ppc64.h"
23 #include "hphp/ppc64-asm/asm-ppc64.h"
25 #include "hphp/util/assertions.h"
29 Decoder
* Decoder::s_decoder
= nullptr;
32 #define PPC_OPERAND_GPR 0x1
33 #define PPC_OPERAND_GPR_0 0x2
34 #define PPC_OPERAND_SIGNED 0x4
35 #define PPC_OPERAND_UNSIGNED 0x8
36 #define PPC_OPERAND_PAREN 0x10
37 #define PPC_OPERAND_RELATIVE 0x20
38 #define PPC_OPERAND_ABSOLUTE 0x40
39 #define PPC_OPERAND_OPTIONAL 0x80
40 #define PPC_OPERAND_FPR 0x100
41 #define PPC_OPERAND_VR 0x200
42 #define PPC_OPERAND_VSX 0x400
43 #define PPC_OPERAND_SIGNOPT 0x800
44 #define PPC_OPERAND_CR 0x1000
45 #define PPC_OPERAND_NEXT 0x2000
46 #define PPC_OPERAND_PLUS1 0x4000
47 #define PPC_OPERAND_NOSHIFT 0x8000
49 #define A { 0x2000000, 0x0 }
50 #define A_L { 0x20, 0x0 }
51 #define BA { 0x001f0000, 0x0 }
52 #define BB { 0x0000f800, 0x0 }
53 #define BD { 0x0000fffc, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED | \
55 #define BDA { 0xfffc, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }
57 #define BFA { 0x1c0000, PPC_OPERAND_CR }
58 #define BFF { 0x3800000, 0x0 }
59 #define BH { 0x00001800, 0x0 }
60 #define BHRBE { 0x1ff800, 0x0 }
61 #define BI { 0x001f0000, 0x0 }
62 #define BO { 0x03e00000, 0x0 }
63 #define BT { 0x03e00000, 0x0 }
64 #define CRFD { 0x3800000, PPC_OPERAND_CR }
65 #define CRB { 0x1c0000, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }
66 #define CT { 0x7, PPC_OPERAND_CR }
67 #define D { 0xffff, PPC_OPERAND_PAREN | PPC_OPERAND_SIGNED }
68 #define DCM { 0xfc00, 0x0 }
70 #define DM { 0xc0, 0x0 }
71 #define DQ { 0xfff0, 0x0 }
72 #define DS { 0xfffc, PPC_OPERAND_PAREN | PPC_OPERAND_SIGNED | \
74 #define DUI { 0x3e00000, 0x0 }
75 #define DUIS { 0x1ff800, PPC_OPERAND_SIGNED }
76 #define E { 0x8000, 0x0 }
77 #define EH { 0x1, PPC_OPERAND_OPTIONAL }
78 #define EVUIMM { 0xf800, 0x0 }
79 #define EVUIMM_2 { 0xf800, PPC_OPERAND_PAREN }
80 #define EVUIMM_4 EVUIMM_2
81 #define EVUIMM_8 EVUIMM_4
82 #define FLM { 0x1fe0000, 0x0 }
83 #define FRA { 0x1f0000, PPC_OPERAND_FPR }
84 #define FRB { 0xf800, PPC_OPERAND_FPR }
85 #define FRC { 0x7c0, PPC_OPERAND_FPR }
86 #define FRS { 0x3e00000, PPC_OPERAND_FPR }
88 #define FXM { 0xff000, 0x0 }
89 #define L { 0x2000000, PPC_OPERAND_OPTIONAL }
90 #define LEV { 0xfe0, PPC_OPERAND_OPTIONAL }
91 #define LI { 0x3fffffc, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED | \
93 #define LIA { 0x3fffffc, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED | \
95 #define LS { 0x600000, PPC_OPERAND_OPTIONAL }
96 #define MB6 { 0x7e0, 0x0 }
98 #define MBE { 0x7c0, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT }
99 #define ME { 0x3e, 0x0 }
100 #define MO { 0x3e00000, PPC_OPERAND_OPTIONAL }
101 #define NB { 0xf800, PPC_OPERAND_PLUS1 }
102 #define OC { 0x3fff800, 0x0 }
103 #define PMR { 0x1ff800, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT }
104 #define PS { 0x200, 0x0 }
105 #define R { 0x10000, 0x0 }
106 #define RA { 0x1f0000, PPC_OPERAND_GPR }
107 // 0 in the RA field means zero, not r0.
108 #define RA0 { 0x1f0000, PPC_OPERAND_GPR_0 }
111 #define RAOPT { 0x1f0000, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL}
114 #define RB { 0xf800, PPC_OPERAND_GPR }
115 #define RMC { 0x600, 0x0 }
116 #define RS { 0x3e00000, PPC_OPERAND_GPR }
117 #define RSO { 0x3e00000, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }
118 #define RSQ { 0x3c00000, PPC_OPERAND_GPR_0 }
122 #define S { 0x100000, 0x0 }
123 #define SH { 0xf000, 0x0 }
124 #define SH6 { (0xf000 | 0x2), 0x0 }
125 #define SH16 { 0xf800, 0x0 }
126 #define SHB { 0x3c0, 0x0 }
127 #define SHO { 0xf800, PPC_OPERAND_OPTIONAL }
128 #define SHW { 0xc0, 0x0 }
129 #define SI { 0xffff, PPC_OPERAND_SIGNED }
130 #define SIMM { 0x1f0000, 0x0 }
131 #define SISIGNOPT { 0xffff, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT }
132 #define SIX { 0x3c00000, 0x0 }
133 #define SP { 0x180000, 0x0 }
134 #define SPR { 0x1ff800, 0x0 }
135 #define SR { 0xf0000, 0x0 }
136 #define ST { 0x600000, 0x0 }
137 #define TBR { 0x1ff800, PPC_OPERAND_OPTIONAL }
138 #define TE { 0x1f0000, 0x0 }
139 #define TH { 0x3e00000, 0x0 }
141 #define U { 0xf000, 0x0 }
142 #define UI { 0xffff, PPC_OPERAND_UNSIGNED }
143 #define UIMM { 0x1f0000, PPC_OPERAND_SIGNED }
144 #define UN { 0x0, 0x0 }
145 #define VA { 0x1f0000, PPC_OPERAND_VR }
146 #define VB { 0xf800, PPC_OPERAND_VR }
147 #define VC { 0x7c0, PPC_OPERAND_VR }
148 #define VD { 0x3e00000, PPC_OPERAND_VR }
150 #define W { 0x10000, PPC_OPERAND_OPTIONAL }
151 #define WC { 0x600000, 0x0 }
152 #define XA { 0x1f0000, PPC_OPERAND_VSX }
153 #define XB { 0xf800, PPC_OPERAND_VSX }
154 #define XC { 0xf800, PPC_OPERAND_VSX }
155 #define XFL_L { 0x2000000, PPC_OPERAND_OPTIONAL }
156 #define XS { 0x3e00000, PPC_OPERAND_VSX }
160 m_decoder_table
= new DecoderInfo
*[kDecoderSize
];
161 m_decoder_table_size
= 0;
162 for (int i
= 0; i
< kDecoderSize
; i
++) {
163 m_decoder_table
[i
] = nullptr;
166 m_opcode_index_table
= new DecoderInfo
*[kTotalOpcodes
];
168 #define DE(name, op, type, mnemonic, ... ) \
169 DecoderInfo instr_##name { \
170 OpcodeNames::op_##name, \
175 setInstruction(instr_##name);
179 // Create index based on instruction opcode
291 std::string
DecoderInfo::toString() const {
292 if (m_form
== Form::kInvalid
) return ".long " + std::to_string(m_image
);
293 if (isNop()) return "nop";
296 std::string instr
= m_mnemonic
+ " ";
298 bool hasParen
= false;
299 for (auto oper
: m_operands
) {
300 auto op
= m_image
& oper
.m_mask
;
301 if (!(oper
.m_flags
& PPC_OPERAND_NOSHIFT
)) op
>>= oper
.operandShift();
302 auto toHex
= [] (std::string
& instruction
, intptr_t n
) {
303 std::stringstream stringStream
;
305 stringStream
<< "-0x";
307 } else stringStream
<< "0x";
308 stringStream
<< std::hex
<< n
;
309 instruction
+= stringStream
.str();
311 if (oper
.m_flags
& PPC_OPERAND_GPR
) { instr
+= "r"; }
312 if (oper
.m_flags
& PPC_OPERAND_GPR_0
) { if (op
!= 0) instr
+= "r"; }
313 if (oper
.m_flags
& PPC_OPERAND_FPR
) { instr
+= "f"; }
314 if (oper
.m_flags
& PPC_OPERAND_VR
) { instr
+= "vs"; }
315 if (oper
.m_flags
& PPC_OPERAND_RELATIVE
) {
316 // print branch target instead of the relative offset
317 int32_t n
= static_cast<int32_t>(op
<< 6) >> 6; // extend sign
318 toHex(instr
, reinterpret_cast<intptr_t>(m_ip
) + n
);
319 } else if (oper
.m_flags
& PPC_OPERAND_SIGNED
) {
320 int16_t n
= static_cast<int16_t>(op
);
322 } else if (oper
.m_flags
& PPC_OPERAND_UNSIGNED
) {
325 instr
+= std::to_string(op
);
328 // Sticky boolean: doesn't clear after set
329 hasParen
|= (oper
.m_flags
& PPC_OPERAND_PAREN
);
330 instr
+= hasParen
? "(" : ",";
332 // remove the "(" or "," at the end. It should not be there.
334 // close that parentheses now.
335 if (hasParen
) instr
+= ")";
339 bool DecoderInfo::isException() const {
340 // trap is a mnemonic of tw 31,0,0
341 if ((m_form
== Form::kX
) && (m_opn
== OpcodeNames::op_tw
)) {
343 xform
.instruction
= m_image
;
344 if ((31 == xform
.RT
) && (!xform
.RA
) && (!xform
.RB
) && (4 == xform
.XO
)) {
352 bool DecoderInfo::isNop() const {
353 // no-op is a mnemonic of ori 0,0,0
354 if ((m_form
== Form::kD
) && (m_opn
== OpcodeNames::op_ori
)) {
356 dform
.instruction
= m_image
;
357 if ((!dform
.D
) && (!dform
.RA
) && (!dform
.RT
)) {
365 bool DecoderInfo::isLd(bool toc
) const {
366 if ((m_form
== Form::kDS
) && (m_opn
== OpcodeNames::op_ld
)) {
367 if (!toc
) return true;
370 dsform
.instruction
= m_image
;
371 if (Reg64(dsform
.RA
) == reg::r2
) {
379 * Auxiliary for isLwz and isAddis
381 bool DecoderInfo::isDformOp(OpcodeNames opn
, bool toc
) const {
382 if ((m_form
== Form::kD
) && (m_opn
== opn
)) {
383 if (!toc
) return true;
386 dform
.instruction
= m_image
;
387 if (Reg64(dform
.RA
) == reg::r2
) {
394 bool DecoderInfo::isLwz(bool toc
) const {
395 return isDformOp(OpcodeNames::op_lwz
, toc
);
398 bool DecoderInfo::isAddis(bool toc
) const {
399 return isDformOp(OpcodeNames::op_addis
, toc
);
402 bool DecoderInfo::isOffsetBranch(AllowCond ac
/* = AllowCond::Any */) const {
404 // b, bl - unconditional branches
405 // And also, if condition is "branch always" (BO field is 1x1xx):
409 // b, bl - unconditional branches
410 // bc, bcl - conditional branches
413 // bc, bcl - conditional branches and it can't be "branch always"
415 // (based on the branch instructions defined on this Decoder)
417 case OpcodeNames::op_b
:
418 case OpcodeNames::op_bl
:
419 return (AllowCond::OnlyCond
!= ac
);
421 case OpcodeNames::op_bc
:
422 case OpcodeNames::op_bcl
:
424 // checking if the condition is "always branch", then it counts as an
425 // unconditional branch
426 assert(m_form
== Form::kB
);
428 bform
.instruction
= m_image
;
429 BranchParams
uncondition_bp(BranchConditions::Always
);
431 if (uncondition_bp
.bo() == bform
.BO
) {
432 // not acceptable if it was required to have a condition
433 return (AllowCond::OnlyCond
!= ac
);
435 // it's a conditional branch
436 return (AllowCond::OnlyUncond
!= ac
);
447 * True if bcctrl (as "branch always" condition) or bl
450 bool DecoderInfo::isBranchWithLR() const {
452 case OpcodeNames::op_bcctrl
:
454 // checking if the condition is "always branch", then it counts as an
455 // unconditional branch
456 assert(m_form
== Form::kXL
);
458 xlform
.instruction
= m_image
;
459 BranchParams
uncondition_bp(BranchConditions::Always
);
460 return xlform
.BT
== uncondition_bp
.bo();
463 case OpcodeNames::op_bl
:
472 bool DecoderInfo::isRegisterBranch(AllowCond ac
/* = AllowCond::Any */) const {
477 // bcctr, bcctrl - only if condition is "branch always" (BO field: 1x1xx)
480 // bcctr, bcctrl - only if condition is NOT "branch always" (BO field)
482 // NOTE: not considering bclr as it's more like a return than a branch
484 case OpcodeNames::op_bcctr
:
485 case OpcodeNames::op_bcctrl
:
487 // checking if the condition is "always branch", then it counts as an
488 // unconditional branch
489 assert(m_form
== Form::kXL
);
491 xlform
.instruction
= m_image
;
492 BranchParams
uncondition_bp(BranchConditions::Always
);
493 if (uncondition_bp
.bo() == xlform
.BT
) {
494 // unconditional is only allowed if it's not OnlyCond
495 return (AllowCond::OnlyCond
!= ac
);
497 // it's a conditional branch
498 return (AllowCond::OnlyUncond
!= ac
);
508 bool DecoderInfo::isClearSignBit() const {
509 // clrldi is a mnemonic to rldicl when
510 if (m_opn
== OpcodeNames::op_rldicl
) {
512 instr_md
.instruction
= m_image
;
513 if ((instr_md
.SH
== 0) && (instr_md
.sh
== 0)) {
514 // it's the clrldi mnemonic!
515 switch (instr_md
.MB
) {
530 * Check if instruction is addi or add, which changes the stack pointer. These
531 * instructions are created by lea, since on PPC64 there is no Lea instruction.
533 bool DecoderInfo::isSpOffsetInstr() const {
534 if (((m_form
== Form::kD
) && (m_opn
== OpcodeNames::op_addi
))
535 || ((m_form
== Form::kXO
) && (m_opn
== OpcodeNames::op_add
))) {
542 * Look for the offset from instructions like addi or add, which was created by
543 * the lower of the Lea instruction.
545 int32_t DecoderInfo::offset() const {
546 always_assert(m_form
== Form::kD
&& "Instruction not expected.");
548 instr_d
.instruction
= m_image
;
549 // As the instruction is known, the immediate is a signed number of
550 // 16bits, so to consider the sign, it must be casted to int16_t.
551 return static_cast<int16_t>(instr_d
.D
);
555 * Return offset of a branch by offset like b or bc.
557 int32_t DecoderInfo::branchOffset() const {
560 case OpcodeNames::op_b
:
561 case OpcodeNames::op_bl
:
564 iform
.instruction
= m_image
;
566 auto signBit
= 1 << 25;
567 auto li
= iform
.LI
<< 2;
568 // sign-extend 32-bits from a 26-bit value, if negative
569 offset
= (signBit
& li
) ? ((int32_t(-1) - ((1<<26)-1)) | li
) : li
;
572 case OpcodeNames::op_bc
:
573 case OpcodeNames::op_bcl
:
576 bform
.instruction
= m_image
;
577 offset
= int16_t(bform
.BD
<< 2);
581 always_assert(false && "Instruction not expected.");
588 * Set offset of a branch by offset like b or bc. Return that instruction
590 PPC64Instr
DecoderInfo::setBranchOffset(int32_t offset
) const {
592 case OpcodeNames::op_b
:
593 case OpcodeNames::op_bl
:
596 iform
.instruction
= m_image
;
597 iform
.LI
= offset
>> 2;
598 return iform
.instruction
;
601 case OpcodeNames::op_bc
:
602 case OpcodeNames::op_bcl
:
605 bform
.instruction
= m_image
;
606 bform
.BD
= offset
>> 2;
607 return bform
.instruction
;
611 always_assert(false && "Instruction not expected.");
617 * Find the offset from instructions like ld, which was created by
620 int16_t DecoderInfo::offsetDS() const {
621 always_assert(m_form
== Form::kDS
&& "Instruction not expected.");
623 instr_d
.instruction
= m_image
;
625 return static_cast<int16_t>(instr_d
.DS
<< 2);
629 * Find the offset from instructions like lwz.
631 int16_t DecoderInfo::offsetD() const {
632 always_assert(m_form
== Form::kD
&& "Instruction not expected.");
634 instr_d
.instruction
= m_image
;
636 return static_cast<int16_t>(instr_d
.D
);
639 ///////////////////////////////////////////////////////////////////////////////
641 const DecoderInfo
Decoder::decode(const PPC64Instr
* const ip
) {
643 PPC64Instr decoded_instr
, operand
, opcode_index
, opcode_size
;
644 PPC64Instr opcode
= *ip
& kOpcodeMask
;
646 // Get index and size for the opcode.
647 opcode_index
= (opcode_index_map
.find(opcode
))->second
;
648 opcode_size
= (opcode_size_map
.find(opcode
))->second
;
650 // To decode a instruction we extract the decoder fields
651 // masking the instruction and test if it 'hits' the decoder table.
652 for (size_t i
= 0; i
< sizeof(DecoderList
)/sizeof(PPC64Instr
); i
++) {
653 decoded_instr
= *ip
& DecoderList
[i
];
654 operand
= decoded_instr
& kOperandMask
;
656 // Search the instruction for the current mask
657 position
= searchInstr(opcode_index
, opcode_size
, operand
);
659 // If instruction found, return it.
660 if (position
!= -1) {
661 DecoderInfo pdi
= *m_decoder_table
[position
];
662 assert(pdi
.opcode() == decoded_instr
);
663 pdi
.instruction_image(*ip
);
669 // invalid instruction! Use fallback.
670 DecoderInfo ret
= getInvalid();
676 * Binary search when looking for the operand
678 int32_t Decoder::searchInstr(int32_t opd_index
,
680 PPC64Instr search
) const {
682 auto first
= opd_index
;
683 auto last
= opd_index
+ opc_size
-1;
684 auto middle
= (first
+ last
)/2;
686 while (first
<= last
) {
687 operand
= m_decoder_table
[middle
]->opcode() & kOperandMask
;
688 if (operand
< search
) {
691 else if (operand
== search
) {
697 middle
= (first
+ last
)/2;
703 } // namespace ppc64_ams