Home | History | Annotate | Download | only in ppc
      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 #include "src/compiler/code-generator.h"
      6 
      7 #include "src/assembler-inl.h"
      8 #include "src/callable.h"
      9 #include "src/compiler/code-generator-impl.h"
     10 #include "src/compiler/gap-resolver.h"
     11 #include "src/compiler/node-matchers.h"
     12 #include "src/compiler/osr.h"
     13 #include "src/double.h"
     14 #include "src/optimized-compilation-info.h"
     15 #include "src/ppc/macro-assembler-ppc.h"
     16 #include "src/wasm/wasm-objects.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 namespace compiler {
     21 
     22 #define __ tasm()->
     23 
     24 #define kScratchReg r11
     25 
     26 
     27 // Adds PPC-specific methods to convert InstructionOperands.
     28 class PPCOperandConverter final : public InstructionOperandConverter {
     29  public:
     30   PPCOperandConverter(CodeGenerator* gen, Instruction* instr)
     31       : InstructionOperandConverter(gen, instr) {}
     32 
     33   size_t OutputCount() { return instr_->OutputCount(); }
     34 
     35   RCBit OutputRCBit() const {
     36     switch (instr_->flags_mode()) {
     37       case kFlags_branch:
     38       case kFlags_branch_and_poison:
     39       case kFlags_deoptimize:
     40       case kFlags_deoptimize_and_poison:
     41       case kFlags_set:
     42       case kFlags_trap:
     43         return SetRC;
     44       case kFlags_none:
     45         return LeaveRC;
     46     }
     47     UNREACHABLE();
     48   }
     49 
     50   bool CompareLogical() const {
     51     switch (instr_->flags_condition()) {
     52       case kUnsignedLessThan:
     53       case kUnsignedGreaterThanOrEqual:
     54       case kUnsignedLessThanOrEqual:
     55       case kUnsignedGreaterThan:
     56         return true;
     57       default:
     58         return false;
     59     }
     60     UNREACHABLE();
     61   }
     62 
     63   Operand InputImmediate(size_t index) {
     64     Constant constant = ToConstant(instr_->InputAt(index));
     65     switch (constant.type()) {
     66       case Constant::kInt32:
     67         return Operand(constant.ToInt32());
     68       case Constant::kFloat32:
     69         return Operand::EmbeddedNumber(constant.ToFloat32());
     70       case Constant::kFloat64:
     71         return Operand::EmbeddedNumber(constant.ToFloat64().value());
     72       case Constant::kInt64:
     73 #if V8_TARGET_ARCH_PPC64
     74         return Operand(constant.ToInt64());
     75 #endif
     76       case Constant::kExternalReference:
     77       case Constant::kHeapObject:
     78       case Constant::kRpoNumber:
     79         break;
     80     }
     81     UNREACHABLE();
     82   }
     83 
     84   MemOperand MemoryOperand(AddressingMode* mode, size_t* first_index) {
     85     const size_t index = *first_index;
     86     *mode = AddressingModeField::decode(instr_->opcode());
     87     switch (*mode) {
     88       case kMode_None:
     89         break;
     90       case kMode_MRI:
     91         *first_index += 2;
     92         return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
     93       case kMode_MRR:
     94         *first_index += 2;
     95         return MemOperand(InputRegister(index + 0), InputRegister(index + 1));
     96     }
     97     UNREACHABLE();
     98   }
     99 
    100   MemOperand MemoryOperand(AddressingMode* mode, size_t first_index = 0) {
    101     return MemoryOperand(mode, &first_index);
    102   }
    103 
    104   MemOperand ToMemOperand(InstructionOperand* op) const {
    105     DCHECK_NOT_NULL(op);
    106     DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
    107     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
    108   }
    109 
    110   MemOperand SlotToMemOperand(int slot) const {
    111     FrameOffset offset = frame_access_state()->GetFrameOffset(slot);
    112     return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
    113   }
    114 };
    115 
    116 
    117 static inline bool HasRegisterInput(Instruction* instr, size_t index) {
    118   return instr->InputAt(index)->IsRegister();
    119 }
    120 
    121 
    122 namespace {
    123 
    124 class OutOfLineRecordWrite final : public OutOfLineCode {
    125  public:
    126   OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset,
    127                        Register value, Register scratch0, Register scratch1,
    128                        RecordWriteMode mode)
    129       : OutOfLineCode(gen),
    130         object_(object),
    131         offset_(offset),
    132         offset_immediate_(0),
    133         value_(value),
    134         scratch0_(scratch0),
    135         scratch1_(scratch1),
    136         mode_(mode),
    137         must_save_lr_(!gen->frame_access_state()->has_frame()),
    138         zone_(gen->zone()) {}
    139 
    140   OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
    141                        Register value, Register scratch0, Register scratch1,
    142                        RecordWriteMode mode)
    143       : OutOfLineCode(gen),
    144         object_(object),
    145         offset_(no_reg),
    146         offset_immediate_(offset),
    147         value_(value),
    148         scratch0_(scratch0),
    149         scratch1_(scratch1),
    150         mode_(mode),
    151         must_save_lr_(!gen->frame_access_state()->has_frame()),
    152         zone_(gen->zone()) {}
    153 
    154   void SaveRegisters(RegList registers) {
    155     DCHECK_LT(0, NumRegs(registers));
    156     RegList regs = 0;
    157     for (int i = 0; i < Register::kNumRegisters; ++i) {
    158       if ((registers >> i) & 1u) {
    159         regs |= Register::from_code(i).bit();
    160       }
    161     }
    162 
    163     __ MultiPush(regs);
    164   }
    165 
    166   void RestoreRegisters(RegList registers) {
    167     DCHECK_LT(0, NumRegs(registers));
    168     RegList regs = 0;
    169     for (int i = 0; i < Register::kNumRegisters; ++i) {
    170       if ((registers >> i) & 1u) {
    171         regs |= Register::from_code(i).bit();
    172       }
    173     }
    174     __ MultiPop(regs);
    175   }
    176 
    177   void Generate() final {
    178     ConstantPoolUnavailableScope constant_pool_unavailable(tasm());
    179     if (mode_ > RecordWriteMode::kValueIsPointer) {
    180       __ JumpIfSmi(value_, exit());
    181     }
    182     __ CheckPageFlag(value_, scratch0_,
    183                      MemoryChunk::kPointersToHereAreInterestingMask, eq,
    184                      exit());
    185     if (offset_ == no_reg) {
    186       __ addi(scratch1_, object_, Operand(offset_immediate_));
    187     } else {
    188       DCHECK_EQ(0, offset_immediate_);
    189       __ add(scratch1_, object_, offset_);
    190     }
    191     RememberedSetAction const remembered_set_action =
    192         mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
    193                                              : OMIT_REMEMBERED_SET;
    194     SaveFPRegsMode const save_fp_mode =
    195         frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
    196     if (must_save_lr_) {
    197       // We need to save and restore lr if the frame was elided.
    198       __ mflr(scratch0_);
    199       __ Push(scratch0_);
    200     }
    201     __ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
    202                            save_fp_mode);
    203     if (must_save_lr_) {
    204       // We need to save and restore lr if the frame was elided.
    205       __ Pop(scratch0_);
    206       __ mtlr(scratch0_);
    207     }
    208   }
    209 
    210  private:
    211   Register const object_;
    212   Register const offset_;
    213   int32_t const offset_immediate_;  // Valid if offset_ == no_reg.
    214   Register const value_;
    215   Register const scratch0_;
    216   Register const scratch1_;
    217   RecordWriteMode const mode_;
    218   bool must_save_lr_;
    219   Zone* zone_;
    220 };
    221 
    222 
    223 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
    224   switch (condition) {
    225     case kEqual:
    226       return eq;
    227     case kNotEqual:
    228       return ne;
    229     case kSignedLessThan:
    230     case kUnsignedLessThan:
    231       return lt;
    232     case kSignedGreaterThanOrEqual:
    233     case kUnsignedGreaterThanOrEqual:
    234       return ge;
    235     case kSignedLessThanOrEqual:
    236     case kUnsignedLessThanOrEqual:
    237       return le;
    238     case kSignedGreaterThan:
    239     case kUnsignedGreaterThan:
    240       return gt;
    241     case kOverflow:
    242       // Overflow checked for add/sub only.
    243       switch (op) {
    244 #if V8_TARGET_ARCH_PPC64
    245         case kPPC_Add32:
    246         case kPPC_Add64:
    247         case kPPC_Sub:
    248 #endif
    249         case kPPC_AddWithOverflow32:
    250         case kPPC_SubWithOverflow32:
    251           return lt;
    252         default:
    253           break;
    254       }
    255       break;
    256     case kNotOverflow:
    257       switch (op) {
    258 #if V8_TARGET_ARCH_PPC64
    259         case kPPC_Add32:
    260         case kPPC_Add64:
    261         case kPPC_Sub:
    262 #endif
    263         case kPPC_AddWithOverflow32:
    264         case kPPC_SubWithOverflow32:
    265           return ge;
    266         default:
    267           break;
    268       }
    269       break;
    270     default:
    271       break;
    272   }
    273   UNREACHABLE();
    274 }
    275 
    276 void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen, Instruction* instr,
    277                                    PPCOperandConverter& i) {
    278   const MemoryAccessMode access_mode =
    279       static_cast<MemoryAccessMode>(MiscField::decode(instr->opcode()));
    280   if (access_mode == kMemoryAccessPoisoned) {
    281     Register value = i.OutputRegister();
    282     codegen->tasm()->and_(value, value, kSpeculationPoisonRegister);
    283   }
    284 }
    285 
    286 }  // namespace
    287 
    288 #define ASSEMBLE_FLOAT_UNOP_RC(asm_instr, round)                     \
    289   do {                                                               \
    290     __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
    291                  i.OutputRCBit());                                   \
    292     if (round) {                                                     \
    293       __ frsp(i.OutputDoubleRegister(), i.OutputDoubleRegister());   \
    294     }                                                                \
    295   } while (0)
    296 
    297 #define ASSEMBLE_FLOAT_BINOP_RC(asm_instr, round)                    \
    298   do {                                                               \
    299     __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
    300                  i.InputDoubleRegister(1), i.OutputRCBit());         \
    301     if (round) {                                                     \
    302       __ frsp(i.OutputDoubleRegister(), i.OutputDoubleRegister());   \
    303     }                                                                \
    304   } while (0)
    305 
    306 #define ASSEMBLE_BINOP(asm_instr_reg, asm_instr_imm)           \
    307   do {                                                         \
    308     if (HasRegisterInput(instr, 1)) {                          \
    309       __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \
    310                        i.InputRegister(1));                    \
    311     } else {                                                   \
    312       __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \
    313                        i.InputImmediate(1));                   \
    314     }                                                          \
    315   } while (0)
    316 
    317 
    318 #define ASSEMBLE_BINOP_RC(asm_instr_reg, asm_instr_imm)        \
    319   do {                                                         \
    320     if (HasRegisterInput(instr, 1)) {                          \
    321       __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \
    322                        i.InputRegister(1), i.OutputRCBit());   \
    323     } else {                                                   \
    324       __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \
    325                        i.InputImmediate(1), i.OutputRCBit());  \
    326     }                                                          \
    327   } while (0)
    328 
    329 
    330 #define ASSEMBLE_BINOP_INT_RC(asm_instr_reg, asm_instr_imm)    \
    331   do {                                                         \
    332     if (HasRegisterInput(instr, 1)) {                          \
    333       __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \
    334                        i.InputRegister(1), i.OutputRCBit());   \
    335     } else {                                                   \
    336       __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \
    337                        i.InputInt32(1), i.OutputRCBit());      \
    338     }                                                          \
    339   } while (0)
    340 
    341 
    342 #define ASSEMBLE_ADD_WITH_OVERFLOW()                                    \
    343   do {                                                                  \
    344     if (HasRegisterInput(instr, 1)) {                                   \
    345       __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
    346                                 i.InputRegister(1), kScratchReg, r0);   \
    347     } else {                                                            \
    348       __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
    349                                 i.InputInt32(1), kScratchReg, r0);      \
    350     }                                                                   \
    351   } while (0)
    352 
    353 
    354 #define ASSEMBLE_SUB_WITH_OVERFLOW()                                    \
    355   do {                                                                  \
    356     if (HasRegisterInput(instr, 1)) {                                   \
    357       __ SubAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
    358                                 i.InputRegister(1), kScratchReg, r0);   \
    359     } else {                                                            \
    360       __ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
    361                                 -i.InputInt32(1), kScratchReg, r0);     \
    362     }                                                                   \
    363   } while (0)
    364 
    365 
    366 #if V8_TARGET_ARCH_PPC64
    367 #define ASSEMBLE_ADD_WITH_OVERFLOW32()         \
    368   do {                                         \
    369     ASSEMBLE_ADD_WITH_OVERFLOW();              \
    370     __ extsw(kScratchReg, kScratchReg, SetRC); \
    371   } while (0)
    372 
    373 #define ASSEMBLE_SUB_WITH_OVERFLOW32()         \
    374   do {                                         \
    375     ASSEMBLE_SUB_WITH_OVERFLOW();              \
    376     __ extsw(kScratchReg, kScratchReg, SetRC); \
    377   } while (0)
    378 #else
    379 #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW
    380 #define ASSEMBLE_SUB_WITH_OVERFLOW32 ASSEMBLE_SUB_WITH_OVERFLOW
    381 #endif
    382 
    383 
    384 #define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr)                        \
    385   do {                                                                 \
    386     const CRegister cr = cr0;                                          \
    387     if (HasRegisterInput(instr, 1)) {                                  \
    388       if (i.CompareLogical()) {                                        \
    389         __ cmpl_instr(i.InputRegister(0), i.InputRegister(1), cr);     \
    390       } else {                                                         \
    391         __ cmp_instr(i.InputRegister(0), i.InputRegister(1), cr);      \
    392       }                                                                \
    393     } else {                                                           \
    394       if (i.CompareLogical()) {                                        \
    395         __ cmpl_instr##i(i.InputRegister(0), i.InputImmediate(1), cr); \
    396       } else {                                                         \
    397         __ cmp_instr##i(i.InputRegister(0), i.InputImmediate(1), cr);  \
    398       }                                                                \
    399     }                                                                  \
    400     DCHECK_EQ(SetRC, i.OutputRCBit());                                 \
    401   } while (0)
    402 
    403 
    404 #define ASSEMBLE_FLOAT_COMPARE(cmp_instr)                                 \
    405   do {                                                                    \
    406     const CRegister cr = cr0;                                             \
    407     __ cmp_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1), cr); \
    408     DCHECK_EQ(SetRC, i.OutputRCBit());                                    \
    409   } while (0)
    410 
    411 
    412 #define ASSEMBLE_MODULO(div_instr, mul_instr)                        \
    413   do {                                                               \
    414     const Register scratch = kScratchReg;                            \
    415     __ div_instr(scratch, i.InputRegister(0), i.InputRegister(1));   \
    416     __ mul_instr(scratch, scratch, i.InputRegister(1));              \
    417     __ sub(i.OutputRegister(), i.InputRegister(0), scratch, LeaveOE, \
    418            i.OutputRCBit());                                         \
    419   } while (0)
    420 
    421 #define ASSEMBLE_FLOAT_MODULO()                                             \
    422   do {                                                                      \
    423     FrameScope scope(tasm(), StackFrame::MANUAL);                           \
    424     __ PrepareCallCFunction(0, 2, kScratchReg);                             \
    425     __ MovToFloatParameters(i.InputDoubleRegister(0),                       \
    426                             i.InputDoubleRegister(1));                      \
    427     __ CallCFunction(ExternalReference::mod_two_doubles_operation(), 0, 2); \
    428     __ MovFromFloatResult(i.OutputDoubleRegister());                        \
    429     DCHECK_EQ(LeaveRC, i.OutputRCBit());                                    \
    430   } while (0)
    431 
    432 #define ASSEMBLE_IEEE754_UNOP(name)                                            \
    433   do {                                                                         \
    434     /* TODO(bmeurer): We should really get rid of this special instruction, */ \
    435     /* and generate a CallAddress instruction instead. */                      \
    436     FrameScope scope(tasm(), StackFrame::MANUAL);                              \
    437     __ PrepareCallCFunction(0, 1, kScratchReg);                                \
    438     __ MovToFloatParameter(i.InputDoubleRegister(0));                          \
    439     __ CallCFunction(ExternalReference::ieee754_##name##_function(), 0, 1);    \
    440     /* Move the result in the double result register. */                       \
    441     __ MovFromFloatResult(i.OutputDoubleRegister());                           \
    442     DCHECK_EQ(LeaveRC, i.OutputRCBit());                                       \
    443   } while (0)
    444 
    445 #define ASSEMBLE_IEEE754_BINOP(name)                                           \
    446   do {                                                                         \
    447     /* TODO(bmeurer): We should really get rid of this special instruction, */ \
    448     /* and generate a CallAddress instruction instead. */                      \
    449     FrameScope scope(tasm(), StackFrame::MANUAL);                              \
    450     __ PrepareCallCFunction(0, 2, kScratchReg);                                \
    451     __ MovToFloatParameters(i.InputDoubleRegister(0),                          \
    452                             i.InputDoubleRegister(1));                         \
    453     __ CallCFunction(ExternalReference::ieee754_##name##_function(), 0, 2);    \
    454     /* Move the result in the double result register. */                       \
    455     __ MovFromFloatResult(i.OutputDoubleRegister());                           \
    456     DCHECK_EQ(LeaveRC, i.OutputRCBit());                                       \
    457   } while (0)
    458 
    459 #define ASSEMBLE_FLOAT_MAX()                                           \
    460   do {                                                                 \
    461     DoubleRegister left_reg = i.InputDoubleRegister(0);                \
    462     DoubleRegister right_reg = i.InputDoubleRegister(1);               \
    463     DoubleRegister result_reg = i.OutputDoubleRegister();              \
    464     Label check_nan_left, check_zero, return_left, return_right, done; \
    465     __ fcmpu(left_reg, right_reg);                                     \
    466     __ bunordered(&check_nan_left);                                    \
    467     __ beq(&check_zero);                                               \
    468     __ bge(&return_left);                                              \
    469     __ b(&return_right);                                               \
    470                                                                        \
    471     __ bind(&check_zero);                                              \
    472     __ fcmpu(left_reg, kDoubleRegZero);                                \
    473     /* left == right != 0. */                                          \
    474     __ bne(&return_left);                                              \
    475     /* At this point, both left and right are either 0 or -0. */       \
    476     __ fadd(result_reg, left_reg, right_reg);                          \
    477     __ b(&done);                                                       \
    478                                                                        \
    479     __ bind(&check_nan_left);                                          \
    480     __ fcmpu(left_reg, left_reg);                                      \
    481     /* left == NaN. */                                                 \
    482     __ bunordered(&return_left);                                       \
    483     __ bind(&return_right);                                            \
    484     if (right_reg != result_reg) {                                     \
    485       __ fmr(result_reg, right_reg);                                   \
    486     }                                                                  \
    487     __ b(&done);                                                       \
    488                                                                        \
    489     __ bind(&return_left);                                             \
    490     if (left_reg != result_reg) {                                      \
    491       __ fmr(result_reg, left_reg);                                    \
    492     }                                                                  \
    493     __ bind(&done);                                                    \
    494   } while (0)
    495 
    496 #define ASSEMBLE_FLOAT_MIN()                                              \
    497   do {                                                                    \
    498     DoubleRegister left_reg = i.InputDoubleRegister(0);                   \
    499     DoubleRegister right_reg = i.InputDoubleRegister(1);                  \
    500     DoubleRegister result_reg = i.OutputDoubleRegister();                 \
    501     Label check_nan_left, check_zero, return_left, return_right, done;    \
    502     __ fcmpu(left_reg, right_reg);                                        \
    503     __ bunordered(&check_nan_left);                                       \
    504     __ beq(&check_zero);                                                  \
    505     __ ble(&return_left);                                                 \
    506     __ b(&return_right);                                                  \
    507                                                                           \
    508     __ bind(&check_zero);                                                 \
    509     __ fcmpu(left_reg, kDoubleRegZero);                                   \
    510     /* left == right != 0. */                                             \
    511     __ bne(&return_left);                                                 \
    512     /* At this point, both left and right are either 0 or -0. */          \
    513     /* Min: The algorithm is: -((-L) + (-R)), which in case of L and R */ \
    514     /* being different registers is most efficiently expressed */         \
    515     /* as -((-L) - R). */                                                 \
    516     __ fneg(left_reg, left_reg);                                          \
    517     if (left_reg == right_reg) {                                          \
    518       __ fadd(result_reg, left_reg, right_reg);                           \
    519     } else {                                                              \
    520       __ fsub(result_reg, left_reg, right_reg);                           \
    521     }                                                                     \
    522     __ fneg(result_reg, result_reg);                                      \
    523     __ b(&done);                                                          \
    524                                                                           \
    525     __ bind(&check_nan_left);                                             \
    526     __ fcmpu(left_reg, left_reg);                                         \
    527     /* left == NaN. */                                                    \
    528     __ bunordered(&return_left);                                          \
    529                                                                           \
    530     __ bind(&return_right);                                               \
    531     if (right_reg != result_reg) {                                        \
    532       __ fmr(result_reg, right_reg);                                      \
    533     }                                                                     \
    534     __ b(&done);                                                          \
    535                                                                           \
    536     __ bind(&return_left);                                                \
    537     if (left_reg != result_reg) {                                         \
    538       __ fmr(result_reg, left_reg);                                       \
    539     }                                                                     \
    540     __ bind(&done);                                                       \
    541   } while (0)
    542 
    543 #define ASSEMBLE_LOAD_FLOAT(asm_instr, asm_instrx)    \
    544   do {                                                \
    545     DoubleRegister result = i.OutputDoubleRegister(); \
    546     AddressingMode mode = kMode_None;                 \
    547     MemOperand operand = i.MemoryOperand(&mode);      \
    548     if (mode == kMode_MRI) {                          \
    549       __ asm_instr(result, operand);                  \
    550     } else {                                          \
    551       __ asm_instrx(result, operand);                 \
    552     }                                                 \
    553     DCHECK_EQ(LeaveRC, i.OutputRCBit());              \
    554   } while (0)
    555 
    556 
    557 #define ASSEMBLE_LOAD_INTEGER(asm_instr, asm_instrx) \
    558   do {                                               \
    559     Register result = i.OutputRegister();            \
    560     AddressingMode mode = kMode_None;                \
    561     MemOperand operand = i.MemoryOperand(&mode);     \
    562     if (mode == kMode_MRI) {                         \
    563       __ asm_instr(result, operand);                 \
    564     } else {                                         \
    565       __ asm_instrx(result, operand);                \
    566     }                                                \
    567     DCHECK_EQ(LeaveRC, i.OutputRCBit());             \
    568   } while (0)
    569 
    570 
    571 #define ASSEMBLE_STORE_FLOAT32()                         \
    572   do {                                                   \
    573     size_t index = 0;                                    \
    574     AddressingMode mode = kMode_None;                    \
    575     MemOperand operand = i.MemoryOperand(&mode, &index); \
    576     DoubleRegister value = i.InputDoubleRegister(index); \
    577     /* removed frsp as instruction-selector checked */   \
    578     /* value to be kFloat32 */                           \
    579     if (mode == kMode_MRI) {                             \
    580       __ stfs(value, operand);                           \
    581     } else {                                             \
    582       __ stfsx(value, operand);                          \
    583     }                                                    \
    584     DCHECK_EQ(LeaveRC, i.OutputRCBit());                 \
    585   } while (0)
    586 
    587 
    588 #define ASSEMBLE_STORE_DOUBLE()                          \
    589   do {                                                   \
    590     size_t index = 0;                                    \
    591     AddressingMode mode = kMode_None;                    \
    592     MemOperand operand = i.MemoryOperand(&mode, &index); \
    593     DoubleRegister value = i.InputDoubleRegister(index); \
    594     if (mode == kMode_MRI) {                             \
    595       __ stfd(value, operand);                           \
    596     } else {                                             \
    597       __ stfdx(value, operand);                          \
    598     }                                                    \
    599     DCHECK_EQ(LeaveRC, i.OutputRCBit());                 \
    600   } while (0)
    601 
    602 
    603 #define ASSEMBLE_STORE_INTEGER(asm_instr, asm_instrx)    \
    604   do {                                                   \
    605     size_t index = 0;                                    \
    606     AddressingMode mode = kMode_None;                    \
    607     MemOperand operand = i.MemoryOperand(&mode, &index); \
    608     Register value = i.InputRegister(index);             \
    609     if (mode == kMode_MRI) {                             \
    610       __ asm_instr(value, operand);                      \
    611     } else {                                             \
    612       __ asm_instrx(value, operand);                     \
    613     }                                                    \
    614     DCHECK_EQ(LeaveRC, i.OutputRCBit());                 \
    615   } while (0)
    616 
    617 #if V8_TARGET_ARCH_PPC64
    618 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
    619 #define CleanUInt32(x) __ ClearLeftImm(x, x, Operand(32))
    620 #else
    621 #define CleanUInt32(x)
    622 #endif
    623 
    624 #define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr, asm_instrx) \
    625   do {                                                      \
    626     Label done;                                             \
    627     Register result = i.OutputRegister();                   \
    628     AddressingMode mode = kMode_None;                       \
    629     MemOperand operand = i.MemoryOperand(&mode);            \
    630     if (mode == kMode_MRI) {                                \
    631       __ asm_instr(result, operand);                        \
    632     } else {                                                \
    633       __ asm_instrx(result, operand);                       \
    634     }                                                       \
    635     __ lwsync();                                            \
    636   } while (0)
    637 #define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr, asm_instrx) \
    638   do {                                                       \
    639     size_t index = 0;                                        \
    640     AddressingMode mode = kMode_None;                        \
    641     MemOperand operand = i.MemoryOperand(&mode, &index);     \
    642     Register value = i.InputRegister(index);                 \
    643     __ lwsync();                                             \
    644     if (mode == kMode_MRI) {                                 \
    645       __ asm_instr(value, operand);                          \
    646     } else {                                                 \
    647       __ asm_instrx(value, operand);                         \
    648     }                                                        \
    649     __ sync();                                               \
    650     DCHECK_EQ(LeaveRC, i.OutputRCBit());                     \
    651   } while (0)
    652 #define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(load_instr, store_instr)       \
    653   do {                                                                  \
    654     Label exchange;                                                     \
    655     __ bind(&exchange);                                                 \
    656     __ load_instr(i.OutputRegister(0),                                  \
    657                   MemOperand(i.InputRegister(0), i.InputRegister(1)));  \
    658     __ store_instr(i.InputRegister(2),                                  \
    659                    MemOperand(i.InputRegister(0), i.InputRegister(1))); \
    660     __ bne(&exchange, cr0);                                             \
    661   } while (0)
    662 
    663 #define ASSEMBLE_ATOMIC_BINOP(bin_inst, load_inst, store_inst)                 \
    664   do {                                                                         \
    665     MemOperand operand = MemOperand(i.InputRegister(0), i.InputRegister(1));   \
    666     Label binop;                                                               \
    667     __ bind(&binop);                                                           \
    668     __ load_inst(i.OutputRegister(), operand);                                 \
    669     __ bin_inst(i.InputRegister(2), i.OutputRegister(), i.InputRegister(2));   \
    670     __ store_inst(i.InputRegister(2), operand);                                \
    671     __ bne(&binop, cr0);                                                       \
    672   } while (false)
    673 
    674 #define ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(bin_inst, load_inst,                    \
    675                                        store_inst, ext_instr)                  \
    676   do {                                                                         \
    677     MemOperand operand = MemOperand(i.InputRegister(0), i.InputRegister(1));   \
    678     Label binop;                                                               \
    679     __ bind(&binop);                                                           \
    680     __ load_inst(i.OutputRegister(), operand);                                 \
    681     __ ext_instr(i.OutputRegister(), i.OutputRegister());                      \
    682     __ bin_inst(i.InputRegister(2), i.OutputRegister(), i.InputRegister(2));   \
    683     __ store_inst(i.InputRegister(2), operand);                                \
    684     __ bne(&binop, cr0);                                                       \
    685   } while (false)
    686 
    687 #define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmp_inst, load_inst, store_inst)      \
    688   do {                                                                         \
    689     MemOperand operand = MemOperand(i.InputRegister(0), i.InputRegister(1));   \
    690     Label loop;                                                                \
    691     Label exit;                                                                \
    692     __ bind(&loop);                                                            \
    693     __ load_inst(i.OutputRegister(), operand);                                 \
    694     __ cmp_inst(i.OutputRegister(), i.InputRegister(2));                       \
    695     __ bne(&exit, cr0);                                                        \
    696     __ store_inst(i.InputRegister(3), operand);                                \
    697     __ bne(&loop, cr0);                                                        \
    698     __ bind(&exit);                                                            \
    699   } while (false)
    700 
    701 #define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_SIGN_EXT(cmp_inst, load_inst,         \
    702                                                   store_inst, ext_instr)       \
    703   do {                                                                         \
    704     MemOperand operand = MemOperand(i.InputRegister(0), i.InputRegister(1));   \
    705     Label loop;                                                                \
    706     Label exit;                                                                \
    707     __ bind(&loop);                                                            \
    708     __ load_inst(i.OutputRegister(), operand);                                 \
    709     __ ext_instr(i.OutputRegister(), i.OutputRegister());                      \
    710     __ cmp_inst(i.OutputRegister(), i.InputRegister(2));                       \
    711     __ bne(&exit, cr0);                                                        \
    712     __ store_inst(i.InputRegister(3), operand);                                \
    713     __ bne(&loop, cr0);                                                        \
    714     __ bind(&exit);                                                            \
    715   } while (false)
    716 
    717 void CodeGenerator::AssembleDeconstructFrame() {
    718   __ LeaveFrame(StackFrame::MANUAL);
    719 }
    720 
    721 void CodeGenerator::AssemblePrepareTailCall() {
    722   if (frame_access_state()->has_frame()) {
    723     __ RestoreFrameStateForTailCall();
    724   }
    725   frame_access_state()->SetFrameAccessToSP();
    726 }
    727 
    728 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
    729                                                      Register scratch1,
    730                                                      Register scratch2,
    731                                                      Register scratch3) {
    732   DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
    733   Label done;
    734 
    735   // Check if current frame is an arguments adaptor frame.
    736   __ LoadP(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset));
    737   __ cmpi(scratch1,
    738           Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
    739   __ bne(&done);
    740 
    741   // Load arguments count from current arguments adaptor frame (note, it
    742   // does not include receiver).
    743   Register caller_args_count_reg = scratch1;
    744   __ LoadP(caller_args_count_reg,
    745            MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
    746   __ SmiUntag(caller_args_count_reg);
    747 
    748   ParameterCount callee_args_count(args_reg);
    749   __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
    750                         scratch3);
    751   __ bind(&done);
    752 }
    753 
    754 namespace {
    755 
    756 void FlushPendingPushRegisters(TurboAssembler* tasm,
    757                                FrameAccessState* frame_access_state,
    758                                ZoneVector<Register>* pending_pushes) {
    759   switch (pending_pushes->size()) {
    760     case 0:
    761       break;
    762     case 1:
    763       tasm->Push((*pending_pushes)[0]);
    764       break;
    765     case 2:
    766       tasm->Push((*pending_pushes)[0], (*pending_pushes)[1]);
    767       break;
    768     case 3:
    769       tasm->Push((*pending_pushes)[0], (*pending_pushes)[1],
    770                  (*pending_pushes)[2]);
    771       break;
    772     default:
    773       UNREACHABLE();
    774       break;
    775   }
    776   frame_access_state->IncreaseSPDelta(pending_pushes->size());
    777   pending_pushes->clear();
    778 }
    779 
    780 void AdjustStackPointerForTailCall(
    781     TurboAssembler* tasm, FrameAccessState* state, int new_slot_above_sp,
    782     ZoneVector<Register>* pending_pushes = nullptr,
    783     bool allow_shrinkage = true) {
    784   int current_sp_offset = state->GetSPToFPSlotCount() +
    785                           StandardFrameConstants::kFixedSlotCountAboveFp;
    786   int stack_slot_delta = new_slot_above_sp - current_sp_offset;
    787   if (stack_slot_delta > 0) {
    788     if (pending_pushes != nullptr) {
    789       FlushPendingPushRegisters(tasm, state, pending_pushes);
    790     }
    791     tasm->Add(sp, sp, -stack_slot_delta * kPointerSize, r0);
    792     state->IncreaseSPDelta(stack_slot_delta);
    793   } else if (allow_shrinkage && stack_slot_delta < 0) {
    794     if (pending_pushes != nullptr) {
    795       FlushPendingPushRegisters(tasm, state, pending_pushes);
    796     }
    797     tasm->Add(sp, sp, -stack_slot_delta * kPointerSize, r0);
    798     state->IncreaseSPDelta(stack_slot_delta);
    799   }
    800 }
    801 
    802 }  // namespace
    803 
    804 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
    805                                               int first_unused_stack_slot) {
    806   ZoneVector<MoveOperands*> pushes(zone());
    807   GetPushCompatibleMoves(instr, kRegisterPush, &pushes);
    808 
    809   if (!pushes.empty() &&
    810       (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
    811        first_unused_stack_slot)) {
    812     PPCOperandConverter g(this, instr);
    813     ZoneVector<Register> pending_pushes(zone());
    814     for (auto move : pushes) {
    815       LocationOperand destination_location(
    816           LocationOperand::cast(move->destination()));
    817       InstructionOperand source(move->source());
    818       AdjustStackPointerForTailCall(
    819           tasm(), frame_access_state(),
    820           destination_location.index() - pending_pushes.size(),
    821           &pending_pushes);
    822       // Pushes of non-register data types are not supported.
    823       DCHECK(source.IsRegister());
    824       LocationOperand source_location(LocationOperand::cast(source));
    825       pending_pushes.push_back(source_location.GetRegister());
    826       // TODO(arm): We can push more than 3 registers at once. Add support in
    827       // the macro-assembler for pushing a list of registers.
    828       if (pending_pushes.size() == 3) {
    829         FlushPendingPushRegisters(tasm(), frame_access_state(),
    830                                   &pending_pushes);
    831       }
    832       move->Eliminate();
    833     }
    834     FlushPendingPushRegisters(tasm(), frame_access_state(), &pending_pushes);
    835   }
    836   AdjustStackPointerForTailCall(tasm(), frame_access_state(),
    837                                 first_unused_stack_slot, nullptr, false);
    838 }
    839 
    840 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
    841                                              int first_unused_stack_slot) {
    842   AdjustStackPointerForTailCall(tasm(), frame_access_state(),
    843                                 first_unused_stack_slot);
    844 }
    845 
    846 // Check that {kJavaScriptCallCodeStartRegister} is correct.
    847 void CodeGenerator::AssembleCodeStartRegisterCheck() {
    848   Register scratch = kScratchReg;
    849   __ ComputeCodeStartAddress(scratch);
    850   __ cmp(scratch, kJavaScriptCallCodeStartRegister);
    851   __ Assert(eq, AbortReason::kWrongFunctionCodeStart);
    852 }
    853 
    854 // Check if the code object is marked for deoptimization. If it is, then it
    855 // jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
    856 // to:
    857 //    1. read from memory the word that contains that bit, which can be found in
    858 //       the flags in the referenced {CodeDataContainer} object;
    859 //    2. test kMarkedForDeoptimizationBit in those flags; and
    860 //    3. if it is not zero then it jumps to the builtin.
    861 void CodeGenerator::BailoutIfDeoptimized() {
    862   if (FLAG_debug_code) {
    863     // Check that {kJavaScriptCallCodeStartRegister} is correct.
    864     __ ComputeCodeStartAddress(ip);
    865     __ cmp(ip, kJavaScriptCallCodeStartRegister);
    866     __ Assert(eq, AbortReason::kWrongFunctionCodeStart);
    867   }
    868 
    869   int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
    870   __ LoadP(r11, MemOperand(kJavaScriptCallCodeStartRegister, offset));
    871   __ LoadWordArith(
    872       r11, FieldMemOperand(r11, CodeDataContainer::kKindSpecificFlagsOffset));
    873   __ TestBit(r11, Code::kMarkedForDeoptimizationBit);
    874   // Ensure we're not serializing (otherwise we'd need to use an indirection to
    875   // access the builtin below).
    876   DCHECK(!isolate()->ShouldLoadConstantsFromRootList());
    877   Handle<Code> code = isolate()->builtins()->builtin_handle(
    878       Builtins::kCompileLazyDeoptimizedCode);
    879   __ Jump(code, RelocInfo::CODE_TARGET, ne, cr0);
    880 }
    881 
    882 void CodeGenerator::GenerateSpeculationPoisonFromCodeStartRegister() {
    883   Register scratch = kScratchReg;
    884 
    885   __ ComputeCodeStartAddress(scratch);
    886 
    887   // Calculate a mask which has all bits set in the normal case, but has all
    888   // bits cleared if we are speculatively executing the wrong PC.
    889   __ cmp(kJavaScriptCallCodeStartRegister, scratch);
    890   __ li(scratch, Operand::Zero());
    891   __ notx(kSpeculationPoisonRegister, scratch);
    892   __ isel(eq, kSpeculationPoisonRegister,
    893           kSpeculationPoisonRegister, scratch);
    894 }
    895 
    896 void CodeGenerator::AssembleRegisterArgumentPoisoning() {
    897   __ and_(kJSFunctionRegister, kJSFunctionRegister, kSpeculationPoisonRegister);
    898   __ and_(kContextRegister, kContextRegister, kSpeculationPoisonRegister);
    899   __ and_(sp, sp, kSpeculationPoisonRegister);
    900 }
    901 
    902 // Assembles an instruction after register allocation, producing machine code.
    903 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
    904     Instruction* instr) {
    905   PPCOperandConverter i(this, instr);
    906   ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode());
    907 
    908   switch (opcode) {
    909     case kArchCallCodeObject: {
    910       v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
    911           tasm());
    912       if (HasRegisterInput(instr, 0)) {
    913         Register reg = i.InputRegister(0);
    914         DCHECK_IMPLIES(
    915             HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
    916             reg == kJavaScriptCallCodeStartRegister);
    917         __ addi(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
    918         __ Call(reg);
    919       } else {
    920         __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
    921       }
    922       RecordCallPosition(instr);
    923       DCHECK_EQ(LeaveRC, i.OutputRCBit());
    924       frame_access_state()->ClearSPDelta();
    925       break;
    926     }
    927     case kArchCallWasmFunction: {
    928       // We must not share code targets for calls to builtins for wasm code, as
    929       // they might need to be patched individually.
    930       if (instr->InputAt(0)->IsImmediate()) {
    931         Constant constant = i.ToConstant(instr->InputAt(0));
    932 #ifdef V8_TARGET_ARCH_PPC64
    933         Address wasm_code = static_cast<Address>(constant.ToInt64());
    934 #else
    935         Address wasm_code = static_cast<Address>(constant.ToInt32());
    936 #endif
    937         __ Call(wasm_code, constant.rmode());
    938       } else {
    939         __ Call(i.InputRegister(0));
    940       }
    941       RecordCallPosition(instr);
    942       DCHECK_EQ(LeaveRC, i.OutputRCBit());
    943       frame_access_state()->ClearSPDelta();
    944       break;
    945     }
    946     case kArchTailCallCodeObjectFromJSFunction:
    947     case kArchTailCallCodeObject: {
    948       if (opcode == kArchTailCallCodeObjectFromJSFunction) {
    949         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
    950                                          i.TempRegister(0), i.TempRegister(1),
    951                                          i.TempRegister(2));
    952       }
    953       if (HasRegisterInput(instr, 0)) {
    954         Register reg = i.InputRegister(0);
    955         DCHECK_IMPLIES(
    956             HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
    957             reg == kJavaScriptCallCodeStartRegister);
    958         __ addi(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
    959         __ Jump(reg);
    960       } else {
    961         // We cannot use the constant pool to load the target since
    962         // we've already restored the caller's frame.
    963         ConstantPoolUnavailableScope constant_pool_unavailable(tasm());
    964         __ Jump(i.InputCode(0), RelocInfo::CODE_TARGET);
    965       }
    966       DCHECK_EQ(LeaveRC, i.OutputRCBit());
    967       frame_access_state()->ClearSPDelta();
    968       frame_access_state()->SetFrameAccessToDefault();
    969       break;
    970     }
    971     case kArchTailCallWasm: {
    972       // We must not share code targets for calls to builtins for wasm code, as
    973       // they might need to be patched individually.
    974       if (instr->InputAt(0)->IsImmediate()) {
    975         Constant constant = i.ToConstant(instr->InputAt(0));
    976 #ifdef V8_TARGET_ARCH_S390X
    977         Address wasm_code = static_cast<Address>(constant.ToInt64());
    978 #else
    979         Address wasm_code = static_cast<Address>(constant.ToInt32());
    980 #endif
    981         __ Jump(wasm_code, constant.rmode());
    982       } else {
    983         __ Jump(i.InputRegister(0));
    984       }
    985       DCHECK_EQ(LeaveRC, i.OutputRCBit());
    986       frame_access_state()->ClearSPDelta();
    987       frame_access_state()->SetFrameAccessToDefault();
    988       break;
    989     }
    990     case kArchTailCallAddress: {
    991       CHECK(!instr->InputAt(0)->IsImmediate());
    992       Register reg = i.InputRegister(0);
    993       DCHECK_IMPLIES(
    994           HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
    995           reg == kJavaScriptCallCodeStartRegister);
    996       __ Jump(reg);
    997       frame_access_state()->ClearSPDelta();
    998       frame_access_state()->SetFrameAccessToDefault();
    999       break;
   1000     }
   1001     case kArchCallJSFunction: {
   1002       v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
   1003           tasm());
   1004       Register func = i.InputRegister(0);
   1005       if (FLAG_debug_code) {
   1006         // Check the function's context matches the context argument.
   1007         __ LoadP(kScratchReg,
   1008                  FieldMemOperand(func, JSFunction::kContextOffset));
   1009         __ cmp(cp, kScratchReg);
   1010         __ Assert(eq, AbortReason::kWrongFunctionContext);
   1011       }
   1012       static_assert(kJavaScriptCallCodeStartRegister == r5, "ABI mismatch");
   1013       __ LoadP(r5, FieldMemOperand(func, JSFunction::kCodeOffset));
   1014       __ addi(r5, r5, Operand(Code::kHeaderSize - kHeapObjectTag));
   1015       __ Call(r5);
   1016       RecordCallPosition(instr);
   1017       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1018       frame_access_state()->ClearSPDelta();
   1019       break;
   1020     }
   1021     case kArchPrepareCallCFunction: {
   1022       int const num_parameters = MiscField::decode(instr->opcode());
   1023       __ PrepareCallCFunction(num_parameters, kScratchReg);
   1024       // Frame alignment requires using FP-relative frame addressing.
   1025       frame_access_state()->SetFrameAccessToFP();
   1026       break;
   1027     }
   1028     case kArchSaveCallerRegisters: {
   1029       fp_mode_ =
   1030           static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode()));
   1031       DCHECK(fp_mode_ == kDontSaveFPRegs || fp_mode_ == kSaveFPRegs);
   1032       // kReturnRegister0 should have been saved before entering the stub.
   1033       int bytes = __ PushCallerSaved(fp_mode_, kReturnRegister0);
   1034       DCHECK_EQ(0, bytes % kPointerSize);
   1035       DCHECK_EQ(0, frame_access_state()->sp_delta());
   1036       frame_access_state()->IncreaseSPDelta(bytes / kPointerSize);
   1037       DCHECK(!caller_registers_saved_);
   1038       caller_registers_saved_ = true;
   1039       break;
   1040     }
   1041     case kArchRestoreCallerRegisters: {
   1042       DCHECK(fp_mode_ ==
   1043              static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode())));
   1044       DCHECK(fp_mode_ == kDontSaveFPRegs || fp_mode_ == kSaveFPRegs);
   1045       // Don't overwrite the returned value.
   1046       int bytes = __ PopCallerSaved(fp_mode_, kReturnRegister0);
   1047       frame_access_state()->IncreaseSPDelta(-(bytes / kPointerSize));
   1048       DCHECK_EQ(0, frame_access_state()->sp_delta());
   1049       DCHECK(caller_registers_saved_);
   1050       caller_registers_saved_ = false;
   1051       break;
   1052     }
   1053     case kArchPrepareTailCall:
   1054       AssemblePrepareTailCall();
   1055       break;
   1056     case kArchComment:
   1057 #ifdef V8_TARGET_ARCH_PPC64
   1058       __ RecordComment(reinterpret_cast<const char*>(i.InputInt64(0)));
   1059 #else
   1060       __ RecordComment(reinterpret_cast<const char*>(i.InputInt32(0)));
   1061 #endif
   1062       break;
   1063     case kArchCallCFunction: {
   1064       int const num_parameters = MiscField::decode(instr->opcode());
   1065       if (instr->InputAt(0)->IsImmediate()) {
   1066         ExternalReference ref = i.InputExternalReference(0);
   1067         __ CallCFunction(ref, num_parameters);
   1068       } else {
   1069         Register func = i.InputRegister(0);
   1070         __ CallCFunction(func, num_parameters);
   1071       }
   1072       frame_access_state()->SetFrameAccessToDefault();
   1073       // Ideally, we should decrement SP delta to match the change of stack
   1074       // pointer in CallCFunction. However, for certain architectures (e.g.
   1075       // ARM), there may be more strict alignment requirement, causing old SP
   1076       // to be saved on the stack. In those cases, we can not calculate the SP
   1077       // delta statically.
   1078       frame_access_state()->ClearSPDelta();
   1079       if (caller_registers_saved_) {
   1080         // Need to re-sync SP delta introduced in kArchSaveCallerRegisters.
   1081         // Here, we assume the sequence to be:
   1082         //   kArchSaveCallerRegisters;
   1083         //   kArchCallCFunction;
   1084         //   kArchRestoreCallerRegisters;
   1085         int bytes =
   1086             __ RequiredStackSizeForCallerSaved(fp_mode_, kReturnRegister0);
   1087         frame_access_state()->IncreaseSPDelta(bytes / kPointerSize);
   1088       }
   1089       break;
   1090     }
   1091     case kArchJmp:
   1092       AssembleArchJump(i.InputRpo(0));
   1093       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1094       break;
   1095     case kArchBinarySearchSwitch:
   1096       AssembleArchBinarySearchSwitch(instr);
   1097       break;
   1098     case kArchLookupSwitch:
   1099       AssembleArchLookupSwitch(instr);
   1100       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1101       break;
   1102     case kArchTableSwitch:
   1103       AssembleArchTableSwitch(instr);
   1104       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1105       break;
   1106     case kArchDebugAbort:
   1107       DCHECK(i.InputRegister(0) == r4);
   1108       if (!frame_access_state()->has_frame()) {
   1109         // We don't actually want to generate a pile of code for this, so just
   1110         // claim there is a stack frame, without generating one.
   1111         FrameScope scope(tasm(), StackFrame::NONE);
   1112         __ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
   1113                 RelocInfo::CODE_TARGET);
   1114       } else {
   1115         __ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
   1116                 RelocInfo::CODE_TARGET);
   1117       }
   1118       __ stop("kArchDebugAbort");
   1119       break;
   1120     case kArchDebugBreak:
   1121       __ stop("kArchDebugBreak");
   1122       break;
   1123     case kArchNop:
   1124     case kArchThrowTerminator:
   1125       // don't emit code for nops.
   1126       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1127       break;
   1128     case kArchDeoptimize: {
   1129       int deopt_state_id =
   1130           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
   1131       CodeGenResult result =
   1132           AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
   1133       if (result != kSuccess) return result;
   1134       break;
   1135     }
   1136     case kArchRet:
   1137       AssembleReturn(instr->InputAt(0));
   1138       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1139       break;
   1140     case kArchStackPointer:
   1141       __ mr(i.OutputRegister(), sp);
   1142       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1143       break;
   1144     case kArchFramePointer:
   1145       __ mr(i.OutputRegister(), fp);
   1146       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1147       break;
   1148     case kArchParentFramePointer:
   1149       if (frame_access_state()->has_frame()) {
   1150         __ LoadP(i.OutputRegister(), MemOperand(fp, 0));
   1151       } else {
   1152         __ mr(i.OutputRegister(), fp);
   1153       }
   1154       break;
   1155     case kArchTruncateDoubleToI:
   1156       __ TruncateDoubleToI(isolate(), zone(), i.OutputRegister(),
   1157                            i.InputDoubleRegister(0), DetermineStubCallMode());
   1158       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1159       break;
   1160     case kArchStoreWithWriteBarrier: {
   1161       RecordWriteMode mode =
   1162           static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
   1163       Register object = i.InputRegister(0);
   1164       Register value = i.InputRegister(2);
   1165       Register scratch0 = i.TempRegister(0);
   1166       Register scratch1 = i.TempRegister(1);
   1167       OutOfLineRecordWrite* ool;
   1168 
   1169       AddressingMode addressing_mode =
   1170           AddressingModeField::decode(instr->opcode());
   1171       if (addressing_mode == kMode_MRI) {
   1172         int32_t offset = i.InputInt32(1);
   1173         ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value,
   1174                                                 scratch0, scratch1, mode);
   1175         __ StoreP(value, MemOperand(object, offset));
   1176       } else {
   1177         DCHECK_EQ(kMode_MRR, addressing_mode);
   1178         Register offset(i.InputRegister(1));
   1179         ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value,
   1180                                                 scratch0, scratch1, mode);
   1181         __ StorePX(value, MemOperand(object, offset));
   1182       }
   1183       __ CheckPageFlag(object, scratch0,
   1184                        MemoryChunk::kPointersFromHereAreInterestingMask, ne,
   1185                        ool->entry());
   1186       __ bind(ool->exit());
   1187       break;
   1188     }
   1189     case kArchStackSlot: {
   1190       FrameOffset offset =
   1191           frame_access_state()->GetFrameOffset(i.InputInt32(0));
   1192       __ addi(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
   1193               Operand(offset.offset()));
   1194       break;
   1195     }
   1196     case kArchWordPoisonOnSpeculation:
   1197       __ and_(i.OutputRegister(), i.InputRegister(0),
   1198               kSpeculationPoisonRegister);
   1199       break;
   1200     case kPPC_And:
   1201       if (HasRegisterInput(instr, 1)) {
   1202         __ and_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1203                 i.OutputRCBit());
   1204       } else {
   1205         __ andi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
   1206       }
   1207       break;
   1208     case kPPC_AndComplement:
   1209       __ andc(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1210               i.OutputRCBit());
   1211       break;
   1212     case kPPC_Or:
   1213       if (HasRegisterInput(instr, 1)) {
   1214         __ orx(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1215                i.OutputRCBit());
   1216       } else {
   1217         __ ori(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
   1218         DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1219       }
   1220       break;
   1221     case kPPC_OrComplement:
   1222       __ orc(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1223              i.OutputRCBit());
   1224       break;
   1225     case kPPC_Xor:
   1226       if (HasRegisterInput(instr, 1)) {
   1227         __ xor_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1228                 i.OutputRCBit());
   1229       } else {
   1230         __ xori(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
   1231         DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1232       }
   1233       break;
   1234     case kPPC_ShiftLeft32:
   1235       ASSEMBLE_BINOP_RC(slw, slwi);
   1236       break;
   1237 #if V8_TARGET_ARCH_PPC64
   1238     case kPPC_ShiftLeft64:
   1239       ASSEMBLE_BINOP_RC(sld, sldi);
   1240       break;
   1241 #endif
   1242     case kPPC_ShiftRight32:
   1243       ASSEMBLE_BINOP_RC(srw, srwi);
   1244       break;
   1245 #if V8_TARGET_ARCH_PPC64
   1246     case kPPC_ShiftRight64:
   1247       ASSEMBLE_BINOP_RC(srd, srdi);
   1248       break;
   1249 #endif
   1250     case kPPC_ShiftRightAlg32:
   1251       ASSEMBLE_BINOP_INT_RC(sraw, srawi);
   1252       break;
   1253 #if V8_TARGET_ARCH_PPC64
   1254     case kPPC_ShiftRightAlg64:
   1255       ASSEMBLE_BINOP_INT_RC(srad, sradi);
   1256       break;
   1257 #endif
   1258 #if !V8_TARGET_ARCH_PPC64
   1259     case kPPC_AddPair:
   1260       // i.InputRegister(0) ... left low word.
   1261       // i.InputRegister(1) ... left high word.
   1262       // i.InputRegister(2) ... right low word.
   1263       // i.InputRegister(3) ... right high word.
   1264       __ addc(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2));
   1265       __ adde(i.OutputRegister(1), i.InputRegister(1), i.InputRegister(3));
   1266       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1267       break;
   1268     case kPPC_SubPair:
   1269       // i.InputRegister(0) ... left low word.
   1270       // i.InputRegister(1) ... left high word.
   1271       // i.InputRegister(2) ... right low word.
   1272       // i.InputRegister(3) ... right high word.
   1273       __ subc(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2));
   1274       __ sube(i.OutputRegister(1), i.InputRegister(1), i.InputRegister(3));
   1275       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1276       break;
   1277     case kPPC_MulPair:
   1278       // i.InputRegister(0) ... left low word.
   1279       // i.InputRegister(1) ... left high word.
   1280       // i.InputRegister(2) ... right low word.
   1281       // i.InputRegister(3) ... right high word.
   1282       __ mullw(i.TempRegister(0), i.InputRegister(0), i.InputRegister(3));
   1283       __ mullw(i.TempRegister(1), i.InputRegister(2), i.InputRegister(1));
   1284       __ add(i.TempRegister(0), i.TempRegister(0), i.TempRegister(1));
   1285       __ mullw(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2));
   1286       __ mulhwu(i.OutputRegister(1), i.InputRegister(0), i.InputRegister(2));
   1287       __ add(i.OutputRegister(1), i.OutputRegister(1), i.TempRegister(0));
   1288       break;
   1289     case kPPC_ShiftLeftPair: {
   1290       Register second_output =
   1291           instr->OutputCount() >= 2 ? i.OutputRegister(1) : i.TempRegister(0);
   1292       if (instr->InputAt(2)->IsImmediate()) {
   1293         __ ShiftLeftPair(i.OutputRegister(0), second_output, i.InputRegister(0),
   1294                          i.InputRegister(1), i.InputInt32(2));
   1295       } else {
   1296         __ ShiftLeftPair(i.OutputRegister(0), second_output, i.InputRegister(0),
   1297                          i.InputRegister(1), kScratchReg, i.InputRegister(2));
   1298       }
   1299       break;
   1300     }
   1301     case kPPC_ShiftRightPair: {
   1302       Register second_output =
   1303           instr->OutputCount() >= 2 ? i.OutputRegister(1) : i.TempRegister(0);
   1304       if (instr->InputAt(2)->IsImmediate()) {
   1305         __ ShiftRightPair(i.OutputRegister(0), second_output,
   1306                           i.InputRegister(0), i.InputRegister(1),
   1307                           i.InputInt32(2));
   1308       } else {
   1309         __ ShiftRightPair(i.OutputRegister(0), second_output,
   1310                           i.InputRegister(0), i.InputRegister(1), kScratchReg,
   1311                           i.InputRegister(2));
   1312       }
   1313       break;
   1314     }
   1315     case kPPC_ShiftRightAlgPair: {
   1316       Register second_output =
   1317           instr->OutputCount() >= 2 ? i.OutputRegister(1) : i.TempRegister(0);
   1318       if (instr->InputAt(2)->IsImmediate()) {
   1319         __ ShiftRightAlgPair(i.OutputRegister(0), second_output,
   1320                              i.InputRegister(0), i.InputRegister(1),
   1321                              i.InputInt32(2));
   1322       } else {
   1323         __ ShiftRightAlgPair(i.OutputRegister(0), second_output,
   1324                              i.InputRegister(0), i.InputRegister(1),
   1325                              kScratchReg, i.InputRegister(2));
   1326       }
   1327       break;
   1328     }
   1329 #endif
   1330     case kPPC_RotRight32:
   1331       if (HasRegisterInput(instr, 1)) {
   1332         __ subfic(kScratchReg, i.InputRegister(1), Operand(32));
   1333         __ rotlw(i.OutputRegister(), i.InputRegister(0), kScratchReg,
   1334                  i.OutputRCBit());
   1335       } else {
   1336         int sh = i.InputInt32(1);
   1337         __ rotrwi(i.OutputRegister(), i.InputRegister(0), sh, i.OutputRCBit());
   1338       }
   1339       break;
   1340 #if V8_TARGET_ARCH_PPC64
   1341     case kPPC_RotRight64:
   1342       if (HasRegisterInput(instr, 1)) {
   1343         __ subfic(kScratchReg, i.InputRegister(1), Operand(64));
   1344         __ rotld(i.OutputRegister(), i.InputRegister(0), kScratchReg,
   1345                  i.OutputRCBit());
   1346       } else {
   1347         int sh = i.InputInt32(1);
   1348         __ rotrdi(i.OutputRegister(), i.InputRegister(0), sh, i.OutputRCBit());
   1349       }
   1350       break;
   1351 #endif
   1352     case kPPC_Not:
   1353       __ notx(i.OutputRegister(), i.InputRegister(0), i.OutputRCBit());
   1354       break;
   1355     case kPPC_RotLeftAndMask32:
   1356       __ rlwinm(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
   1357                 31 - i.InputInt32(2), 31 - i.InputInt32(3), i.OutputRCBit());
   1358       break;
   1359 #if V8_TARGET_ARCH_PPC64
   1360     case kPPC_RotLeftAndClear64:
   1361       __ rldic(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
   1362                63 - i.InputInt32(2), i.OutputRCBit());
   1363       break;
   1364     case kPPC_RotLeftAndClearLeft64:
   1365       __ rldicl(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
   1366                 63 - i.InputInt32(2), i.OutputRCBit());
   1367       break;
   1368     case kPPC_RotLeftAndClearRight64:
   1369       __ rldicr(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
   1370                 63 - i.InputInt32(2), i.OutputRCBit());
   1371       break;
   1372 #endif
   1373     case kPPC_Add32:
   1374 #if V8_TARGET_ARCH_PPC64
   1375       if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
   1376         ASSEMBLE_ADD_WITH_OVERFLOW();
   1377       } else {
   1378 #endif
   1379         if (HasRegisterInput(instr, 1)) {
   1380           __ add(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1381                  LeaveOE, i.OutputRCBit());
   1382         } else {
   1383           __ addi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
   1384           DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1385         }
   1386         __ extsw(i.OutputRegister(), i.OutputRegister());
   1387 #if V8_TARGET_ARCH_PPC64
   1388       }
   1389 #endif
   1390       break;
   1391 #if V8_TARGET_ARCH_PPC64
   1392     case kPPC_Add64:
   1393       if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
   1394         ASSEMBLE_ADD_WITH_OVERFLOW();
   1395       } else {
   1396         if (HasRegisterInput(instr, 1)) {
   1397           __ add(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1398                  LeaveOE, i.OutputRCBit());
   1399         } else {
   1400           __ addi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
   1401           DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1402         }
   1403       }
   1404       break;
   1405 #endif
   1406     case kPPC_AddWithOverflow32:
   1407       ASSEMBLE_ADD_WITH_OVERFLOW32();
   1408       break;
   1409     case kPPC_AddDouble:
   1410       ASSEMBLE_FLOAT_BINOP_RC(fadd, MiscField::decode(instr->opcode()));
   1411       break;
   1412     case kPPC_Sub:
   1413 #if V8_TARGET_ARCH_PPC64
   1414       if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
   1415         ASSEMBLE_SUB_WITH_OVERFLOW();
   1416       } else {
   1417 #endif
   1418         if (HasRegisterInput(instr, 1)) {
   1419           __ sub(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1420                  LeaveOE, i.OutputRCBit());
   1421         } else {
   1422           if (is_int16(i.InputImmediate(1).immediate())) {
   1423             __ subi(i.OutputRegister(), i.InputRegister(0),
   1424                     i.InputImmediate(1));
   1425             DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1426           } else {
   1427             __ mov(kScratchReg, i.InputImmediate(1));
   1428             __ sub(i.OutputRegister(), i.InputRegister(0), kScratchReg, LeaveOE,
   1429                    i.OutputRCBit());
   1430           }
   1431         }
   1432 #if V8_TARGET_ARCH_PPC64
   1433       }
   1434 #endif
   1435       break;
   1436     case kPPC_SubWithOverflow32:
   1437       ASSEMBLE_SUB_WITH_OVERFLOW32();
   1438       break;
   1439     case kPPC_SubDouble:
   1440       ASSEMBLE_FLOAT_BINOP_RC(fsub, MiscField::decode(instr->opcode()));
   1441       break;
   1442     case kPPC_Mul32:
   1443       __ mullw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1444                LeaveOE, i.OutputRCBit());
   1445       break;
   1446 #if V8_TARGET_ARCH_PPC64
   1447     case kPPC_Mul64:
   1448       __ mulld(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1449                LeaveOE, i.OutputRCBit());
   1450       break;
   1451 #endif
   1452 
   1453     case kPPC_Mul32WithHigh32:
   1454       if (i.OutputRegister(0) == i.InputRegister(0) ||
   1455           i.OutputRegister(0) == i.InputRegister(1) ||
   1456           i.OutputRegister(1) == i.InputRegister(0) ||
   1457           i.OutputRegister(1) == i.InputRegister(1)) {
   1458         __ mullw(kScratchReg,
   1459                  i.InputRegister(0), i.InputRegister(1));  // low
   1460         __ mulhw(i.OutputRegister(1),
   1461                  i.InputRegister(0), i.InputRegister(1));  // high
   1462         __ mr(i.OutputRegister(0), kScratchReg);
   1463       } else {
   1464         __ mullw(i.OutputRegister(0),
   1465                  i.InputRegister(0), i.InputRegister(1));  // low
   1466         __ mulhw(i.OutputRegister(1),
   1467                  i.InputRegister(0), i.InputRegister(1));  // high
   1468       }
   1469       break;
   1470     case kPPC_MulHigh32:
   1471       __ mulhw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1472                i.OutputRCBit());
   1473       break;
   1474     case kPPC_MulHighU32:
   1475       __ mulhwu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
   1476                 i.OutputRCBit());
   1477       break;
   1478     case kPPC_MulDouble:
   1479       ASSEMBLE_FLOAT_BINOP_RC(fmul, MiscField::decode(instr->opcode()));
   1480       break;
   1481     case kPPC_Div32:
   1482       __ divw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1483       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1484       break;
   1485 #if V8_TARGET_ARCH_PPC64
   1486     case kPPC_Div64:
   1487       __ divd(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1488       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1489       break;
   1490 #endif
   1491     case kPPC_DivU32:
   1492       __ divwu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1493       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1494       break;
   1495 #if V8_TARGET_ARCH_PPC64
   1496     case kPPC_DivU64:
   1497       __ divdu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1498       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1499       break;
   1500 #endif
   1501     case kPPC_DivDouble:
   1502       ASSEMBLE_FLOAT_BINOP_RC(fdiv, MiscField::decode(instr->opcode()));
   1503       break;
   1504     case kPPC_Mod32:
   1505       if (CpuFeatures::IsSupported(MODULO)) {
   1506         __ modsw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1507       } else {
   1508         ASSEMBLE_MODULO(divw, mullw);
   1509       }
   1510       break;
   1511 #if V8_TARGET_ARCH_PPC64
   1512     case kPPC_Mod64:
   1513       if (CpuFeatures::IsSupported(MODULO)) {
   1514         __ modsd(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1515       } else {
   1516         ASSEMBLE_MODULO(divd, mulld);
   1517       }
   1518       break;
   1519 #endif
   1520     case kPPC_ModU32:
   1521       if (CpuFeatures::IsSupported(MODULO)) {
   1522         __ moduw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1523       } else {
   1524         ASSEMBLE_MODULO(divwu, mullw);
   1525       }
   1526       break;
   1527 #if V8_TARGET_ARCH_PPC64
   1528     case kPPC_ModU64:
   1529       if (CpuFeatures::IsSupported(MODULO)) {
   1530         __ modud(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
   1531       } else {
   1532         ASSEMBLE_MODULO(divdu, mulld);
   1533       }
   1534       break;
   1535 #endif
   1536     case kPPC_ModDouble:
   1537       // TODO(bmeurer): We should really get rid of this special instruction,
   1538       // and generate a CallAddress instruction instead.
   1539       ASSEMBLE_FLOAT_MODULO();
   1540       break;
   1541     case kIeee754Float64Acos:
   1542       ASSEMBLE_IEEE754_UNOP(acos);
   1543       break;
   1544     case kIeee754Float64Acosh:
   1545       ASSEMBLE_IEEE754_UNOP(acosh);
   1546       break;
   1547     case kIeee754Float64Asin:
   1548       ASSEMBLE_IEEE754_UNOP(asin);
   1549       break;
   1550     case kIeee754Float64Asinh:
   1551       ASSEMBLE_IEEE754_UNOP(asinh);
   1552       break;
   1553     case kIeee754Float64Atan:
   1554       ASSEMBLE_IEEE754_UNOP(atan);
   1555       break;
   1556     case kIeee754Float64Atan2:
   1557       ASSEMBLE_IEEE754_BINOP(atan2);
   1558       break;
   1559     case kIeee754Float64Atanh:
   1560       ASSEMBLE_IEEE754_UNOP(atanh);
   1561       break;
   1562     case kIeee754Float64Tan:
   1563       ASSEMBLE_IEEE754_UNOP(tan);
   1564       break;
   1565     case kIeee754Float64Tanh:
   1566       ASSEMBLE_IEEE754_UNOP(tanh);
   1567       break;
   1568     case kIeee754Float64Cbrt:
   1569       ASSEMBLE_IEEE754_UNOP(cbrt);
   1570       break;
   1571     case kIeee754Float64Sin:
   1572       ASSEMBLE_IEEE754_UNOP(sin);
   1573       break;
   1574     case kIeee754Float64Sinh:
   1575       ASSEMBLE_IEEE754_UNOP(sinh);
   1576       break;
   1577     case kIeee754Float64Cos:
   1578       ASSEMBLE_IEEE754_UNOP(cos);
   1579       break;
   1580     case kIeee754Float64Cosh:
   1581       ASSEMBLE_IEEE754_UNOP(cosh);
   1582       break;
   1583     case kIeee754Float64Exp:
   1584       ASSEMBLE_IEEE754_UNOP(exp);
   1585       break;
   1586     case kIeee754Float64Expm1:
   1587       ASSEMBLE_IEEE754_UNOP(expm1);
   1588       break;
   1589     case kIeee754Float64Log:
   1590       ASSEMBLE_IEEE754_UNOP(log);
   1591       break;
   1592     case kIeee754Float64Log1p:
   1593       ASSEMBLE_IEEE754_UNOP(log1p);
   1594       break;
   1595     case kIeee754Float64Log2:
   1596       ASSEMBLE_IEEE754_UNOP(log2);
   1597       break;
   1598     case kIeee754Float64Log10:
   1599       ASSEMBLE_IEEE754_UNOP(log10);
   1600       break;
   1601     case kIeee754Float64Pow: {
   1602       __ Call(BUILTIN_CODE(isolate(), MathPowInternal), RelocInfo::CODE_TARGET);
   1603       __ Move(d1, d3);
   1604       break;
   1605     }
   1606     case kPPC_Neg:
   1607       __ neg(i.OutputRegister(), i.InputRegister(0), LeaveOE, i.OutputRCBit());
   1608       break;
   1609     case kPPC_MaxDouble:
   1610       ASSEMBLE_FLOAT_MAX();
   1611       break;
   1612     case kPPC_MinDouble:
   1613       ASSEMBLE_FLOAT_MIN();
   1614       break;
   1615     case kPPC_AbsDouble:
   1616       ASSEMBLE_FLOAT_UNOP_RC(fabs, 0);
   1617       break;
   1618     case kPPC_SqrtDouble:
   1619       ASSEMBLE_FLOAT_UNOP_RC(fsqrt, MiscField::decode(instr->opcode()));
   1620       break;
   1621     case kPPC_FloorDouble:
   1622       ASSEMBLE_FLOAT_UNOP_RC(frim, MiscField::decode(instr->opcode()));
   1623       break;
   1624     case kPPC_CeilDouble:
   1625       ASSEMBLE_FLOAT_UNOP_RC(frip, MiscField::decode(instr->opcode()));
   1626       break;
   1627     case kPPC_TruncateDouble:
   1628       ASSEMBLE_FLOAT_UNOP_RC(friz, MiscField::decode(instr->opcode()));
   1629       break;
   1630     case kPPC_RoundDouble:
   1631       ASSEMBLE_FLOAT_UNOP_RC(frin, MiscField::decode(instr->opcode()));
   1632       break;
   1633     case kPPC_NegDouble:
   1634       ASSEMBLE_FLOAT_UNOP_RC(fneg, 0);
   1635       break;
   1636     case kPPC_Cntlz32:
   1637       __ cntlzw(i.OutputRegister(), i.InputRegister(0));
   1638       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1639       break;
   1640 #if V8_TARGET_ARCH_PPC64
   1641     case kPPC_Cntlz64:
   1642       __ cntlzd(i.OutputRegister(), i.InputRegister(0));
   1643       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1644       break;
   1645 #endif
   1646     case kPPC_Popcnt32:
   1647       __ popcntw(i.OutputRegister(), i.InputRegister(0));
   1648       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1649       break;
   1650 #if V8_TARGET_ARCH_PPC64
   1651     case kPPC_Popcnt64:
   1652       __ popcntd(i.OutputRegister(), i.InputRegister(0));
   1653       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1654       break;
   1655 #endif
   1656     case kPPC_Cmp32:
   1657       ASSEMBLE_COMPARE(cmpw, cmplw);
   1658       break;
   1659 #if V8_TARGET_ARCH_PPC64
   1660     case kPPC_Cmp64:
   1661       ASSEMBLE_COMPARE(cmp, cmpl);
   1662       break;
   1663 #endif
   1664     case kPPC_CmpDouble:
   1665       ASSEMBLE_FLOAT_COMPARE(fcmpu);
   1666       break;
   1667     case kPPC_Tst32:
   1668       if (HasRegisterInput(instr, 1)) {
   1669         __ and_(r0, i.InputRegister(0), i.InputRegister(1), i.OutputRCBit());
   1670       } else {
   1671         __ andi(r0, i.InputRegister(0), i.InputImmediate(1));
   1672       }
   1673 #if V8_TARGET_ARCH_PPC64
   1674       __ extsw(r0, r0, i.OutputRCBit());
   1675 #endif
   1676       DCHECK_EQ(SetRC, i.OutputRCBit());
   1677       break;
   1678 #if V8_TARGET_ARCH_PPC64
   1679     case kPPC_Tst64:
   1680       if (HasRegisterInput(instr, 1)) {
   1681         __ and_(r0, i.InputRegister(0), i.InputRegister(1), i.OutputRCBit());
   1682       } else {
   1683         __ andi(r0, i.InputRegister(0), i.InputImmediate(1));
   1684       }
   1685       DCHECK_EQ(SetRC, i.OutputRCBit());
   1686       break;
   1687 #endif
   1688     case kPPC_Float64SilenceNaN: {
   1689       DoubleRegister value = i.InputDoubleRegister(0);
   1690       DoubleRegister result = i.OutputDoubleRegister();
   1691       __ CanonicalizeNaN(result, value);
   1692       break;
   1693     }
   1694     case kPPC_Push:
   1695       if (instr->InputAt(0)->IsFPRegister()) {
   1696         LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
   1697         if (op->representation() == MachineRepresentation::kFloat64) {
   1698           __ StoreDoubleU(i.InputDoubleRegister(0),
   1699                           MemOperand(sp, -kDoubleSize), r0);
   1700           frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1701         } else {
   1702           DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
   1703           __ StoreSingleU(i.InputDoubleRegister(0),
   1704                           MemOperand(sp, -kPointerSize), r0);
   1705           frame_access_state()->IncreaseSPDelta(1);
   1706         }
   1707       } else {
   1708         __ StorePU(i.InputRegister(0), MemOperand(sp, -kPointerSize), r0);
   1709         frame_access_state()->IncreaseSPDelta(1);
   1710       }
   1711       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1712       break;
   1713     case kPPC_PushFrame: {
   1714       int num_slots = i.InputInt32(1);
   1715       if (instr->InputAt(0)->IsFPRegister()) {
   1716         LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
   1717         if (op->representation() == MachineRepresentation::kFloat64) {
   1718           __ StoreDoubleU(i.InputDoubleRegister(0),
   1719                         MemOperand(sp, -num_slots * kPointerSize), r0);
   1720         } else {
   1721           DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
   1722           __ StoreSingleU(i.InputDoubleRegister(0),
   1723                         MemOperand(sp, -num_slots * kPointerSize), r0);
   1724         }
   1725       } else {
   1726         __ StorePU(i.InputRegister(0),
   1727                    MemOperand(sp, -num_slots * kPointerSize), r0);
   1728       }
   1729       break;
   1730     }
   1731     case kPPC_StoreToStackSlot: {
   1732       int slot = i.InputInt32(1);
   1733       if (instr->InputAt(0)->IsFPRegister()) {
   1734         LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
   1735         if (op->representation() == MachineRepresentation::kFloat64) {
   1736           __ StoreDouble(i.InputDoubleRegister(0),
   1737                         MemOperand(sp, slot * kPointerSize), r0);
   1738         } else {
   1739           DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
   1740           __ StoreSingle(i.InputDoubleRegister(0),
   1741                         MemOperand(sp, slot * kPointerSize), r0);
   1742         }
   1743       } else {
   1744         __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize), r0);
   1745       }
   1746       break;
   1747     }
   1748     case kPPC_ExtendSignWord8:
   1749       __ extsb(i.OutputRegister(), i.InputRegister(0));
   1750       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1751       break;
   1752     case kPPC_ExtendSignWord16:
   1753       __ extsh(i.OutputRegister(), i.InputRegister(0));
   1754       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1755       break;
   1756 #if V8_TARGET_ARCH_PPC64
   1757     case kPPC_ExtendSignWord32:
   1758       __ extsw(i.OutputRegister(), i.InputRegister(0));
   1759       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1760       break;
   1761     case kPPC_Uint32ToUint64:
   1762       // Zero extend
   1763       __ clrldi(i.OutputRegister(), i.InputRegister(0), Operand(32));
   1764       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1765       break;
   1766     case kPPC_Int64ToInt32:
   1767       __ extsw(i.OutputRegister(), i.InputRegister(0));
   1768       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1769       break;
   1770     case kPPC_Int64ToFloat32:
   1771       __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister());
   1772       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1773       break;
   1774     case kPPC_Int64ToDouble:
   1775       __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister());
   1776       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1777       break;
   1778     case kPPC_Uint64ToFloat32:
   1779       __ ConvertUnsignedInt64ToFloat(i.InputRegister(0),
   1780                                      i.OutputDoubleRegister());
   1781       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1782       break;
   1783     case kPPC_Uint64ToDouble:
   1784       __ ConvertUnsignedInt64ToDouble(i.InputRegister(0),
   1785                                       i.OutputDoubleRegister());
   1786       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1787       break;
   1788 #endif
   1789     case kPPC_Int32ToFloat32:
   1790       __ ConvertIntToFloat(i.InputRegister(0), i.OutputDoubleRegister());
   1791       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1792       break;
   1793     case kPPC_Int32ToDouble:
   1794       __ ConvertIntToDouble(i.InputRegister(0), i.OutputDoubleRegister());
   1795       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1796       break;
   1797     case kPPC_Uint32ToFloat32:
   1798       __ ConvertUnsignedIntToFloat(i.InputRegister(0),
   1799                                    i.OutputDoubleRegister());
   1800       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1801       break;
   1802     case kPPC_Uint32ToDouble:
   1803       __ ConvertUnsignedIntToDouble(i.InputRegister(0),
   1804                                     i.OutputDoubleRegister());
   1805       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1806       break;
   1807     case kPPC_DoubleToInt32:
   1808     case kPPC_DoubleToUint32:
   1809     case kPPC_DoubleToInt64: {
   1810 #if V8_TARGET_ARCH_PPC64
   1811       bool check_conversion =
   1812           (opcode == kPPC_DoubleToInt64 && i.OutputCount() > 1);
   1813       if (check_conversion) {
   1814         __ mtfsb0(VXCVI);  // clear FPSCR:VXCVI bit
   1815       }
   1816 #endif
   1817       __ ConvertDoubleToInt64(i.InputDoubleRegister(0),
   1818 #if !V8_TARGET_ARCH_PPC64
   1819                               kScratchReg,
   1820 #endif
   1821                               i.OutputRegister(0), kScratchDoubleReg);
   1822 #if V8_TARGET_ARCH_PPC64
   1823       if (check_conversion) {
   1824         // Set 2nd output to zero if conversion fails.
   1825         CRegister cr = cr7;
   1826         int crbit = v8::internal::Assembler::encode_crbit(
   1827             cr, static_cast<CRBit>(VXCVI % CRWIDTH));
   1828         __ mcrfs(cr, VXCVI);  // extract FPSCR field containing VXCVI into cr7
   1829         if (CpuFeatures::IsSupported(ISELECT)) {
   1830           __ li(i.OutputRegister(1), Operand(1));
   1831           __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit);
   1832         } else {
   1833           __ li(i.OutputRegister(1), Operand::Zero());
   1834           __ bc(v8::internal::kInstrSize * 2, BT, crbit);
   1835           __ li(i.OutputRegister(1), Operand(1));
   1836         }
   1837       }
   1838 #endif
   1839       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1840       break;
   1841     }
   1842 #if V8_TARGET_ARCH_PPC64
   1843     case kPPC_DoubleToUint64: {
   1844       bool check_conversion = (i.OutputCount() > 1);
   1845       if (check_conversion) {
   1846         __ mtfsb0(VXCVI);  // clear FPSCR:VXCVI bit
   1847       }
   1848       __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0),
   1849                                       i.OutputRegister(0), kScratchDoubleReg);
   1850       if (check_conversion) {
   1851         // Set 2nd output to zero if conversion fails.
   1852         CRegister cr = cr7;
   1853         int crbit = v8::internal::Assembler::encode_crbit(
   1854             cr, static_cast<CRBit>(VXCVI % CRWIDTH));
   1855         __ mcrfs(cr, VXCVI);  // extract FPSCR field containing VXCVI into cr7
   1856         if (CpuFeatures::IsSupported(ISELECT)) {
   1857           __ li(i.OutputRegister(1), Operand(1));
   1858           __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit);
   1859         } else {
   1860           __ li(i.OutputRegister(1), Operand::Zero());
   1861           __ bc(v8::internal::kInstrSize * 2, BT, crbit);
   1862           __ li(i.OutputRegister(1), Operand(1));
   1863         }
   1864       }
   1865       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1866       break;
   1867     }
   1868 #endif
   1869     case kPPC_DoubleToFloat32:
   1870       ASSEMBLE_FLOAT_UNOP_RC(frsp, 0);
   1871       break;
   1872     case kPPC_Float32ToDouble:
   1873       // Nothing to do.
   1874       __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1875       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1876       break;
   1877     case kPPC_DoubleExtractLowWord32:
   1878       __ MovDoubleLowToInt(i.OutputRegister(), i.InputDoubleRegister(0));
   1879       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1880       break;
   1881     case kPPC_DoubleExtractHighWord32:
   1882       __ MovDoubleHighToInt(i.OutputRegister(), i.InputDoubleRegister(0));
   1883       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1884       break;
   1885     case kPPC_DoubleInsertLowWord32:
   1886       __ InsertDoubleLow(i.OutputDoubleRegister(), i.InputRegister(1), r0);
   1887       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1888       break;
   1889     case kPPC_DoubleInsertHighWord32:
   1890       __ InsertDoubleHigh(i.OutputDoubleRegister(), i.InputRegister(1), r0);
   1891       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1892       break;
   1893     case kPPC_DoubleConstruct:
   1894 #if V8_TARGET_ARCH_PPC64
   1895       __ MovInt64ComponentsToDouble(i.OutputDoubleRegister(),
   1896                                     i.InputRegister(0), i.InputRegister(1), r0);
   1897 #else
   1898       __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0),
   1899                           i.InputRegister(1));
   1900 #endif
   1901       DCHECK_EQ(LeaveRC, i.OutputRCBit());
   1902       break;
   1903     case kPPC_BitcastFloat32ToInt32:
   1904       __ MovFloatToInt(i.OutputRegister(), i.InputDoubleRegister(0));
   1905       break;
   1906     case kPPC_BitcastInt32ToFloat32:
   1907       __ MovIntToFloat(i.OutputDoubleRegister(), i.InputRegister(0));
   1908       break;
   1909 #if V8_TARGET_ARCH_PPC64
   1910     case kPPC_BitcastDoubleToInt64:
   1911       __ MovDoubleToInt64(i.OutputRegister(), i.InputDoubleRegister(0));
   1912       break;
   1913     case kPPC_BitcastInt64ToDouble:
   1914       __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0));
   1915       break;
   1916 #endif
   1917     case kPPC_LoadWordU8:
   1918       ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
   1919       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1920       break;
   1921     case kPPC_LoadWordS8:
   1922       ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
   1923       __ extsb(i.OutputRegister(), i.OutputRegister());
   1924       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1925       break;
   1926     case kPPC_LoadWordU16:
   1927       ASSEMBLE_LOAD_INTEGER(lhz, lhzx);
   1928       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1929       break;
   1930     case kPPC_LoadWordS16:
   1931       ASSEMBLE_LOAD_INTEGER(lha, lhax);
   1932       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1933       break;
   1934     case kPPC_LoadWordU32:
   1935       ASSEMBLE_LOAD_INTEGER(lwz, lwzx);
   1936       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1937       break;
   1938     case kPPC_LoadWordS32:
   1939       ASSEMBLE_LOAD_INTEGER(lwa, lwax);
   1940       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1941       break;
   1942 #if V8_TARGET_ARCH_PPC64
   1943     case kPPC_LoadWord64:
   1944       ASSEMBLE_LOAD_INTEGER(ld, ldx);
   1945       EmitWordLoadPoisoningIfNeeded(this, instr, i);
   1946       break;
   1947 #endif
   1948     case kPPC_LoadFloat32:
   1949       ASSEMBLE_LOAD_FLOAT(lfs, lfsx);
   1950       break;
   1951     case kPPC_LoadDouble:
   1952       ASSEMBLE_LOAD_FLOAT(lfd, lfdx);
   1953       break;
   1954     case kPPC_StoreWord8:
   1955       ASSEMBLE_STORE_INTEGER(stb, stbx);
   1956       break;
   1957     case kPPC_StoreWord16:
   1958       ASSEMBLE_STORE_INTEGER(sth, sthx);
   1959       break;
   1960     case kPPC_StoreWord32:
   1961       ASSEMBLE_STORE_INTEGER(stw, stwx);
   1962       break;
   1963 #if V8_TARGET_ARCH_PPC64
   1964     case kPPC_StoreWord64:
   1965       ASSEMBLE_STORE_INTEGER(std, stdx);
   1966       break;
   1967 #endif
   1968     case kPPC_StoreFloat32:
   1969       ASSEMBLE_STORE_FLOAT32();
   1970       break;
   1971     case kPPC_StoreDouble:
   1972       ASSEMBLE_STORE_DOUBLE();
   1973       break;
   1974     case kWord32AtomicLoadInt8:
   1975       ASSEMBLE_ATOMIC_LOAD_INTEGER(lbz, lbzx);
   1976       __ extsb(i.OutputRegister(), i.OutputRegister());
   1977       break;
   1978     case kWord32AtomicLoadUint8:
   1979       ASSEMBLE_ATOMIC_LOAD_INTEGER(lbz, lbzx);
   1980       break;
   1981     case kWord32AtomicLoadInt16:
   1982       ASSEMBLE_ATOMIC_LOAD_INTEGER(lha, lhax);
   1983       break;
   1984     case kWord32AtomicLoadUint16:
   1985       ASSEMBLE_ATOMIC_LOAD_INTEGER(lhz, lhzx);
   1986       break;
   1987     case kWord32AtomicLoadWord32:
   1988       ASSEMBLE_ATOMIC_LOAD_INTEGER(lwz, lwzx);
   1989       break;
   1990 
   1991     case kWord32AtomicStoreWord8:
   1992       ASSEMBLE_ATOMIC_STORE_INTEGER(stb, stbx);
   1993       break;
   1994     case kWord32AtomicStoreWord16:
   1995       ASSEMBLE_ATOMIC_STORE_INTEGER(sth, sthx);
   1996       break;
   1997     case kWord32AtomicStoreWord32:
   1998       ASSEMBLE_ATOMIC_STORE_INTEGER(stw, stwx);
   1999       break;
   2000     case kWord32AtomicExchangeInt8:
   2001       ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lbarx, stbcx);
   2002       __ extsb(i.OutputRegister(0), i.OutputRegister(0));
   2003       break;
   2004     case kWord32AtomicExchangeUint8:
   2005       ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lbarx, stbcx);
   2006       break;
   2007     case kWord32AtomicExchangeInt16:
   2008       ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lharx, sthcx);
   2009       __ extsh(i.OutputRegister(0), i.OutputRegister(0));
   2010       break;
   2011     case kWord32AtomicExchangeUint16:
   2012       ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lharx, sthcx);
   2013       break;
   2014     case kWord32AtomicExchangeWord32:
   2015       ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lwarx, stwcx);
   2016       break;
   2017 
   2018     case kWord32AtomicCompareExchangeInt8:
   2019       ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_SIGN_EXT(cmp, lbarx, stbcx, extsb);
   2020       break;
   2021     case kWord32AtomicCompareExchangeUint8:
   2022       ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmp, lbarx, stbcx);
   2023       break;
   2024     case kWord32AtomicCompareExchangeInt16:
   2025       ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_SIGN_EXT(cmp, lharx, sthcx, extsh);
   2026       break;
   2027     case kWord32AtomicCompareExchangeUint16:
   2028       ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmp, lharx, sthcx);
   2029       break;
   2030     case kWord32AtomicCompareExchangeWord32:
   2031       ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmpw, lwarx, stwcx);
   2032       break;
   2033 
   2034 #define ATOMIC_BINOP_CASE(op, inst)                             \
   2035   case kWord32Atomic##op##Int8:                                 \
   2036     ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(inst, lbarx, stbcx, extsb);  \
   2037     break;                                                      \
   2038   case kWord32Atomic##op##Uint8:                                \
   2039     ASSEMBLE_ATOMIC_BINOP(inst, lbarx, stbcx);                  \
   2040     break;                                                      \
   2041   case kWord32Atomic##op##Int16:                                \
   2042     ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(inst, lharx, sthcx, extsh);  \
   2043     break;                                                      \
   2044   case kWord32Atomic##op##Uint16:                               \
   2045     ASSEMBLE_ATOMIC_BINOP(inst, lharx, sthcx);                  \
   2046     break;                                                      \
   2047   case kWord32Atomic##op##Word32:                               \
   2048     ASSEMBLE_ATOMIC_BINOP(inst, lwarx, stwcx);                  \
   2049     break;
   2050       ATOMIC_BINOP_CASE(Add, add)
   2051       ATOMIC_BINOP_CASE(Sub, sub)
   2052       ATOMIC_BINOP_CASE(And, and_)
   2053       ATOMIC_BINOP_CASE(Or, orx)
   2054       ATOMIC_BINOP_CASE(Xor, xor_)
   2055 #undef ATOMIC_BINOP_CASE
   2056 
   2057     case kPPC_ByteRev32: {
   2058       Register input = i.InputRegister(0);
   2059       Register output = i.OutputRegister();
   2060       Register temp1 = r0;
   2061       __ rotlwi(temp1, input, 8);
   2062       __ rlwimi(temp1, input, 24, 0, 7);
   2063       __ rlwimi(temp1, input, 24, 16, 23);
   2064       __ extsw(output, temp1);
   2065       break;
   2066     }
   2067 #ifdef V8_TARGET_ARCH_PPC64
   2068     case kPPC_ByteRev64: {
   2069       Register input = i.InputRegister(0);
   2070       Register output = i.OutputRegister();
   2071       Register temp1 = r0;
   2072       Register temp2 = kScratchReg;
   2073       Register temp3 = i.TempRegister(0);
   2074       __ rldicl(temp1, input, 32, 32);
   2075       __ rotlwi(temp2, input, 8);
   2076       __ rlwimi(temp2, input, 24, 0, 7);
   2077       __ rotlwi(temp3, temp1, 8);
   2078       __ rlwimi(temp2, input, 24, 16, 23);
   2079       __ rlwimi(temp3, temp1, 24, 0, 7);
   2080       __ rlwimi(temp3, temp1, 24, 16, 23);
   2081       __ rldicr(temp2, temp2, 32, 31);
   2082       __ orx(output, temp2, temp3);
   2083       break;
   2084     }
   2085 #endif  // V8_TARGET_ARCH_PPC64
   2086     default:
   2087       UNREACHABLE();
   2088       break;
   2089   }
   2090   return kSuccess;
   2091 }  // NOLINT(readability/fn_size)
   2092 
   2093 
   2094 // Assembles branches after an instruction.
   2095 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
   2096   PPCOperandConverter i(this, instr);
   2097   Label* tlabel = branch->true_label;
   2098   Label* flabel = branch->false_label;
   2099   ArchOpcode op = instr->arch_opcode();
   2100   FlagsCondition condition = branch->condition;
   2101   CRegister cr = cr0;
   2102 
   2103   Condition cond = FlagsConditionToCondition(condition, op);
   2104   if (op == kPPC_CmpDouble) {
   2105     // check for unordered if necessary
   2106     if (cond == le) {
   2107       __ bunordered(flabel, cr);
   2108       // Unnecessary for eq/lt since only FU bit will be set.
   2109     } else if (cond == gt) {
   2110       __ bunordered(tlabel, cr);
   2111       // Unnecessary for ne/ge since only FU bit will be set.
   2112     }
   2113   }
   2114   __ b(cond, tlabel, cr);
   2115   if (!branch->fallthru) __ b(flabel);  // no fallthru to flabel.
   2116 }
   2117 
   2118 void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
   2119                                             Instruction* instr) {
   2120   // TODO(John) Handle float comparisons (kUnordered[Not]Equal).
   2121   if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
   2122     return;
   2123   }
   2124 
   2125   ArchOpcode op = instr->arch_opcode();
   2126   condition = NegateFlagsCondition(condition);
   2127   __ li(kScratchReg, Operand::Zero());
   2128   __ isel(FlagsConditionToCondition(condition, op), kSpeculationPoisonRegister,
   2129           kScratchReg, kSpeculationPoisonRegister, cr0);
   2130 }
   2131 
   2132 void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
   2133                                             BranchInfo* branch) {
   2134   AssembleArchBranch(instr, branch);
   2135 }
   2136 
   2137 void CodeGenerator::AssembleArchJump(RpoNumber target) {
   2138   if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target));
   2139 }
   2140 
   2141 void CodeGenerator::AssembleArchTrap(Instruction* instr,
   2142                                      FlagsCondition condition) {
   2143   class OutOfLineTrap final : public OutOfLineCode {
   2144    public:
   2145     OutOfLineTrap(CodeGenerator* gen, Instruction* instr)
   2146         : OutOfLineCode(gen), instr_(instr), gen_(gen) {}
   2147 
   2148     void Generate() final {
   2149       PPCOperandConverter i(gen_, instr_);
   2150       TrapId trap_id =
   2151           static_cast<TrapId>(i.InputInt32(instr_->InputCount() - 1));
   2152       GenerateCallToTrap(trap_id);
   2153     }
   2154 
   2155    private:
   2156     void GenerateCallToTrap(TrapId trap_id) {
   2157       if (trap_id == TrapId::kInvalid) {
   2158         // We cannot test calls to the runtime in cctest/test-run-wasm.
   2159         // Therefore we emit a call to C here instead of a call to the runtime.
   2160         // We use the context register as the scratch register, because we do
   2161         // not have a context here.
   2162         __ PrepareCallCFunction(0, 0, cp);
   2163         __ CallCFunction(
   2164             ExternalReference::wasm_call_trap_callback_for_testing(), 0);
   2165         __ LeaveFrame(StackFrame::WASM_COMPILED);
   2166         auto call_descriptor = gen_->linkage()->GetIncomingDescriptor();
   2167         int pop_count =
   2168             static_cast<int>(call_descriptor->StackParameterCount());
   2169         __ Drop(pop_count);
   2170         __ Ret();
   2171       } else {
   2172         gen_->AssembleSourcePosition(instr_);
   2173         // A direct call to a wasm runtime stub defined in this module.
   2174         // Just encode the stub index. This will be patched at relocation.
   2175         __ Call(static_cast<Address>(trap_id), RelocInfo::WASM_STUB_CALL);
   2176         ReferenceMap* reference_map =
   2177             new (gen_->zone()) ReferenceMap(gen_->zone());
   2178         gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
   2179                               Safepoint::kNoLazyDeopt);
   2180         if (FLAG_debug_code) {
   2181           __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromWasmTrap));
   2182         }
   2183       }
   2184     }
   2185 
   2186     Instruction* instr_;
   2187     CodeGenerator* gen_;
   2188   };
   2189   auto ool = new (zone()) OutOfLineTrap(this, instr);
   2190   Label* tlabel = ool->entry();
   2191   Label end;
   2192 
   2193   ArchOpcode op = instr->arch_opcode();
   2194   CRegister cr = cr0;
   2195   Condition cond = FlagsConditionToCondition(condition, op);
   2196   if (op == kPPC_CmpDouble) {
   2197     // check for unordered if necessary
   2198     if (cond == le) {
   2199       __ bunordered(&end, cr);
   2200       // Unnecessary for eq/lt since only FU bit will be set.
   2201     } else if (cond == gt) {
   2202       __ bunordered(tlabel, cr);
   2203       // Unnecessary for ne/ge since only FU bit will be set.
   2204     }
   2205   }
   2206   __ b(cond, tlabel, cr);
   2207   __ bind(&end);
   2208 }
   2209 
   2210 // Assembles boolean materializations after an instruction.
   2211 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
   2212                                         FlagsCondition condition) {
   2213   PPCOperandConverter i(this, instr);
   2214   Label done;
   2215   ArchOpcode op = instr->arch_opcode();
   2216   CRegister cr = cr0;
   2217   int reg_value = -1;
   2218 
   2219   // Materialize a full 32-bit 1 or 0 value. The result register is always the
   2220   // last output of the instruction.
   2221   DCHECK_NE(0u, instr->OutputCount());
   2222   Register reg = i.OutputRegister(instr->OutputCount() - 1);
   2223 
   2224   Condition cond = FlagsConditionToCondition(condition, op);
   2225   if (op == kPPC_CmpDouble) {
   2226     // check for unordered if necessary
   2227     if (cond == le) {
   2228       reg_value = 0;
   2229       __ li(reg, Operand::Zero());
   2230       __ bunordered(&done, cr);
   2231     } else if (cond == gt) {
   2232       reg_value = 1;
   2233       __ li(reg, Operand(1));
   2234       __ bunordered(&done, cr);
   2235     }
   2236     // Unnecessary for eq/lt & ne/ge since only FU bit will be set.
   2237   }
   2238 
   2239   if (CpuFeatures::IsSupported(ISELECT)) {
   2240     switch (cond) {
   2241       case eq:
   2242       case lt:
   2243       case gt:
   2244         if (reg_value != 1) __ li(reg, Operand(1));
   2245         __ li(kScratchReg, Operand::Zero());
   2246         __ isel(cond, reg, reg, kScratchReg, cr);
   2247         break;
   2248       case ne:
   2249       case ge:
   2250       case le:
   2251         if (reg_value != 1) __ li(reg, Operand(1));
   2252         // r0 implies logical zero in this form
   2253         __ isel(NegateCondition(cond), reg, r0, reg, cr);
   2254         break;
   2255     default:
   2256       UNREACHABLE();
   2257       break;
   2258     }
   2259   } else {
   2260     if (reg_value != 0) __ li(reg, Operand::Zero());
   2261     __ b(NegateCondition(cond), &done, cr);
   2262     __ li(reg, Operand(1));
   2263   }
   2264   __ bind(&done);
   2265 }
   2266 
   2267 void CodeGenerator::AssembleArchBinarySearchSwitch(Instruction* instr) {
   2268   PPCOperandConverter i(this, instr);
   2269   Register input = i.InputRegister(0);
   2270   std::vector<std::pair<int32_t, Label*>> cases;
   2271   for (size_t index = 2; index < instr->InputCount(); index += 2) {
   2272     cases.push_back({i.InputInt32(index + 0), GetLabel(i.InputRpo(index + 1))});
   2273   }
   2274   AssembleArchBinarySearchSwitchRange(input, i.InputRpo(1), cases.data(),
   2275                                       cases.data() + cases.size());
   2276 }
   2277 
   2278 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
   2279   PPCOperandConverter i(this, instr);
   2280   Register input = i.InputRegister(0);
   2281   for (size_t index = 2; index < instr->InputCount(); index += 2) {
   2282     __ Cmpwi(input, Operand(i.InputInt32(index + 0)), r0);
   2283     __ beq(GetLabel(i.InputRpo(index + 1)));
   2284   }
   2285   AssembleArchJump(i.InputRpo(1));
   2286 }
   2287 
   2288 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
   2289   PPCOperandConverter i(this, instr);
   2290   Register input = i.InputRegister(0);
   2291   int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2);
   2292   Label** cases = zone()->NewArray<Label*>(case_count);
   2293   for (int32_t index = 0; index < case_count; ++index) {
   2294     cases[index] = GetLabel(i.InputRpo(index + 2));
   2295   }
   2296   Label* const table = AddJumpTable(cases, case_count);
   2297   __ Cmpli(input, Operand(case_count), r0);
   2298   __ bge(GetLabel(i.InputRpo(1)));
   2299   __ mov_label_addr(kScratchReg, table);
   2300   __ ShiftLeftImm(r0, input, Operand(kPointerSizeLog2));
   2301   __ LoadPX(kScratchReg, MemOperand(kScratchReg, r0));
   2302   __ Jump(kScratchReg);
   2303 }
   2304 
   2305 void CodeGenerator::FinishFrame(Frame* frame) {
   2306   auto call_descriptor = linkage()->GetIncomingDescriptor();
   2307   const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
   2308 
   2309   // Save callee-saved Double registers.
   2310   if (double_saves != 0) {
   2311     frame->AlignSavedCalleeRegisterSlots();
   2312     DCHECK_EQ(kNumCalleeSavedDoubles,
   2313               base::bits::CountPopulation(double_saves));
   2314     frame->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
   2315                                              (kDoubleSize / kPointerSize));
   2316   }
   2317   // Save callee-saved registers.
   2318   const RegList saves = FLAG_enable_embedded_constant_pool
   2319                             ? call_descriptor->CalleeSavedRegisters() &
   2320                                   ~kConstantPoolRegister.bit()
   2321                             : call_descriptor->CalleeSavedRegisters();
   2322   if (saves != 0) {
   2323     // register save area does not include the fp or constant pool pointer.
   2324     const int num_saves =
   2325         kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
   2326     DCHECK(num_saves == base::bits::CountPopulation(saves));
   2327     frame->AllocateSavedCalleeRegisterSlots(num_saves);
   2328   }
   2329 }
   2330 
   2331 void CodeGenerator::AssembleConstructFrame() {
   2332   auto call_descriptor = linkage()->GetIncomingDescriptor();
   2333   if (frame_access_state()->has_frame()) {
   2334     if (call_descriptor->IsCFunctionCall()) {
   2335       __ function_descriptor();
   2336       __ mflr(r0);
   2337       if (FLAG_enable_embedded_constant_pool) {
   2338         __ Push(r0, fp, kConstantPoolRegister);
   2339         // Adjust FP to point to saved FP.
   2340         __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
   2341       } else {
   2342         __ Push(r0, fp);
   2343         __ mr(fp, sp);
   2344       }
   2345     } else if (call_descriptor->IsJSFunctionCall()) {
   2346       __ Prologue();
   2347       if (call_descriptor->PushArgumentCount()) {
   2348         __ Push(kJavaScriptCallArgCountRegister);
   2349       }
   2350     } else {
   2351       StackFrame::Type type = info()->GetOutputStackFrameType();
   2352       // TODO(mbrandy): Detect cases where ip is the entrypoint (for
   2353       // efficient intialization of the constant pool pointer register).
   2354       __ StubPrologue(type);
   2355       if (call_descriptor->IsWasmFunctionCall()) {
   2356         __ Push(kWasmInstanceRegister);
   2357       }
   2358     }
   2359   }
   2360 
   2361   int shrink_slots = frame()->GetTotalFrameSlotCount() -
   2362                      call_descriptor->CalculateFixedFrameSize();
   2363   if (info()->is_osr()) {
   2364     // TurboFan OSR-compiled functions cannot be entered directly.
   2365     __ Abort(AbortReason::kShouldNotDirectlyEnterOsrFunction);
   2366 
   2367     // Unoptimized code jumps directly to this entrypoint while the unoptimized
   2368     // frame is still on the stack. Optimized code uses OSR values directly from
   2369     // the unoptimized frame. Thus, all that needs to be done is to allocate the
   2370     // remaining stack slots.
   2371     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
   2372     osr_pc_offset_ = __ pc_offset();
   2373     shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
   2374     ResetSpeculationPoison();
   2375   }
   2376 
   2377   const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
   2378   const RegList saves = FLAG_enable_embedded_constant_pool
   2379                             ? call_descriptor->CalleeSavedRegisters() &
   2380                                   ~kConstantPoolRegister.bit()
   2381                             : call_descriptor->CalleeSavedRegisters();
   2382 
   2383   if (shrink_slots > 0) {
   2384     if (info()->IsWasm() && shrink_slots > 128) {
   2385       // For WebAssembly functions with big frames we have to do the stack
   2386       // overflow check before we construct the frame. Otherwise we may not
   2387       // have enough space on the stack to call the runtime for the stack
   2388       // overflow.
   2389       Label done;
   2390 
   2391       // If the frame is bigger than the stack, we throw the stack overflow
   2392       // exception unconditionally. Thereby we can avoid the integer overflow
   2393       // check in the condition code.
   2394       if ((shrink_slots * kPointerSize) < (FLAG_stack_size * 1024)) {
   2395         Register scratch = ip;
   2396         __ LoadP(scratch, FieldMemOperand(
   2397                             kWasmInstanceRegister,
   2398                             WasmInstanceObject::kRealStackLimitAddressOffset));
   2399         __ LoadP(scratch, MemOperand(scratch), r0);
   2400         __ Add(scratch, scratch, shrink_slots * kPointerSize, r0);
   2401         __ cmpl(sp, scratch);
   2402         __ bge(&done);
   2403       }
   2404 
   2405       __ LoadP(r5,
   2406                FieldMemOperand(kWasmInstanceRegister,
   2407                                WasmInstanceObject::kCEntryStubOffset),
   2408                r0);
   2409       __ Move(cp, Smi::kZero);
   2410       __ CallRuntimeWithCEntry(Runtime::kThrowWasmStackOverflow, r5);
   2411       // We come from WebAssembly, there are no references for the GC.
   2412       ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
   2413       RecordSafepoint(reference_map, Safepoint::kSimple, 0,
   2414                       Safepoint::kNoLazyDeopt);
   2415       if (FLAG_debug_code) {
   2416         __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromThrow));
   2417       }
   2418 
   2419       __ bind(&done);
   2420     }
   2421 
   2422     // Skip callee-saved and return slots, which are pushed below.
   2423     shrink_slots -= base::bits::CountPopulation(saves);
   2424     shrink_slots -= frame()->GetReturnSlotCount();
   2425     shrink_slots -=
   2426         (kDoubleSize / kPointerSize) * base::bits::CountPopulation(saves_fp);
   2427     __ Add(sp, sp, -shrink_slots * kPointerSize, r0);
   2428   }
   2429 
   2430   // Save callee-saved Double registers.
   2431   if (saves_fp != 0) {
   2432     __ MultiPushDoubles(saves_fp);
   2433     DCHECK_EQ(kNumCalleeSavedDoubles, base::bits::CountPopulation(saves_fp));
   2434   }
   2435 
   2436   // Save callee-saved registers.
   2437   if (saves != 0) {
   2438     __ MultiPush(saves);
   2439     // register save area does not include the fp or constant pool pointer.
   2440   }
   2441 
   2442   const int returns = frame()->GetReturnSlotCount();
   2443   if (returns != 0) {
   2444     // Create space for returns.
   2445     __ Add(sp, sp, -returns * kPointerSize, r0);
   2446   }
   2447 }
   2448 
   2449 void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
   2450   auto call_descriptor = linkage()->GetIncomingDescriptor();
   2451   int pop_count = static_cast<int>(call_descriptor->StackParameterCount());
   2452 
   2453   const int returns = frame()->GetReturnSlotCount();
   2454   if (returns != 0) {
   2455     // Create space for returns.
   2456     __ Add(sp, sp, returns * kPointerSize, r0);
   2457   }
   2458 
   2459   // Restore registers.
   2460   const RegList saves = FLAG_enable_embedded_constant_pool
   2461                             ? call_descriptor->CalleeSavedRegisters() &
   2462                                   ~kConstantPoolRegister.bit()
   2463                             : call_descriptor->CalleeSavedRegisters();
   2464   if (saves != 0) {
   2465     __ MultiPop(saves);
   2466   }
   2467 
   2468   // Restore double registers.
   2469   const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
   2470   if (double_saves != 0) {
   2471     __ MultiPopDoubles(double_saves);
   2472   }
   2473   PPCOperandConverter g(this, nullptr);
   2474 
   2475   if (call_descriptor->IsCFunctionCall()) {
   2476     AssembleDeconstructFrame();
   2477   } else if (frame_access_state()->has_frame()) {
   2478     // Canonicalize JSFunction return sites for now unless they have an variable
   2479     // number of stack slot pops
   2480     if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) {
   2481       if (return_label_.is_bound()) {
   2482         __ b(&return_label_);
   2483         return;
   2484       } else {
   2485         __ bind(&return_label_);
   2486         AssembleDeconstructFrame();
   2487       }
   2488     } else {
   2489       AssembleDeconstructFrame();
   2490     }
   2491   }
   2492   // Constant pool is unavailable since the frame has been destructed
   2493   ConstantPoolUnavailableScope constant_pool_unavailable(tasm());
   2494   if (pop->IsImmediate()) {
   2495     DCHECK(Constant::kInt32 == g.ToConstant(pop).type() ||
   2496            Constant::kInt64 == g.ToConstant(pop).type());
   2497     pop_count += g.ToConstant(pop).ToInt32();
   2498   } else {
   2499     __ Drop(g.ToRegister(pop));
   2500   }
   2501   __ Drop(pop_count);
   2502   __ Ret();
   2503 }
   2504 
   2505 void CodeGenerator::FinishCode() { __ EmitConstantPool(); }
   2506 
   2507 void CodeGenerator::AssembleMove(InstructionOperand* source,
   2508                                  InstructionOperand* destination) {
   2509   PPCOperandConverter g(this, nullptr);
   2510   // Dispatch on the source and destination operand kinds.  Not all
   2511   // combinations are possible.
   2512   if (source->IsRegister()) {
   2513     DCHECK(destination->IsRegister() || destination->IsStackSlot());
   2514     Register src = g.ToRegister(source);
   2515     if (destination->IsRegister()) {
   2516       __ Move(g.ToRegister(destination), src);
   2517     } else {
   2518       __ StoreP(src, g.ToMemOperand(destination), r0);
   2519     }
   2520   } else if (source->IsStackSlot()) {
   2521     DCHECK(destination->IsRegister() || destination->IsStackSlot());
   2522     MemOperand src = g.ToMemOperand(source);
   2523     if (destination->IsRegister()) {
   2524       __ LoadP(g.ToRegister(destination), src, r0);
   2525     } else {
   2526       Register temp = kScratchReg;
   2527       __ LoadP(temp, src, r0);
   2528       __ StoreP(temp, g.ToMemOperand(destination), r0);
   2529     }
   2530   } else if (source->IsConstant()) {
   2531     Constant src = g.ToConstant(source);
   2532     if (destination->IsRegister() || destination->IsStackSlot()) {
   2533       Register dst =
   2534           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
   2535       switch (src.type()) {
   2536         case Constant::kInt32:
   2537 #if V8_TARGET_ARCH_PPC64
   2538           if (false) {
   2539 #else
   2540           if (RelocInfo::IsWasmReference(src.rmode())) {
   2541 #endif
   2542             __ mov(dst, Operand(src.ToInt32(), src.rmode()));
   2543           } else {
   2544             __ mov(dst, Operand(src.ToInt32()));
   2545           }
   2546           break;
   2547         case Constant::kInt64:
   2548 #if V8_TARGET_ARCH_PPC64
   2549           if (RelocInfo::IsWasmPtrReference(src.rmode())) {
   2550             __ mov(dst, Operand(src.ToInt64(), src.rmode()));
   2551           } else {
   2552 #endif
   2553             __ mov(dst, Operand(src.ToInt64()));
   2554 #if V8_TARGET_ARCH_PPC64
   2555           }
   2556 #endif
   2557           break;
   2558         case Constant::kFloat32:
   2559           __ mov(dst, Operand::EmbeddedNumber(src.ToFloat32()));
   2560           break;
   2561         case Constant::kFloat64:
   2562           __ mov(dst, Operand::EmbeddedNumber(src.ToFloat64().value()));
   2563           break;
   2564         case Constant::kExternalReference:
   2565           __ Move(dst, src.ToExternalReference());
   2566           break;
   2567         case Constant::kHeapObject: {
   2568           Handle<HeapObject> src_object = src.ToHeapObject();
   2569           Heap::RootListIndex index;
   2570           if (IsMaterializableFromRoot(src_object, &index)) {
   2571             __ LoadRoot(dst, index);
   2572           } else {
   2573             __ Move(dst, src_object);
   2574           }
   2575           break;
   2576         }
   2577         case Constant::kRpoNumber:
   2578           UNREACHABLE();  // TODO(dcarney): loading RPO constants on PPC.
   2579           break;
   2580       }
   2581       if (destination->IsStackSlot()) {
   2582         __ StoreP(dst, g.ToMemOperand(destination), r0);
   2583       }
   2584     } else {
   2585       DoubleRegister dst = destination->IsFPRegister()
   2586                                ? g.ToDoubleRegister(destination)
   2587                                : kScratchDoubleReg;
   2588       Double value;
   2589 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
   2590       // casting double precision snan to single precision
   2591       // converts it to qnan on ia32/x64
   2592       if (src.type() == Constant::kFloat32) {
   2593         uint32_t val = src.ToFloat32AsInt();
   2594         if ((val & 0x7F800000) == 0x7F800000) {
   2595           uint64_t dval = static_cast<uint64_t>(val);
   2596           dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
   2597                  ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29);
   2598           value = Double(dval);
   2599         } else {
   2600           value = Double(static_cast<double>(src.ToFloat32()));
   2601         }
   2602       } else {
   2603         value = Double(src.ToFloat64());
   2604       }
   2605 #else
   2606       value = src.type() == Constant::kFloat32
   2607                   ? Double(static_cast<double>(src.ToFloat32()))
   2608                   : Double(src.ToFloat64());
   2609 #endif
   2610       __ LoadDoubleLiteral(dst, value, kScratchReg);
   2611       if (destination->IsDoubleStackSlot()) {
   2612         __ StoreDouble(dst, g.ToMemOperand(destination), r0);
   2613       } else if (destination->IsFloatStackSlot()) {
   2614         __ StoreSingle(dst, g.ToMemOperand(destination), r0);
   2615       }
   2616     }
   2617   } else if (source->IsFPRegister()) {
   2618     DoubleRegister src = g.ToDoubleRegister(source);
   2619     if (destination->IsFPRegister()) {
   2620       DoubleRegister dst = g.ToDoubleRegister(destination);
   2621       __ Move(dst, src);
   2622     } else {
   2623       DCHECK(destination->IsFPStackSlot());
   2624       LocationOperand* op = LocationOperand::cast(source);
   2625       if (op->representation() == MachineRepresentation::kFloat64) {
   2626         __ StoreDouble(src, g.ToMemOperand(destination), r0);
   2627       } else {
   2628         __ StoreSingle(src, g.ToMemOperand(destination), r0);
   2629       }
   2630     }
   2631   } else if (source->IsFPStackSlot()) {
   2632     DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
   2633     MemOperand src = g.ToMemOperand(source);
   2634     if (destination->IsFPRegister()) {
   2635       LocationOperand* op = LocationOperand::cast(source);
   2636       if (op->representation() == MachineRepresentation::kFloat64) {
   2637         __ LoadDouble(g.ToDoubleRegister(destination), src, r0);
   2638       } else {
   2639         __ LoadSingle(g.ToDoubleRegister(destination), src, r0);
   2640       }
   2641     } else {
   2642       LocationOperand* op = LocationOperand::cast(source);
   2643       DoubleRegister temp = kScratchDoubleReg;
   2644       if (op->representation() == MachineRepresentation::kFloat64) {
   2645         __ LoadDouble(temp, src, r0);
   2646         __ StoreDouble(temp, g.ToMemOperand(destination), r0);
   2647       } else {
   2648         __ LoadSingle(temp, src, r0);
   2649         __ StoreSingle(temp, g.ToMemOperand(destination), r0);
   2650       }
   2651     }
   2652   } else {
   2653     UNREACHABLE();
   2654   }
   2655 }
   2656 
   2657 // Swaping contents in source and destination.
   2658 // source and destination could be:
   2659 //   Register,
   2660 //   FloatRegister,
   2661 //   DoubleRegister,
   2662 //   StackSlot,
   2663 //   FloatStackSlot,
   2664 //   or DoubleStackSlot
   2665 void CodeGenerator::AssembleSwap(InstructionOperand* source,
   2666                                  InstructionOperand* destination) {
   2667   PPCOperandConverter g(this, nullptr);
   2668   if (source->IsRegister()) {
   2669     Register src = g.ToRegister(source);
   2670     if (destination->IsRegister()) {
   2671       __ SwapP(src, g.ToRegister(destination), kScratchReg);
   2672     } else {
   2673       DCHECK(destination->IsStackSlot());
   2674       __ SwapP(src, g.ToMemOperand(destination), kScratchReg);
   2675     }
   2676   } else if (source->IsStackSlot()) {
   2677     DCHECK(destination->IsStackSlot());
   2678     __ SwapP(g.ToMemOperand(source), g.ToMemOperand(destination), kScratchReg,
   2679              r0);
   2680   } else if (source->IsFloatRegister()) {
   2681     DoubleRegister src = g.ToDoubleRegister(source);
   2682     if (destination->IsFloatRegister()) {
   2683       __ SwapFloat32(src, g.ToDoubleRegister(destination), kScratchDoubleReg);
   2684     } else {
   2685       DCHECK(destination->IsFloatStackSlot());
   2686       __ SwapFloat32(src, g.ToMemOperand(destination), kScratchDoubleReg);
   2687     }
   2688   } else if (source->IsDoubleRegister()) {
   2689     DoubleRegister src = g.ToDoubleRegister(source);
   2690     if (destination->IsDoubleRegister()) {
   2691       __ SwapDouble(src, g.ToDoubleRegister(destination), kScratchDoubleReg);
   2692     } else {
   2693       DCHECK(destination->IsDoubleStackSlot());
   2694       __ SwapDouble(src, g.ToMemOperand(destination), kScratchDoubleReg);
   2695     }
   2696   } else if (source->IsFloatStackSlot()) {
   2697     DCHECK(destination->IsFloatStackSlot());
   2698     __ SwapFloat32(g.ToMemOperand(source), g.ToMemOperand(destination),
   2699                    kScratchDoubleReg, d0);
   2700   } else if (source->IsDoubleStackSlot()) {
   2701     DCHECK(destination->IsDoubleStackSlot());
   2702     __ SwapDouble(g.ToMemOperand(source), g.ToMemOperand(destination),
   2703                   kScratchDoubleReg, d0);
   2704   } else if (source->IsSimd128Register()) {
   2705     UNREACHABLE();
   2706   } else {
   2707     UNREACHABLE();
   2708   }
   2709 
   2710   return;
   2711 }
   2712 
   2713 
   2714 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
   2715   for (size_t index = 0; index < target_count; ++index) {
   2716     __ emit_label_addr(targets[index]);
   2717   }
   2718 }
   2719 
   2720 
   2721 #undef __
   2722 
   2723 }  // namespace compiler
   2724 }  // namespace internal
   2725 }  // namespace v8
   2726