Home | History | Annotate | Download | only in s390
      1 // Copyright 2015 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/compilation-info.h"
      8 #include "src/compiler/code-generator-impl.h"
      9 #include "src/compiler/gap-resolver.h"
     10 #include "src/compiler/node-matchers.h"
     11 #include "src/compiler/osr.h"
     12 #include "src/s390/macro-assembler-s390.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 namespace compiler {
     17 
     18 #define __ masm()->
     19 
     20 #define kScratchReg ip
     21 
     22 // Adds S390-specific methods to convert InstructionOperands.
     23 class S390OperandConverter final : public InstructionOperandConverter {
     24  public:
     25   S390OperandConverter(CodeGenerator* gen, Instruction* instr)
     26       : InstructionOperandConverter(gen, instr) {}
     27 
     28   size_t OutputCount() { return instr_->OutputCount(); }
     29 
     30   bool Is64BitOperand(int index) {
     31     return LocationOperand::cast(instr_->InputAt(index))->representation() ==
     32            MachineRepresentation::kWord64;
     33   }
     34 
     35   bool Is32BitOperand(int index) {
     36     return LocationOperand::cast(instr_->InputAt(index))->representation() ==
     37            MachineRepresentation::kWord32;
     38   }
     39 
     40   bool CompareLogical() const {
     41     switch (instr_->flags_condition()) {
     42       case kUnsignedLessThan:
     43       case kUnsignedGreaterThanOrEqual:
     44       case kUnsignedLessThanOrEqual:
     45       case kUnsignedGreaterThan:
     46         return true;
     47       default:
     48         return false;
     49     }
     50     UNREACHABLE();
     51     return false;
     52   }
     53 
     54   Operand InputImmediate(size_t index) {
     55     Constant constant = ToConstant(instr_->InputAt(index));
     56     switch (constant.type()) {
     57       case Constant::kInt32:
     58         return Operand(constant.ToInt32());
     59       case Constant::kFloat32:
     60         return Operand(
     61             isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
     62       case Constant::kFloat64:
     63         return Operand(
     64             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
     65       case Constant::kInt64:
     66 #if V8_TARGET_ARCH_S390X
     67         return Operand(constant.ToInt64());
     68 #endif
     69       case Constant::kExternalReference:
     70       case Constant::kHeapObject:
     71       case Constant::kRpoNumber:
     72         break;
     73     }
     74     UNREACHABLE();
     75     return Operand::Zero();
     76   }
     77 
     78   MemOperand MemoryOperand(AddressingMode* mode, size_t* first_index) {
     79     const size_t index = *first_index;
     80     if (mode) *mode = AddressingModeField::decode(instr_->opcode());
     81     switch (AddressingModeField::decode(instr_->opcode())) {
     82       case kMode_None:
     83         break;
     84       case kMode_MR:
     85         *first_index += 1;
     86         return MemOperand(InputRegister(index + 0), 0);
     87       case kMode_MRI:
     88         *first_index += 2;
     89         return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
     90       case kMode_MRR:
     91         *first_index += 2;
     92         return MemOperand(InputRegister(index + 0), InputRegister(index + 1));
     93       case kMode_MRRI:
     94         *first_index += 3;
     95         return MemOperand(InputRegister(index + 0), InputRegister(index + 1),
     96                           InputInt32(index + 2));
     97     }
     98     UNREACHABLE();
     99     return MemOperand(r0);
    100   }
    101 
    102   MemOperand MemoryOperand(AddressingMode* mode = NULL,
    103                            size_t first_index = 0) {
    104     return MemoryOperand(mode, &first_index);
    105   }
    106 
    107   MemOperand ToMemOperand(InstructionOperand* op) const {
    108     DCHECK_NOT_NULL(op);
    109     DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
    110     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
    111   }
    112 
    113   MemOperand SlotToMemOperand(int slot) const {
    114     FrameOffset offset = frame_access_state()->GetFrameOffset(slot);
    115     return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
    116   }
    117 
    118   MemOperand InputStackSlot(size_t index) {
    119     InstructionOperand* op = instr_->InputAt(index);
    120     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
    121   }
    122 
    123   MemOperand InputStackSlot32(size_t index) {
    124 #if V8_TARGET_ARCH_S390X && !V8_TARGET_LITTLE_ENDIAN
    125     // We want to read the 32-bits directly from memory
    126     MemOperand mem = InputStackSlot(index);
    127     return MemOperand(mem.rb(), mem.rx(), mem.offset() + 4);
    128 #else
    129     return InputStackSlot(index);
    130 #endif
    131   }
    132 };
    133 
    134 static inline bool HasRegisterOutput(Instruction* instr, int index = 0) {
    135   return instr->OutputCount() > 0 && instr->OutputAt(index)->IsRegister();
    136 }
    137 
    138 static inline bool HasRegisterInput(Instruction* instr, int index) {
    139   return instr->InputAt(index)->IsRegister();
    140 }
    141 
    142 static inline bool HasFPRegisterInput(Instruction* instr, int index) {
    143   return instr->InputAt(index)->IsFPRegister();
    144 }
    145 
    146 static inline bool HasImmediateInput(Instruction* instr, size_t index) {
    147   return instr->InputAt(index)->IsImmediate();
    148 }
    149 
    150 static inline bool HasStackSlotInput(Instruction* instr, size_t index) {
    151   return instr->InputAt(index)->IsStackSlot();
    152 }
    153 
    154 static inline bool HasFPStackSlotInput(Instruction* instr, size_t index) {
    155   return instr->InputAt(index)->IsFPStackSlot();
    156 }
    157 
    158 namespace {
    159 
    160 class OutOfLineLoadNAN32 final : public OutOfLineCode {
    161  public:
    162   OutOfLineLoadNAN32(CodeGenerator* gen, DoubleRegister result)
    163       : OutOfLineCode(gen), result_(result) {}
    164 
    165   void Generate() final {
    166     __ LoadDoubleLiteral(result_, std::numeric_limits<float>::quiet_NaN(),
    167                          kScratchReg);
    168   }
    169 
    170  private:
    171   DoubleRegister const result_;
    172 };
    173 
    174 class OutOfLineLoadNAN64 final : public OutOfLineCode {
    175  public:
    176   OutOfLineLoadNAN64(CodeGenerator* gen, DoubleRegister result)
    177       : OutOfLineCode(gen), result_(result) {}
    178 
    179   void Generate() final {
    180     __ LoadDoubleLiteral(result_, std::numeric_limits<double>::quiet_NaN(),
    181                          kScratchReg);
    182   }
    183 
    184  private:
    185   DoubleRegister const result_;
    186 };
    187 
    188 class OutOfLineLoadZero final : public OutOfLineCode {
    189  public:
    190   OutOfLineLoadZero(CodeGenerator* gen, Register result)
    191       : OutOfLineCode(gen), result_(result) {}
    192 
    193   void Generate() final { __ LoadImmP(result_, Operand::Zero()); }
    194 
    195  private:
    196   Register const result_;
    197 };
    198 
    199 class OutOfLineRecordWrite final : public OutOfLineCode {
    200  public:
    201   OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset,
    202                        Register value, Register scratch0, Register scratch1,
    203                        RecordWriteMode mode)
    204       : OutOfLineCode(gen),
    205         object_(object),
    206         offset_(offset),
    207         offset_immediate_(0),
    208         value_(value),
    209         scratch0_(scratch0),
    210         scratch1_(scratch1),
    211         mode_(mode),
    212         must_save_lr_(!gen->frame_access_state()->has_frame()) {}
    213 
    214   OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
    215                        Register value, Register scratch0, Register scratch1,
    216                        RecordWriteMode mode)
    217       : OutOfLineCode(gen),
    218         object_(object),
    219         offset_(no_reg),
    220         offset_immediate_(offset),
    221         value_(value),
    222         scratch0_(scratch0),
    223         scratch1_(scratch1),
    224         mode_(mode),
    225         must_save_lr_(!gen->frame_access_state()->has_frame()) {}
    226 
    227   void Generate() final {
    228     if (mode_ > RecordWriteMode::kValueIsPointer) {
    229       __ JumpIfSmi(value_, exit());
    230     }
    231     __ CheckPageFlag(value_, scratch0_,
    232                      MemoryChunk::kPointersToHereAreInterestingMask, eq,
    233                      exit());
    234     RememberedSetAction const remembered_set_action =
    235         mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
    236                                              : OMIT_REMEMBERED_SET;
    237     SaveFPRegsMode const save_fp_mode =
    238         frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
    239     if (must_save_lr_) {
    240       // We need to save and restore r14 if the frame was elided.
    241       __ Push(r14);
    242     }
    243     RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
    244                          remembered_set_action, save_fp_mode);
    245     if (offset_.is(no_reg)) {
    246       __ AddP(scratch1_, object_, Operand(offset_immediate_));
    247     } else {
    248       DCHECK_EQ(0, offset_immediate_);
    249       __ AddP(scratch1_, object_, offset_);
    250     }
    251     __ CallStub(&stub);
    252     if (must_save_lr_) {
    253       // We need to save and restore r14 if the frame was elided.
    254       __ Pop(r14);
    255     }
    256   }
    257 
    258  private:
    259   Register const object_;
    260   Register const offset_;
    261   int32_t const offset_immediate_;  // Valid if offset_.is(no_reg).
    262   Register const value_;
    263   Register const scratch0_;
    264   Register const scratch1_;
    265   RecordWriteMode const mode_;
    266   bool must_save_lr_;
    267 };
    268 
    269 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
    270   switch (condition) {
    271     case kEqual:
    272       return eq;
    273     case kNotEqual:
    274       return ne;
    275     case kUnsignedLessThan:
    276       // unsigned number never less than 0
    277       if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64)
    278         return CC_NOP;
    279     // fall through
    280     case kSignedLessThan:
    281       return lt;
    282     case kUnsignedGreaterThanOrEqual:
    283       // unsigned number always greater than or equal 0
    284       if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64)
    285         return CC_ALWAYS;
    286     // fall through
    287     case kSignedGreaterThanOrEqual:
    288       return ge;
    289     case kUnsignedLessThanOrEqual:
    290       // unsigned number never less than 0
    291       if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64)
    292         return CC_EQ;
    293     // fall through
    294     case kSignedLessThanOrEqual:
    295       return le;
    296     case kUnsignedGreaterThan:
    297       // unsigned number always greater than or equal 0
    298       if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64)
    299         return ne;
    300     // fall through
    301     case kSignedGreaterThan:
    302       return gt;
    303     case kOverflow:
    304       // Overflow checked for AddP/SubP only.
    305       switch (op) {
    306         case kS390_Add32:
    307         case kS390_Add64:
    308         case kS390_Sub32:
    309         case kS390_Sub64:
    310           return overflow;
    311         default:
    312           break;
    313       }
    314       break;
    315     case kNotOverflow:
    316       switch (op) {
    317         case kS390_Add32:
    318         case kS390_Add64:
    319         case kS390_Sub32:
    320         case kS390_Sub64:
    321           return nooverflow;
    322         default:
    323           break;
    324       }
    325       break;
    326     default:
    327       break;
    328   }
    329   UNREACHABLE();
    330   return kNoCondition;
    331 }
    332 
    333 typedef void (MacroAssembler::*RRTypeInstr)(Register, Register);
    334 typedef void (MacroAssembler::*RMTypeInstr)(Register, const MemOperand&);
    335 typedef void (MacroAssembler::*RITypeInstr)(Register, const Operand&);
    336 typedef void (MacroAssembler::*RRRTypeInstr)(Register, Register, Register);
    337 typedef void (MacroAssembler::*RRMTypeInstr)(Register, Register,
    338                                              const MemOperand&);
    339 typedef void (MacroAssembler::*RRITypeInstr)(Register, Register,
    340                                              const Operand&);
    341 
    342 #define CHECK_AND_ZERO_EXT_OUTPUT(num)                                   \
    343   {                                                                      \
    344     CHECK(HasImmediateInput(instr, (num)));                              \
    345     int doZeroExt = i.InputInt32(num);                                   \
    346     if (doZeroExt) masm->LoadlW(i.OutputRegister(), i.OutputRegister()); \
    347   }
    348 
    349 void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm,
    350                    Instruction* instr, RRTypeInstr rr_instr,
    351                    RMTypeInstr rm_instr, RITypeInstr ri_instr) {
    352   CHECK(i.OutputRegister().is(i.InputRegister(0)));
    353   AddressingMode mode = AddressingModeField::decode(instr->opcode());
    354   int zeroExtIndex = 2;
    355   if (mode != kMode_None) {
    356     size_t first_index = 1;
    357     MemOperand operand = i.MemoryOperand(&mode, &first_index);
    358     zeroExtIndex = first_index;
    359     CHECK(rm_instr != NULL);
    360     (masm->*rm_instr)(i.OutputRegister(), operand);
    361   } else if (HasRegisterInput(instr, 1)) {
    362     (masm->*rr_instr)(i.OutputRegister(), i.InputRegister(1));
    363   } else if (HasImmediateInput(instr, 1)) {
    364     (masm->*ri_instr)(i.OutputRegister(), i.InputImmediate(1));
    365   } else if (HasStackSlotInput(instr, 1)) {
    366     (masm->*rm_instr)(i.OutputRegister(), i.InputStackSlot32(1));
    367   } else {
    368     UNREACHABLE();
    369   }
    370   CHECK_AND_ZERO_EXT_OUTPUT(zeroExtIndex);
    371 }
    372 
    373 void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm,
    374                    Instruction* instr, RRRTypeInstr rrr_instr,
    375                    RMTypeInstr rm_instr, RITypeInstr ri_instr) {
    376   AddressingMode mode = AddressingModeField::decode(instr->opcode());
    377   int zeroExtIndex = 2;
    378   if (mode != kMode_None) {
    379     CHECK(i.OutputRegister().is(i.InputRegister(0)));
    380     size_t first_index = 1;
    381     MemOperand operand = i.MemoryOperand(&mode, &first_index);
    382     zeroExtIndex = first_index;
    383     CHECK(rm_instr != NULL);
    384     (masm->*rm_instr)(i.OutputRegister(), operand);
    385   } else if (HasRegisterInput(instr, 1)) {
    386     (masm->*rrr_instr)(i.OutputRegister(), i.InputRegister(0),
    387                        i.InputRegister(1));
    388   } else if (HasImmediateInput(instr, 1)) {
    389     CHECK(i.OutputRegister().is(i.InputRegister(0)));
    390     (masm->*ri_instr)(i.OutputRegister(), i.InputImmediate(1));
    391   } else if (HasStackSlotInput(instr, 1)) {
    392     CHECK(i.OutputRegister().is(i.InputRegister(0)));
    393     (masm->*rm_instr)(i.OutputRegister(), i.InputStackSlot32(1));
    394   } else {
    395     UNREACHABLE();
    396   }
    397   CHECK_AND_ZERO_EXT_OUTPUT(zeroExtIndex);
    398 }
    399 
    400 void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm,
    401                    Instruction* instr, RRRTypeInstr rrr_instr,
    402                    RMTypeInstr rm_instr, RRITypeInstr rri_instr) {
    403   AddressingMode mode = AddressingModeField::decode(instr->opcode());
    404   int zeroExtIndex = 2;
    405   if (mode != kMode_None) {
    406     CHECK(i.OutputRegister().is(i.InputRegister(0)));
    407     size_t first_index = 1;
    408     MemOperand operand = i.MemoryOperand(&mode, &first_index);
    409     zeroExtIndex = first_index;
    410     CHECK(rm_instr != NULL);
    411     (masm->*rm_instr)(i.OutputRegister(), operand);
    412   } else if (HasRegisterInput(instr, 1)) {
    413     (masm->*rrr_instr)(i.OutputRegister(), i.InputRegister(0),
    414                        i.InputRegister(1));
    415   } else if (HasImmediateInput(instr, 1)) {
    416     (masm->*rri_instr)(i.OutputRegister(), i.InputRegister(0),
    417                        i.InputImmediate(1));
    418   } else if (HasStackSlotInput(instr, 1)) {
    419     CHECK(i.OutputRegister().is(i.InputRegister(0)));
    420     (masm->*rm_instr)(i.OutputRegister(), i.InputStackSlot32(1));
    421   } else {
    422     UNREACHABLE();
    423   }
    424   CHECK_AND_ZERO_EXT_OUTPUT(zeroExtIndex);
    425 }
    426 
    427 void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm,
    428                    Instruction* instr, RRRTypeInstr rrr_instr,
    429                    RRMTypeInstr rrm_instr, RRITypeInstr rri_instr) {
    430   AddressingMode mode = AddressingModeField::decode(instr->opcode());
    431   int zeroExtIndex = 2;
    432   if (mode != kMode_None) {
    433     size_t first_index = 1;
    434     MemOperand operand = i.MemoryOperand(&mode, &first_index);
    435     zeroExtIndex = first_index;
    436     CHECK(rrm_instr != NULL);
    437     (masm->*rrm_instr)(i.OutputRegister(), i.InputRegister(0), operand);
    438   } else if (HasRegisterInput(instr, 1)) {
    439     (masm->*rrr_instr)(i.OutputRegister(), i.InputRegister(0),
    440                        i.InputRegister(1));
    441   } else if (HasImmediateInput(instr, 1)) {
    442     (masm->*rri_instr)(i.OutputRegister(), i.InputRegister(0),
    443                        i.InputImmediate(1));
    444   } else if (HasStackSlotInput(instr, 1)) {
    445     (masm->*rrm_instr)(i.OutputRegister(), i.InputRegister(0),
    446                        i.InputStackSlot32(1));
    447   } else {
    448     UNREACHABLE();
    449   }
    450   CHECK_AND_ZERO_EXT_OUTPUT(zeroExtIndex);
    451 }
    452 
    453 void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm,
    454                    Instruction* instr, RRRTypeInstr rrr_instr,
    455                    RRITypeInstr rri_instr) {
    456   AddressingMode mode = AddressingModeField::decode(instr->opcode());
    457   CHECK(mode == kMode_None);
    458   int zeroExtIndex = 2;
    459   if (HasRegisterInput(instr, 1)) {
    460     (masm->*rrr_instr)(i.OutputRegister(), i.InputRegister(0),
    461                        i.InputRegister(1));
    462   } else if (HasImmediateInput(instr, 1)) {
    463     (masm->*rri_instr)(i.OutputRegister(), i.InputRegister(0),
    464                        i.InputImmediate(1));
    465   } else {
    466     UNREACHABLE();
    467   }
    468   CHECK_AND_ZERO_EXT_OUTPUT(zeroExtIndex);
    469 }
    470 
    471 void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm,
    472                    Instruction* instr, RRTypeInstr rr_instr,
    473                    RITypeInstr ri_instr) {
    474   AddressingMode mode = AddressingModeField::decode(instr->opcode());
    475   CHECK(mode == kMode_None);
    476   CHECK(i.OutputRegister().is(i.InputRegister(0)));
    477   int zeroExtIndex = 2;
    478   if (HasRegisterInput(instr, 1)) {
    479     (masm->*rr_instr)(i.OutputRegister(), i.InputRegister(1));
    480   } else if (HasImmediateInput(instr, 1)) {
    481     (masm->*ri_instr)(i.OutputRegister(), i.InputImmediate(1));
    482   } else {
    483     UNREACHABLE();
    484   }
    485   CHECK_AND_ZERO_EXT_OUTPUT(zeroExtIndex);
    486 }
    487 
    488 #define ASSEMBLE_BIN_OP(instr1, instr2, instr3)            \
    489   AssembleBinOp(i, masm(), instr, &MacroAssembler::instr1, \
    490                 &MacroAssembler::instr2, &MacroAssembler::instr3)
    491 
    492 #undef CHECK_AND_ZERO_EXT_OUTPUT
    493 
    494 }  // namespace
    495 
    496 #define CHECK_AND_ZERO_EXT_OUTPUT(num)                                \
    497   {                                                                   \
    498     CHECK(HasImmediateInput(instr, (num)));                           \
    499     int doZeroExt = i.InputInt32(num);                                \
    500     if (doZeroExt) __ LoadlW(i.OutputRegister(), i.OutputRegister()); \
    501   }
    502 
    503 #define ASSEMBLE_FLOAT_UNOP(asm_instr)                                \
    504   do {                                                                \
    505     __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
    506   } while (0)
    507 
    508 #define ASSEMBLE_FLOAT_BINOP(asm_instr)                              \
    509   do {                                                               \
    510     __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
    511                  i.InputDoubleRegister(1));                          \
    512   } while (0)
    513 
    514 #define ASSEMBLE_BINOP(asm_instr)                          \
    515   do {                                                     \
    516     if (HasRegisterInput(instr, 1)) {                      \
    517       __ asm_instr(i.OutputRegister(), i.InputRegister(0), \
    518                    i.InputRegister(1));                    \
    519     } else if (HasImmediateInput(instr, 1)) {              \
    520       __ asm_instr(i.OutputRegister(), i.InputRegister(0), \
    521                    i.InputImmediate(1));                   \
    522     } else {                                               \
    523       UNIMPLEMENTED();                                     \
    524     }                                                      \
    525   } while (0)
    526 
    527 #define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr)                         \
    528   do {                                                                  \
    529     AddressingMode mode = AddressingModeField::decode(instr->opcode()); \
    530     if (mode != kMode_None) {                                           \
    531       size_t first_index = 1;                                           \
    532       MemOperand operand = i.MemoryOperand(&mode, &first_index);        \
    533       if (i.CompareLogical()) {                                         \
    534         __ cmpl_instr(i.InputRegister(0), operand);                     \
    535       } else {                                                          \
    536         __ cmp_instr(i.InputRegister(0), operand);                      \
    537       }                                                                 \
    538     } else if (HasRegisterInput(instr, 1)) {                            \
    539       if (i.CompareLogical()) {                                         \
    540         __ cmpl_instr(i.InputRegister(0), i.InputRegister(1));          \
    541       } else {                                                          \
    542         __ cmp_instr(i.InputRegister(0), i.InputRegister(1));           \
    543       }                                                                 \
    544     } else if (HasImmediateInput(instr, 1)) {                           \
    545       if (i.CompareLogical()) {                                         \
    546         __ cmpl_instr(i.InputRegister(0), i.InputImmediate(1));         \
    547       } else {                                                          \
    548         __ cmp_instr(i.InputRegister(0), i.InputImmediate(1));          \
    549       }                                                                 \
    550     } else {                                                            \
    551       DCHECK(HasStackSlotInput(instr, 1));                              \
    552       if (i.CompareLogical()) {                                         \
    553         __ cmpl_instr(i.InputRegister(0), i.InputStackSlot(1));         \
    554       } else {                                                          \
    555         __ cmp_instr(i.InputRegister(0), i.InputStackSlot(1));          \
    556       }                                                                 \
    557     }                                                                   \
    558   } while (0)
    559 
    560 #define ASSEMBLE_COMPARE32(cmp_instr, cmpl_instr)                       \
    561   do {                                                                  \
    562     AddressingMode mode = AddressingModeField::decode(instr->opcode()); \
    563     if (mode != kMode_None) {                                           \
    564       size_t first_index = 1;                                           \
    565       MemOperand operand = i.MemoryOperand(&mode, &first_index);        \
    566       if (i.CompareLogical()) {                                         \
    567         __ cmpl_instr(i.InputRegister(0), operand);                     \
    568       } else {                                                          \
    569         __ cmp_instr(i.InputRegister(0), operand);                      \
    570       }                                                                 \
    571     } else if (HasRegisterInput(instr, 1)) {                            \
    572       if (i.CompareLogical()) {                                         \
    573         __ cmpl_instr(i.InputRegister(0), i.InputRegister(1));          \
    574       } else {                                                          \
    575         __ cmp_instr(i.InputRegister(0), i.InputRegister(1));           \
    576       }                                                                 \
    577     } else if (HasImmediateInput(instr, 1)) {                           \
    578       if (i.CompareLogical()) {                                         \
    579         __ cmpl_instr(i.InputRegister(0), i.InputImmediate(1));         \
    580       } else {                                                          \
    581         __ cmp_instr(i.InputRegister(0), i.InputImmediate(1));          \
    582       }                                                                 \
    583     } else {                                                            \
    584       DCHECK(HasStackSlotInput(instr, 1));                              \
    585       if (i.CompareLogical()) {                                         \
    586         __ cmpl_instr(i.InputRegister(0), i.InputStackSlot32(1));       \
    587       } else {                                                          \
    588         __ cmp_instr(i.InputRegister(0), i.InputStackSlot32(1));        \
    589       }                                                                 \
    590     }                                                                   \
    591   } while (0)
    592 
    593 #define ASSEMBLE_FLOAT_COMPARE(cmp_rr_instr, cmp_rm_instr, load_instr)     \
    594   do {                                                                     \
    595     AddressingMode mode = AddressingModeField::decode(instr->opcode());    \
    596     if (mode != kMode_None) {                                              \
    597       size_t first_index = 1;                                              \
    598       MemOperand operand = i.MemoryOperand(&mode, &first_index);           \
    599       __ cmp_rm_instr(i.InputDoubleRegister(0), operand);                  \
    600     } else if (HasFPRegisterInput(instr, 1)) {                             \
    601       __ cmp_rr_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
    602     } else {                                                               \
    603       USE(HasFPStackSlotInput);                                            \
    604       DCHECK(HasFPStackSlotInput(instr, 1));                               \
    605       MemOperand operand = i.InputStackSlot(1);                            \
    606       if (operand.offset() >= 0) {                                         \
    607         __ cmp_rm_instr(i.InputDoubleRegister(0), operand);                \
    608       } else {                                                             \
    609         __ load_instr(kScratchDoubleReg, operand);                         \
    610         __ cmp_rr_instr(i.InputDoubleRegister(0), kScratchDoubleReg);      \
    611       }                                                                    \
    612     }                                                                      \
    613   } while (0)
    614 
    615 // Divide instruction dr will implicity use register pair
    616 // r0 & r1 below.
    617 // R0:R1 = R1 / divisor - R0 remainder
    618 // Copy remainder to output reg
    619 #define ASSEMBLE_MODULO(div_instr, shift_instr) \
    620   do {                                          \
    621     __ LoadRR(r0, i.InputRegister(0));          \
    622     __ shift_instr(r0, Operand(32));            \
    623     __ div_instr(r0, i.InputRegister(1));       \
    624     __ LoadlW(i.OutputRegister(), r0);          \
    625   } while (0)
    626 
    627 #define ASSEMBLE_FLOAT_MODULO()                                               \
    628   do {                                                                        \
    629     FrameScope scope(masm(), StackFrame::MANUAL);                             \
    630     __ PrepareCallCFunction(0, 2, kScratchReg);                               \
    631     __ MovToFloatParameters(i.InputDoubleRegister(0),                         \
    632                             i.InputDoubleRegister(1));                        \
    633     __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), \
    634                      0, 2);                                                   \
    635     __ MovFromFloatResult(i.OutputDoubleRegister());                          \
    636   } while (0)
    637 
    638 #define ASSEMBLE_IEEE754_UNOP(name)                                            \
    639   do {                                                                         \
    640     /* TODO(bmeurer): We should really get rid of this special instruction, */ \
    641     /* and generate a CallAddress instruction instead. */                      \
    642     FrameScope scope(masm(), StackFrame::MANUAL);                              \
    643     __ PrepareCallCFunction(0, 1, kScratchReg);                                \
    644     __ MovToFloatParameter(i.InputDoubleRegister(0));                          \
    645     __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
    646                      0, 1);                                                    \
    647     /* Move the result in the double result register. */                       \
    648     __ MovFromFloatResult(i.OutputDoubleRegister());                           \
    649   } while (0)
    650 
    651 #define ASSEMBLE_IEEE754_BINOP(name)                                           \
    652   do {                                                                         \
    653     /* TODO(bmeurer): We should really get rid of this special instruction, */ \
    654     /* and generate a CallAddress instruction instead. */                      \
    655     FrameScope scope(masm(), StackFrame::MANUAL);                              \
    656     __ PrepareCallCFunction(0, 2, kScratchReg);                                \
    657     __ MovToFloatParameters(i.InputDoubleRegister(0),                          \
    658                             i.InputDoubleRegister(1));                         \
    659     __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
    660                      0, 2);                                                    \
    661     /* Move the result in the double result register. */                       \
    662     __ MovFromFloatResult(i.OutputDoubleRegister());                           \
    663   } while (0)
    664 
    665 #define ASSEMBLE_DOUBLE_MAX()                                          \
    666   do {                                                                 \
    667     DoubleRegister left_reg = i.InputDoubleRegister(0);                \
    668     DoubleRegister right_reg = i.InputDoubleRegister(1);               \
    669     DoubleRegister result_reg = i.OutputDoubleRegister();              \
    670     Label check_nan_left, check_zero, return_left, return_right, done; \
    671     __ cdbr(left_reg, right_reg);                                      \
    672     __ bunordered(&check_nan_left, Label::kNear);                      \
    673     __ beq(&check_zero);                                               \
    674     __ bge(&return_left, Label::kNear);                                \
    675     __ b(&return_right, Label::kNear);                                 \
    676                                                                        \
    677     __ bind(&check_zero);                                              \
    678     __ lzdr(kDoubleRegZero);                                           \
    679     __ cdbr(left_reg, kDoubleRegZero);                                 \
    680     /* left == right != 0. */                                          \
    681     __ bne(&return_left, Label::kNear);                                \
    682     /* At this point, both left and right are either 0 or -0. */       \
    683     /* N.B. The following works because +0 + -0 == +0 */               \
    684     /* For max we want logical-and of sign bit: (L + R) */             \
    685     __ ldr(result_reg, left_reg);                                      \
    686     __ adbr(result_reg, right_reg);                                    \
    687     __ b(&done, Label::kNear);                                         \
    688                                                                        \
    689     __ bind(&check_nan_left);                                          \
    690     __ cdbr(left_reg, left_reg);                                       \
    691     /* left == NaN. */                                                 \
    692     __ bunordered(&return_left, Label::kNear);                         \
    693                                                                        \
    694     __ bind(&return_right);                                            \
    695     if (!right_reg.is(result_reg)) {                                   \
    696       __ ldr(result_reg, right_reg);                                   \
    697     }                                                                  \
    698     __ b(&done, Label::kNear);                                         \
    699                                                                        \
    700     __ bind(&return_left);                                             \
    701     if (!left_reg.is(result_reg)) {                                    \
    702       __ ldr(result_reg, left_reg);                                    \
    703     }                                                                  \
    704     __ bind(&done);                                                    \
    705   } while (0)
    706 
    707 #define ASSEMBLE_DOUBLE_MIN()                                          \
    708   do {                                                                 \
    709     DoubleRegister left_reg = i.InputDoubleRegister(0);                \
    710     DoubleRegister right_reg = i.InputDoubleRegister(1);               \
    711     DoubleRegister result_reg = i.OutputDoubleRegister();              \
    712     Label check_nan_left, check_zero, return_left, return_right, done; \
    713     __ cdbr(left_reg, right_reg);                                      \
    714     __ bunordered(&check_nan_left, Label::kNear);                      \
    715     __ beq(&check_zero);                                               \
    716     __ ble(&return_left, Label::kNear);                                \
    717     __ b(&return_right, Label::kNear);                                 \
    718                                                                        \
    719     __ bind(&check_zero);                                              \
    720     __ lzdr(kDoubleRegZero);                                           \
    721     __ cdbr(left_reg, kDoubleRegZero);                                 \
    722     /* left == right != 0. */                                          \
    723     __ bne(&return_left, Label::kNear);                                \
    724     /* At this point, both left and right are either 0 or -0. */       \
    725     /* N.B. The following works because +0 + -0 == +0 */               \
    726     /* For min we want logical-or of sign bit: -(-L + -R) */           \
    727     __ lcdbr(left_reg, left_reg);                                      \
    728     __ ldr(result_reg, left_reg);                                      \
    729     if (left_reg.is(right_reg)) {                                      \
    730       __ adbr(result_reg, right_reg);                                  \
    731     } else {                                                           \
    732       __ sdbr(result_reg, right_reg);                                  \
    733     }                                                                  \
    734     __ lcdbr(result_reg, result_reg);                                  \
    735     __ b(&done, Label::kNear);                                         \
    736                                                                        \
    737     __ bind(&check_nan_left);                                          \
    738     __ cdbr(left_reg, left_reg);                                       \
    739     /* left == NaN. */                                                 \
    740     __ bunordered(&return_left, Label::kNear);                         \
    741                                                                        \
    742     __ bind(&return_right);                                            \
    743     if (!right_reg.is(result_reg)) {                                   \
    744       __ ldr(result_reg, right_reg);                                   \
    745     }                                                                  \
    746     __ b(&done, Label::kNear);                                         \
    747                                                                        \
    748     __ bind(&return_left);                                             \
    749     if (!left_reg.is(result_reg)) {                                    \
    750       __ ldr(result_reg, left_reg);                                    \
    751     }                                                                  \
    752     __ bind(&done);                                                    \
    753   } while (0)
    754 
    755 #define ASSEMBLE_FLOAT_MAX()                                           \
    756   do {                                                                 \
    757     DoubleRegister left_reg = i.InputDoubleRegister(0);                \
    758     DoubleRegister right_reg = i.InputDoubleRegister(1);               \
    759     DoubleRegister result_reg = i.OutputDoubleRegister();              \
    760     Label check_nan_left, check_zero, return_left, return_right, done; \
    761     __ cebr(left_reg, right_reg);                                      \
    762     __ bunordered(&check_nan_left, Label::kNear);                      \
    763     __ beq(&check_zero);                                               \
    764     __ bge(&return_left, Label::kNear);                                \
    765     __ b(&return_right, Label::kNear);                                 \
    766                                                                        \
    767     __ bind(&check_zero);                                              \
    768     __ lzdr(kDoubleRegZero);                                           \
    769     __ cebr(left_reg, kDoubleRegZero);                                 \
    770     /* left == right != 0. */                                          \
    771     __ bne(&return_left, Label::kNear);                                \
    772     /* At this point, both left and right are either 0 or -0. */       \
    773     /* N.B. The following works because +0 + -0 == +0 */               \
    774     /* For max we want logical-and of sign bit: (L + R) */             \
    775     __ ldr(result_reg, left_reg);                                      \
    776     __ aebr(result_reg, right_reg);                                    \
    777     __ b(&done, Label::kNear);                                         \
    778                                                                        \
    779     __ bind(&check_nan_left);                                          \
    780     __ cebr(left_reg, left_reg);                                       \
    781     /* left == NaN. */                                                 \
    782     __ bunordered(&return_left, Label::kNear);                         \
    783                                                                        \
    784     __ bind(&return_right);                                            \
    785     if (!right_reg.is(result_reg)) {                                   \
    786       __ ldr(result_reg, right_reg);                                   \
    787     }                                                                  \
    788     __ b(&done, Label::kNear);                                         \
    789                                                                        \
    790     __ bind(&return_left);                                             \
    791     if (!left_reg.is(result_reg)) {                                    \
    792       __ ldr(result_reg, left_reg);                                    \
    793     }                                                                  \
    794     __ bind(&done);                                                    \
    795   } while (0)
    796 
    797 #define ASSEMBLE_FLOAT_MIN()                                           \
    798   do {                                                                 \
    799     DoubleRegister left_reg = i.InputDoubleRegister(0);                \
    800     DoubleRegister right_reg = i.InputDoubleRegister(1);               \
    801     DoubleRegister result_reg = i.OutputDoubleRegister();              \
    802     Label check_nan_left, check_zero, return_left, return_right, done; \
    803     __ cebr(left_reg, right_reg);                                      \
    804     __ bunordered(&check_nan_left, Label::kNear);                      \
    805     __ beq(&check_zero);                                               \
    806     __ ble(&return_left, Label::kNear);                                \
    807     __ b(&return_right, Label::kNear);                                 \
    808                                                                        \
    809     __ bind(&check_zero);                                              \
    810     __ lzdr(kDoubleRegZero);                                           \
    811     __ cebr(left_reg, kDoubleRegZero);                                 \
    812     /* left == right != 0. */                                          \
    813     __ bne(&return_left, Label::kNear);                                \
    814     /* At this point, both left and right are either 0 or -0. */       \
    815     /* N.B. The following works because +0 + -0 == +0 */               \
    816     /* For min we want logical-or of sign bit: -(-L + -R) */           \
    817     __ lcebr(left_reg, left_reg);                                      \
    818     __ ldr(result_reg, left_reg);                                      \
    819     if (left_reg.is(right_reg)) {                                      \
    820       __ aebr(result_reg, right_reg);                                  \
    821     } else {                                                           \
    822       __ sebr(result_reg, right_reg);                                  \
    823     }                                                                  \
    824     __ lcebr(result_reg, result_reg);                                  \
    825     __ b(&done, Label::kNear);                                         \
    826                                                                        \
    827     __ bind(&check_nan_left);                                          \
    828     __ cebr(left_reg, left_reg);                                       \
    829     /* left == NaN. */                                                 \
    830     __ bunordered(&return_left, Label::kNear);                         \
    831                                                                        \
    832     __ bind(&return_right);                                            \
    833     if (!right_reg.is(result_reg)) {                                   \
    834       __ ldr(result_reg, right_reg);                                   \
    835     }                                                                  \
    836     __ b(&done, Label::kNear);                                         \
    837                                                                        \
    838     __ bind(&return_left);                                             \
    839     if (!left_reg.is(result_reg)) {                                    \
    840       __ ldr(result_reg, left_reg);                                    \
    841     }                                                                  \
    842     __ bind(&done);                                                    \
    843   } while (0)
    844 //
    845 // Only MRI mode for these instructions available
    846 #define ASSEMBLE_LOAD_FLOAT(asm_instr)                \
    847   do {                                                \
    848     DoubleRegister result = i.OutputDoubleRegister(); \
    849     AddressingMode mode = kMode_None;                 \
    850     MemOperand operand = i.MemoryOperand(&mode);      \
    851     __ asm_instr(result, operand);                    \
    852   } while (0)
    853 
    854 #define ASSEMBLE_LOAD_INTEGER(asm_instr)         \
    855   do {                                           \
    856     Register result = i.OutputRegister();        \
    857     AddressingMode mode = kMode_None;            \
    858     MemOperand operand = i.MemoryOperand(&mode); \
    859     __ asm_instr(result, operand);               \
    860   } while (0)
    861 
    862 #define ASSEMBLE_LOADANDTEST64(asm_instr_rr, asm_instr_rm)              \
    863   {                                                                     \
    864     AddressingMode mode = AddressingModeField::decode(instr->opcode()); \
    865     Register dst = HasRegisterOutput(instr) ? i.OutputRegister() : r0;  \
    866     if (mode != kMode_None) {                                           \
    867       size_t first_index = 0;                                           \
    868       MemOperand operand = i.MemoryOperand(&mode, &first_index);        \
    869       __ asm_instr_rm(dst, operand);                                    \
    870     } else if (HasRegisterInput(instr, 0)) {                            \
    871       __ asm_instr_rr(dst, i.InputRegister(0));                         \
    872     } else {                                                            \
    873       DCHECK(HasStackSlotInput(instr, 0));                              \
    874       __ asm_instr_rm(dst, i.InputStackSlot(0));                        \
    875     }                                                                   \
    876   }
    877 
    878 #define ASSEMBLE_LOADANDTEST32(asm_instr_rr, asm_instr_rm)              \
    879   {                                                                     \
    880     AddressingMode mode = AddressingModeField::decode(instr->opcode()); \
    881     Register dst = HasRegisterOutput(instr) ? i.OutputRegister() : r0;  \
    882     if (mode != kMode_None) {                                           \
    883       size_t first_index = 0;                                           \
    884       MemOperand operand = i.MemoryOperand(&mode, &first_index);        \
    885       __ asm_instr_rm(dst, operand);                                    \
    886     } else if (HasRegisterInput(instr, 0)) {                            \
    887       __ asm_instr_rr(dst, i.InputRegister(0));                         \
    888     } else {                                                            \
    889       DCHECK(HasStackSlotInput(instr, 0));                              \
    890       __ asm_instr_rm(dst, i.InputStackSlot32(0));                      \
    891     }                                                                   \
    892   }
    893 
    894 #define ASSEMBLE_STORE_FLOAT32()                         \
    895   do {                                                   \
    896     size_t index = 0;                                    \
    897     AddressingMode mode = kMode_None;                    \
    898     MemOperand operand = i.MemoryOperand(&mode, &index); \
    899     DoubleRegister value = i.InputDoubleRegister(index); \
    900     __ StoreFloat32(value, operand);                     \
    901   } while (0)
    902 
    903 #define ASSEMBLE_STORE_DOUBLE()                          \
    904   do {                                                   \
    905     size_t index = 0;                                    \
    906     AddressingMode mode = kMode_None;                    \
    907     MemOperand operand = i.MemoryOperand(&mode, &index); \
    908     DoubleRegister value = i.InputDoubleRegister(index); \
    909     __ StoreDouble(value, operand);                      \
    910   } while (0)
    911 
    912 #define ASSEMBLE_STORE_INTEGER(asm_instr)                \
    913   do {                                                   \
    914     size_t index = 0;                                    \
    915     AddressingMode mode = kMode_None;                    \
    916     MemOperand operand = i.MemoryOperand(&mode, &index); \
    917     Register value = i.InputRegister(index);             \
    918     __ asm_instr(value, operand);                        \
    919   } while (0)
    920 
    921 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, width)              \
    922   do {                                                             \
    923     DoubleRegister result = i.OutputDoubleRegister();              \
    924     size_t index = 0;                                              \
    925     AddressingMode mode = kMode_None;                              \
    926     MemOperand operand = i.MemoryOperand(&mode, index);            \
    927     Register offset = operand.rb();                                \
    928     if (HasRegisterInput(instr, 2)) {                              \
    929       __ CmpLogical32(offset, i.InputRegister(2));                 \
    930     } else {                                                       \
    931       __ CmpLogical32(offset, i.InputImmediate(2));                \
    932     }                                                              \
    933     auto ool = new (zone()) OutOfLineLoadNAN##width(this, result); \
    934     __ bge(ool->entry());                                          \
    935     __ CleanUInt32(offset);                                        \
    936     __ asm_instr(result, operand);                                 \
    937     __ bind(ool->exit());                                          \
    938   } while (0)
    939 
    940 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)             \
    941   do {                                                       \
    942     Register result = i.OutputRegister();                    \
    943     size_t index = 0;                                        \
    944     AddressingMode mode = kMode_None;                        \
    945     MemOperand operand = i.MemoryOperand(&mode, index);      \
    946     Register offset = operand.rb();                          \
    947     if (HasRegisterInput(instr, 2)) {                        \
    948       __ CmpLogical32(offset, i.InputRegister(2));           \
    949     } else {                                                 \
    950       __ CmpLogical32(offset, i.InputImmediate(2));          \
    951     }                                                        \
    952     auto ool = new (zone()) OutOfLineLoadZero(this, result); \
    953     __ bge(ool->entry());                                    \
    954     __ CleanUInt32(offset);                                  \
    955     __ asm_instr(result, operand);                           \
    956     __ bind(ool->exit());                                    \
    957   } while (0)
    958 
    959 #define ASSEMBLE_CHECKED_STORE_FLOAT32()                \
    960   do {                                                  \
    961     Label done;                                         \
    962     size_t index = 0;                                   \
    963     AddressingMode mode = kMode_None;                   \
    964     MemOperand operand = i.MemoryOperand(&mode, index); \
    965     Register offset = operand.rb();                     \
    966     if (HasRegisterInput(instr, 2)) {                   \
    967       __ CmpLogical32(offset, i.InputRegister(2));      \
    968     } else {                                            \
    969       __ CmpLogical32(offset, i.InputImmediate(2));     \
    970     }                                                   \
    971     __ bge(&done);                                      \
    972     DoubleRegister value = i.InputDoubleRegister(3);    \
    973     __ CleanUInt32(offset);                             \
    974     __ StoreFloat32(value, operand);                    \
    975     __ bind(&done);                                     \
    976   } while (0)
    977 
    978 #define ASSEMBLE_CHECKED_STORE_DOUBLE()                 \
    979   do {                                                  \
    980     Label done;                                         \
    981     size_t index = 0;                                   \
    982     AddressingMode mode = kMode_None;                   \
    983     MemOperand operand = i.MemoryOperand(&mode, index); \
    984     DCHECK_EQ(kMode_MRR, mode);                         \
    985     Register offset = operand.rb();                     \
    986     if (HasRegisterInput(instr, 2)) {                   \
    987       __ CmpLogical32(offset, i.InputRegister(2));      \
    988     } else {                                            \
    989       __ CmpLogical32(offset, i.InputImmediate(2));     \
    990     }                                                   \
    991     __ bge(&done);                                      \
    992     DoubleRegister value = i.InputDoubleRegister(3);    \
    993     __ CleanUInt32(offset);                             \
    994     __ StoreDouble(value, operand);                     \
    995     __ bind(&done);                                     \
    996   } while (0)
    997 
    998 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)       \
    999   do {                                                  \
   1000     Label done;                                         \
   1001     size_t index = 0;                                   \
   1002     AddressingMode mode = kMode_None;                   \
   1003     MemOperand operand = i.MemoryOperand(&mode, index); \
   1004     Register offset = operand.rb();                     \
   1005     if (HasRegisterInput(instr, 2)) {                   \
   1006       __ CmpLogical32(offset, i.InputRegister(2));      \
   1007     } else {                                            \
   1008       __ CmpLogical32(offset, i.InputImmediate(2));     \
   1009     }                                                   \
   1010     __ bge(&done);                                      \
   1011     Register value = i.InputRegister(3);                \
   1012     __ CleanUInt32(offset);                             \
   1013     __ asm_instr(value, operand);                       \
   1014     __ bind(&done);                                     \
   1015   } while (0)
   1016 
   1017 void CodeGenerator::AssembleDeconstructFrame() {
   1018   __ LeaveFrame(StackFrame::MANUAL);
   1019 }
   1020 
   1021 void CodeGenerator::AssemblePrepareTailCall() {
   1022   if (frame_access_state()->has_frame()) {
   1023     __ RestoreFrameStateForTailCall();
   1024   }
   1025   frame_access_state()->SetFrameAccessToSP();
   1026 }
   1027 
   1028 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
   1029                                                      Register scratch1,
   1030                                                      Register scratch2,
   1031                                                      Register scratch3) {
   1032   DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
   1033   Label done;
   1034 
   1035   // Check if current frame is an arguments adaptor frame.
   1036   __ LoadP(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset));
   1037   __ CmpP(scratch1,
   1038           Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
   1039   __ bne(&done);
   1040 
   1041   // Load arguments count from current arguments adaptor frame (note, it
   1042   // does not include receiver).
   1043   Register caller_args_count_reg = scratch1;
   1044   __ LoadP(caller_args_count_reg,
   1045            MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
   1046   __ SmiUntag(caller_args_count_reg);
   1047 
   1048   ParameterCount callee_args_count(args_reg);
   1049   __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
   1050                         scratch3);
   1051   __ bind(&done);
   1052 }
   1053 
   1054 namespace {
   1055 
   1056 void FlushPendingPushRegisters(MacroAssembler* masm,
   1057                                FrameAccessState* frame_access_state,
   1058                                ZoneVector<Register>* pending_pushes) {
   1059   switch (pending_pushes->size()) {
   1060     case 0:
   1061       break;
   1062     case 1:
   1063       masm->Push((*pending_pushes)[0]);
   1064       break;
   1065     case 2:
   1066       masm->Push((*pending_pushes)[0], (*pending_pushes)[1]);
   1067       break;
   1068     case 3:
   1069       masm->Push((*pending_pushes)[0], (*pending_pushes)[1],
   1070                  (*pending_pushes)[2]);
   1071       break;
   1072     default:
   1073       UNREACHABLE();
   1074       break;
   1075   }
   1076   frame_access_state->IncreaseSPDelta(pending_pushes->size());
   1077   pending_pushes->resize(0);
   1078 }
   1079 
   1080 void AddPendingPushRegister(MacroAssembler* masm,
   1081                             FrameAccessState* frame_access_state,
   1082                             ZoneVector<Register>* pending_pushes,
   1083                             Register reg) {
   1084   pending_pushes->push_back(reg);
   1085   if (pending_pushes->size() == 3 || reg.is(ip)) {
   1086     FlushPendingPushRegisters(masm, frame_access_state, pending_pushes);
   1087   }
   1088 }
   1089 void AdjustStackPointerForTailCall(
   1090     MacroAssembler* masm, FrameAccessState* state, int new_slot_above_sp,
   1091     ZoneVector<Register>* pending_pushes = nullptr,
   1092     bool allow_shrinkage = true) {
   1093   int current_sp_offset = state->GetSPToFPSlotCount() +
   1094                           StandardFrameConstants::kFixedSlotCountAboveFp;
   1095   int stack_slot_delta = new_slot_above_sp - current_sp_offset;
   1096   if (stack_slot_delta > 0) {
   1097     if (pending_pushes != nullptr) {
   1098       FlushPendingPushRegisters(masm, state, pending_pushes);
   1099     }
   1100     masm->AddP(sp, sp, Operand(-stack_slot_delta * kPointerSize));
   1101     state->IncreaseSPDelta(stack_slot_delta);
   1102   } else if (allow_shrinkage && stack_slot_delta < 0) {
   1103     if (pending_pushes != nullptr) {
   1104       FlushPendingPushRegisters(masm, state, pending_pushes);
   1105     }
   1106     masm->AddP(sp, sp, Operand(-stack_slot_delta * kPointerSize));
   1107     state->IncreaseSPDelta(stack_slot_delta);
   1108   }
   1109 }
   1110 
   1111 }  // namespace
   1112 
   1113 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
   1114                                               int first_unused_stack_slot) {
   1115   CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush);
   1116   ZoneVector<MoveOperands*> pushes(zone());
   1117   GetPushCompatibleMoves(instr, flags, &pushes);
   1118 
   1119   if (!pushes.empty() &&
   1120       (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
   1121        first_unused_stack_slot)) {
   1122     S390OperandConverter g(this, instr);
   1123     ZoneVector<Register> pending_pushes(zone());
   1124     for (auto move : pushes) {
   1125       LocationOperand destination_location(
   1126           LocationOperand::cast(move->destination()));
   1127       InstructionOperand source(move->source());
   1128       AdjustStackPointerForTailCall(
   1129           masm(), frame_access_state(),
   1130           destination_location.index() - pending_pushes.size(),
   1131           &pending_pushes);
   1132       if (source.IsStackSlot()) {
   1133         LocationOperand source_location(LocationOperand::cast(source));
   1134         __ LoadP(ip, g.SlotToMemOperand(source_location.index()));
   1135         AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
   1136                                ip);
   1137       } else if (source.IsRegister()) {
   1138         LocationOperand source_location(LocationOperand::cast(source));
   1139         AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
   1140                                source_location.GetRegister());
   1141       } else if (source.IsImmediate()) {
   1142         AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
   1143                                ip);
   1144       } else {
   1145         // Pushes of non-scalar data types is not supported.
   1146         UNIMPLEMENTED();
   1147       }
   1148       move->Eliminate();
   1149     }
   1150     FlushPendingPushRegisters(masm(), frame_access_state(), &pending_pushes);
   1151   }
   1152   AdjustStackPointerForTailCall(masm(), frame_access_state(),
   1153                                 first_unused_stack_slot, nullptr, false);
   1154 }
   1155 
   1156 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
   1157                                              int first_unused_stack_slot) {
   1158   AdjustStackPointerForTailCall(masm(), frame_access_state(),
   1159                                 first_unused_stack_slot);
   1160 }
   1161 
   1162 // Assembles an instruction after register allocation, producing machine code.
   1163 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
   1164     Instruction* instr) {
   1165   S390OperandConverter i(this, instr);
   1166   ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode());
   1167 
   1168   switch (opcode) {
   1169     case kArchComment: {
   1170       Address comment_string = i.InputExternalReference(0).address();
   1171       __ RecordComment(reinterpret_cast<const char*>(comment_string));
   1172       break;
   1173     }
   1174     case kArchCallCodeObject: {
   1175       EnsureSpaceForLazyDeopt();
   1176       if (HasRegisterInput(instr, 0)) {
   1177         __ AddP(ip, i.InputRegister(0),
   1178                 Operand(Code::kHeaderSize - kHeapObjectTag));
   1179         __ Call(ip);
   1180       } else {
   1181         __ Call(Handle<Code>::cast(i.InputHeapObject(0)),
   1182                 RelocInfo::CODE_TARGET);
   1183       }
   1184       RecordCallPosition(instr);
   1185       frame_access_state()->ClearSPDelta();
   1186       break;
   1187     }
   1188     case kArchTailCallCodeObjectFromJSFunction:
   1189     case kArchTailCallCodeObject: {
   1190       if (opcode == kArchTailCallCodeObjectFromJSFunction) {
   1191         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
   1192                                          i.TempRegister(0), i.TempRegister(1),
   1193                                          i.TempRegister(2));
   1194       }
   1195       if (HasRegisterInput(instr, 0)) {
   1196         __ AddP(ip, i.InputRegister(0),
   1197                 Operand(Code::kHeaderSize - kHeapObjectTag));
   1198         __ Jump(ip);
   1199       } else {
   1200         // We cannot use the constant pool to load the target since
   1201         // we've already restored the caller's frame.
   1202         ConstantPoolUnavailableScope constant_pool_unavailable(masm());
   1203         __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
   1204                 RelocInfo::CODE_TARGET);
   1205       }
   1206       frame_access_state()->ClearSPDelta();
   1207       frame_access_state()->SetFrameAccessToDefault();
   1208       break;
   1209     }
   1210     case kArchTailCallAddress: {
   1211       CHECK(!instr->InputAt(0)->IsImmediate());
   1212       __ Jump(i.InputRegister(0));
   1213       frame_access_state()->ClearSPDelta();
   1214       frame_access_state()->SetFrameAccessToDefault();
   1215       break;
   1216     }
   1217     case kArchCallJSFunction: {
   1218       EnsureSpaceForLazyDeopt();
   1219       Register func = i.InputRegister(0);
   1220       if (FLAG_debug_code) {
   1221         // Check the function's context matches the context argument.
   1222         __ LoadP(kScratchReg,
   1223                  FieldMemOperand(func, JSFunction::kContextOffset));
   1224         __ CmpP(cp, kScratchReg);
   1225         __ Assert(eq, kWrongFunctionContext);
   1226       }
   1227       __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
   1228       __ Call(ip);
   1229       RecordCallPosition(instr);
   1230       frame_access_state()->ClearSPDelta();
   1231       break;
   1232     }
   1233     case kArchTailCallJSFunctionFromJSFunction: {
   1234       Register func = i.InputRegister(0);
   1235       if (FLAG_debug_code) {
   1236         // Check the function's context matches the context argument.
   1237         __ LoadP(kScratchReg,
   1238                  FieldMemOperand(func, JSFunction::kContextOffset));
   1239         __ CmpP(cp, kScratchReg);
   1240         __ Assert(eq, kWrongFunctionContext);
   1241       }
   1242       AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
   1243                                        i.TempRegister(0), i.TempRegister(1),
   1244                                        i.TempRegister(2));
   1245       __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
   1246       __ Jump(ip);
   1247       frame_access_state()->ClearSPDelta();
   1248       frame_access_state()->SetFrameAccessToDefault();
   1249       break;
   1250     }
   1251     case kArchPrepareCallCFunction: {
   1252       int const num_parameters = MiscField::decode(instr->opcode());
   1253       __ PrepareCallCFunction(num_parameters, kScratchReg);
   1254       // Frame alignment requires using FP-relative frame addressing.
   1255       frame_access_state()->SetFrameAccessToFP();
   1256       break;
   1257     }
   1258     case kArchPrepareTailCall:
   1259       AssemblePrepareTailCall();
   1260       break;
   1261     case kArchCallCFunction: {
   1262       int const num_parameters = MiscField::decode(instr->opcode());
   1263       if (instr->InputAt(0)->IsImmediate()) {
   1264         ExternalReference ref = i.InputExternalReference(0);
   1265         __ CallCFunction(ref, num_parameters);
   1266       } else {
   1267         Register func = i.InputRegister(0);
   1268         __ CallCFunction(func, num_parameters);
   1269       }
   1270       frame_access_state()->SetFrameAccessToDefault();
   1271       frame_access_state()->ClearSPDelta();
   1272       break;
   1273     }
   1274     case kArchJmp:
   1275       AssembleArchJump(i.InputRpo(0));
   1276       break;
   1277     case kArchLookupSwitch:
   1278       AssembleArchLookupSwitch(instr);
   1279       break;
   1280     case kArchTableSwitch:
   1281       AssembleArchTableSwitch(instr);
   1282       break;
   1283     case kArchDebugBreak:
   1284       __ stop("kArchDebugBreak");
   1285       break;
   1286     case kArchNop:
   1287     case kArchThrowTerminator:
   1288       // don't emit code for nops.
   1289       break;
   1290     case kArchDeoptimize: {
   1291       int deopt_state_id =
   1292           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
   1293       CodeGenResult result =
   1294           AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
   1295       if (result != kSuccess) return result;
   1296       break;
   1297     }
   1298     case kArchRet:
   1299       AssembleReturn(instr->InputAt(0));
   1300       break;
   1301     case kArchStackPointer:
   1302       __ LoadRR(i.OutputRegister(), sp);
   1303       break;
   1304     case kArchFramePointer:
   1305       __ LoadRR(i.OutputRegister(), fp);
   1306       break;
   1307     case kArchParentFramePointer:
   1308       if (frame_access_state()->has_frame()) {
   1309         __ LoadP(i.OutputRegister(), MemOperand(fp, 0));
   1310       } else {
   1311         __ LoadRR(i.OutputRegister(), fp);
   1312       }
   1313       break;
   1314     case kArchTruncateDoubleToI:
   1315       // TODO(mbrandy): move slow call to stub out of line.
   1316       __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
   1317       break;
   1318     case kArchStoreWithWriteBarrier: {
   1319       RecordWriteMode mode =
   1320           static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
   1321       Register object = i.InputRegister(0);
   1322       Register value = i.InputRegister(2);
   1323       Register scratch0 = i.TempRegister(0);
   1324       Register scratch1 = i.TempRegister(1);
   1325       OutOfLineRecordWrite* ool;
   1326 
   1327       AddressingMode addressing_mode =
   1328           AddressingModeField::decode(instr->opcode());
   1329       if (addressing_mode == kMode_MRI) {
   1330         int32_t offset = i.InputInt32(1);
   1331         ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value,
   1332                                                 scratch0, scratch1, mode);
   1333         __ StoreP(value, MemOperand(object, offset));
   1334       } else {
   1335         DCHECK_EQ(kMode_MRR, addressing_mode);
   1336         Register offset(i.InputRegister(1));
   1337         ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value,
   1338                                                 scratch0, scratch1, mode);
   1339         __ StoreP(value, MemOperand(object, offset));
   1340       }
   1341       __ CheckPageFlag(object, scratch0,
   1342                        MemoryChunk::kPointersFromHereAreInterestingMask, ne,
   1343                        ool->entry());
   1344       __ bind(ool->exit());
   1345       break;
   1346     }
   1347     case kArchStackSlot: {
   1348       FrameOffset offset =
   1349           frame_access_state()->GetFrameOffset(i.InputInt32(0));
   1350       __ AddP(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
   1351               Operand(offset.offset()));
   1352       break;
   1353     }
   1354     case kS390_And32:
   1355       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1356         ASSEMBLE_BIN_OP(nrk, And, nilf);
   1357       } else {
   1358         ASSEMBLE_BIN_OP(nr, And, nilf);
   1359       }
   1360       break;
   1361     case kS390_And64:
   1362       ASSEMBLE_BINOP(AndP);
   1363       break;
   1364     case kS390_Or32:
   1365       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1366         ASSEMBLE_BIN_OP(ork, Or, oilf);
   1367       } else {
   1368         ASSEMBLE_BIN_OP(or_z, Or, oilf);
   1369       }
   1370       break;
   1371     case kS390_Or64:
   1372       ASSEMBLE_BINOP(OrP);
   1373       break;
   1374     case kS390_Xor32:
   1375       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1376         ASSEMBLE_BIN_OP(xrk, Xor, xilf);
   1377       } else {
   1378         ASSEMBLE_BIN_OP(xr, Xor, xilf);
   1379       }
   1380       break;
   1381     case kS390_Xor64:
   1382       ASSEMBLE_BINOP(XorP);
   1383       break;
   1384     case kS390_ShiftLeft32:
   1385       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1386         AssembleBinOp(i, masm(), instr, &MacroAssembler::ShiftLeft,
   1387                       &MacroAssembler::ShiftLeft);
   1388       } else {
   1389         AssembleBinOp(i, masm(), instr, &MacroAssembler::sll,
   1390                       &MacroAssembler::sll);
   1391       }
   1392       break;
   1393 #if V8_TARGET_ARCH_S390X
   1394     case kS390_ShiftLeft64:
   1395       ASSEMBLE_BINOP(sllg);
   1396       break;
   1397 #endif
   1398     case kS390_ShiftRight32:
   1399       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1400         AssembleBinOp(i, masm(), instr, &MacroAssembler::srlk,
   1401                       &MacroAssembler::srlk);
   1402       } else {
   1403         AssembleBinOp(i, masm(), instr, &MacroAssembler::srl,
   1404                       &MacroAssembler::srl);
   1405       }
   1406       break;
   1407 #if V8_TARGET_ARCH_S390X
   1408     case kS390_ShiftRight64:
   1409       ASSEMBLE_BINOP(srlg);
   1410       break;
   1411 #endif
   1412     case kS390_ShiftRightArith32:
   1413       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1414         AssembleBinOp(i, masm(), instr, &MacroAssembler::srak,
   1415                       &MacroAssembler::srak);
   1416       } else {
   1417         AssembleBinOp(i, masm(), instr, &MacroAssembler::sra,
   1418                       &MacroAssembler::sra);
   1419       }
   1420       break;
   1421 #if V8_TARGET_ARCH_S390X
   1422     case kS390_ShiftRightArith64:
   1423       ASSEMBLE_BINOP(srag);
   1424       break;
   1425 #endif
   1426 #if !V8_TARGET_ARCH_S390X
   1427     case kS390_AddPair:
   1428       // i.InputRegister(0) ... left low word.
   1429       // i.InputRegister(1) ... left high word.
   1430       // i.InputRegister(2) ... right low word.
   1431       // i.InputRegister(3) ... right high word.
   1432       __ AddLogical32(i.OutputRegister(0), i.InputRegister(0),
   1433                       i.InputRegister(2));
   1434       __ AddLogicalWithCarry32(i.OutputRegister(1), i.InputRegister(1),
   1435                                i.InputRegister(3));
   1436       break;
   1437     case kS390_SubPair:
   1438       // i.InputRegister(0) ... left low word.
   1439       // i.InputRegister(1) ... left high word.
   1440       // i.InputRegister(2) ... right low word.
   1441       // i.InputRegister(3) ... right high word.
   1442       __ SubLogical32(i.OutputRegister(0), i.InputRegister(0),
   1443                       i.InputRegister(2));
   1444       __ SubLogicalWithBorrow32(i.OutputRegister(1), i.InputRegister(1),
   1445                                 i.InputRegister(3));
   1446       break;
   1447     case kS390_MulPair:
   1448       // i.InputRegister(0) ... left low word.
   1449       // i.InputRegister(1) ... left high word.
   1450       // i.InputRegister(2) ... right low word.
   1451       // i.InputRegister(3) ... right high word.
   1452       __ sllg(r0, i.InputRegister(1), Operand(32));
   1453       __ sllg(r1, i.InputRegister(3), Operand(32));
   1454       __ lr(r0, i.InputRegister(0));
   1455       __ lr(r1, i.InputRegister(2));
   1456       __ msgr(r1, r0);
   1457       __ lr(i.OutputRegister(0), r1);
   1458       __ srag(i.OutputRegister(1), r1, Operand(32));
   1459       break;
   1460     case kS390_ShiftLeftPair: {
   1461       Register second_output =
   1462           instr->OutputCount() >= 2 ? i.OutputRegister(1) : i.TempRegister(0);
   1463       if (instr->InputAt(2)->IsImmediate()) {
   1464         __ ShiftLeftPair(i.OutputRegister(0), second_output, i.InputRegister(0),
   1465                          i.InputRegister(1), i.InputInt32(2));
   1466       } else {
   1467         __ ShiftLeftPair(i.OutputRegister(0), second_output, i.InputRegister(0),
   1468                          i.InputRegister(1), kScratchReg, i.InputRegister(2));
   1469       }
   1470       break;
   1471     }
   1472     case kS390_ShiftRightPair: {
   1473       Register second_output =
   1474           instr->OutputCount() >= 2 ? i.OutputRegister(1) : i.TempRegister(0);
   1475       if (instr->InputAt(2)->IsImmediate()) {
   1476         __ ShiftRightPair(i.OutputRegister(0), second_output,
   1477                           i.InputRegister(0), i.InputRegister(1),
   1478                           i.InputInt32(2));
   1479       } else {
   1480         __ ShiftRightPair(i.OutputRegister(0), second_output,
   1481                           i.InputRegister(0), i.InputRegister(1), kScratchReg,
   1482                           i.InputRegister(2));
   1483       }
   1484       break;
   1485     }
   1486     case kS390_ShiftRightArithPair: {
   1487       Register second_output =
   1488           instr->OutputCount() >= 2 ? i.OutputRegister(1) : i.TempRegister(0);
   1489       if (instr->InputAt(2)->IsImmediate()) {
   1490         __ ShiftRightArithPair(i.OutputRegister(0), second_output,
   1491                                i.InputRegister(0), i.InputRegister(1),
   1492                                i.InputInt32(2));
   1493       } else {
   1494         __ ShiftRightArithPair(i.OutputRegister(0), second_output,
   1495                                i.InputRegister(0), i.InputRegister(1),
   1496                                kScratchReg, i.InputRegister(2));
   1497       }
   1498       break;
   1499     }
   1500 #endif
   1501     case kS390_RotRight32: {
   1502       if (HasRegisterInput(instr, 1)) {
   1503         __ LoadComplementRR(kScratchReg, i.InputRegister(1));
   1504         __ rll(i.OutputRegister(), i.InputRegister(0), kScratchReg);
   1505       } else {
   1506         __ rll(i.OutputRegister(), i.InputRegister(0),
   1507                Operand(32 - i.InputInt32(1)));
   1508       }
   1509       CHECK_AND_ZERO_EXT_OUTPUT(2);
   1510       break;
   1511     }
   1512 #if V8_TARGET_ARCH_S390X
   1513     case kS390_RotRight64:
   1514       if (HasRegisterInput(instr, 1)) {
   1515         __ LoadComplementRR(kScratchReg, i.InputRegister(1));
   1516         __ rllg(i.OutputRegister(), i.InputRegister(0), kScratchReg);
   1517       } else {
   1518         __ rllg(i.OutputRegister(), i.InputRegister(0),
   1519                 Operand(64 - i.InputInt32(1)));
   1520       }
   1521       break;
   1522     case kS390_RotLeftAndClear64:
   1523       if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
   1524         int shiftAmount = i.InputInt32(1);
   1525         int endBit = 63 - shiftAmount;
   1526         int startBit = 63 - i.InputInt32(2);
   1527         __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
   1528                  Operand(endBit), Operand(shiftAmount), true);
   1529       } else {
   1530         int shiftAmount = i.InputInt32(1);
   1531         int clearBit = 63 - i.InputInt32(2);
   1532         __ rllg(i.OutputRegister(), i.InputRegister(0), Operand(shiftAmount));
   1533         __ sllg(i.OutputRegister(), i.OutputRegister(), Operand(clearBit));
   1534         __ srlg(i.OutputRegister(), i.OutputRegister(),
   1535                 Operand(clearBit + shiftAmount));
   1536         __ sllg(i.OutputRegister(), i.OutputRegister(), Operand(shiftAmount));
   1537       }
   1538       break;
   1539     case kS390_RotLeftAndClearLeft64:
   1540       if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
   1541         int shiftAmount = i.InputInt32(1);
   1542         int endBit = 63;
   1543         int startBit = 63 - i.InputInt32(2);
   1544         __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
   1545                  Operand(endBit), Operand(shiftAmount), true);
   1546       } else {
   1547         int shiftAmount = i.InputInt32(1);
   1548         int clearBit = 63 - i.InputInt32(2);
   1549         __ rllg(i.OutputRegister(), i.InputRegister(0), Operand(shiftAmount));
   1550         __ sllg(i.OutputRegister(), i.OutputRegister(), Operand(clearBit));
   1551         __ srlg(i.OutputRegister(), i.OutputRegister(), Operand(clearBit));
   1552       }
   1553       break;
   1554     case kS390_RotLeftAndClearRight64:
   1555       if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
   1556         int shiftAmount = i.InputInt32(1);
   1557         int endBit = 63 - i.InputInt32(2);
   1558         int startBit = 0;
   1559         __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
   1560                  Operand(endBit), Operand(shiftAmount), true);
   1561       } else {
   1562         int shiftAmount = i.InputInt32(1);
   1563         int clearBit = i.InputInt32(2);
   1564         __ rllg(i.OutputRegister(), i.InputRegister(0), Operand(shiftAmount));
   1565         __ srlg(i.OutputRegister(), i.OutputRegister(), Operand(clearBit));
   1566         __ sllg(i.OutputRegister(), i.OutputRegister(), Operand(clearBit));
   1567       }
   1568       break;
   1569 #endif
   1570     case kS390_Add32: {
   1571       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1572         ASSEMBLE_BIN_OP(ark, Add32, Add32_RRI);
   1573       } else {
   1574         ASSEMBLE_BIN_OP(ar, Add32, Add32_RI);
   1575       }
   1576       break;
   1577     }
   1578     case kS390_Add64:
   1579       ASSEMBLE_BINOP(AddP);
   1580       break;
   1581     case kS390_AddFloat:
   1582       // Ensure we don't clobber right/InputReg(1)
   1583       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1584         ASSEMBLE_FLOAT_UNOP(aebr);
   1585       } else {
   1586         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
   1587           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1588         __ aebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1589       }
   1590       break;
   1591     case kS390_AddDouble:
   1592       // Ensure we don't clobber right/InputReg(1)
   1593       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1594         ASSEMBLE_FLOAT_UNOP(adbr);
   1595       } else {
   1596         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
   1597           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1598         __ adbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1599       }
   1600       break;
   1601     case kS390_Sub32:
   1602       if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
   1603         ASSEMBLE_BIN_OP(srk, Sub32, Sub32_RRI);
   1604       } else {
   1605         ASSEMBLE_BIN_OP(sr, Sub32, Sub32_RI);
   1606       }
   1607       break;
   1608     case kS390_Sub64:
   1609       ASSEMBLE_BINOP(SubP);
   1610       break;
   1611     case kS390_SubFloat:
   1612       // OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1)
   1613       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1614         __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
   1615         __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1616         __ sebr(i.OutputDoubleRegister(), kScratchDoubleReg);
   1617       } else {
   1618         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) {
   1619           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1620         }
   1621         __ sebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1622       }
   1623       break;
   1624     case kS390_SubDouble:
   1625       // OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1)
   1626       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1627         __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
   1628         __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1629         __ sdbr(i.OutputDoubleRegister(), kScratchDoubleReg);
   1630       } else {
   1631         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) {
   1632           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1633         }
   1634         __ sdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1635       }
   1636       break;
   1637     case kS390_Mul32:
   1638       ASSEMBLE_BIN_OP(Mul32, Mul32, Mul32);
   1639       break;
   1640     case kS390_Mul32WithOverflow:
   1641       ASSEMBLE_BIN_OP(Mul32WithOverflowIfCCUnequal,
   1642                       Mul32WithOverflowIfCCUnequal,
   1643                       Mul32WithOverflowIfCCUnequal);
   1644       break;
   1645     case kS390_Mul64:
   1646       CHECK(i.OutputRegister().is(i.InputRegister(0)));
   1647       if (HasRegisterInput(instr, 1)) {
   1648         __ Mul64(i.InputRegister(0), i.InputRegister(1));
   1649       } else if (HasImmediateInput(instr, 1)) {
   1650         __ Mul64(i.InputRegister(0), i.InputImmediate(1));
   1651       } else if (HasStackSlotInput(instr, 1)) {
   1652         __ Mul64(i.InputRegister(0), i.InputStackSlot(1));
   1653       } else {
   1654         UNIMPLEMENTED();
   1655       }
   1656       break;
   1657     case kS390_MulHigh32:
   1658       ASSEMBLE_BIN_OP(MulHigh32, MulHigh32, MulHigh32);
   1659       break;
   1660     case kS390_MulHighU32:
   1661       ASSEMBLE_BIN_OP(MulHighU32, MulHighU32, MulHighU32);
   1662       break;
   1663     case kS390_MulFloat:
   1664       // Ensure we don't clobber right
   1665       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1666         ASSEMBLE_FLOAT_UNOP(meebr);
   1667       } else {
   1668         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
   1669           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1670         __ meebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1671       }
   1672       break;
   1673     case kS390_MulDouble:
   1674       // Ensure we don't clobber right
   1675       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1676         ASSEMBLE_FLOAT_UNOP(mdbr);
   1677       } else {
   1678         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
   1679           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1680         __ mdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1681       }
   1682       break;
   1683 #if V8_TARGET_ARCH_S390X
   1684     case kS390_Div64:
   1685       __ LoadRR(r1, i.InputRegister(0));
   1686       __ dsgr(r0, i.InputRegister(1));  // R1: Dividend
   1687       __ ltgr(i.OutputRegister(), r1);  // Copy R1: Quotient to output
   1688       break;
   1689 #endif
   1690     case kS390_Div32: {
   1691       ASSEMBLE_BIN_OP(Div32, Div32, Div32);
   1692       break;
   1693     }
   1694 #if V8_TARGET_ARCH_S390X
   1695     case kS390_DivU64:
   1696       __ LoadRR(r1, i.InputRegister(0));
   1697       __ LoadImmP(r0, Operand::Zero());
   1698       __ dlgr(r0, i.InputRegister(1));  // R0:R1: Dividend
   1699       __ ltgr(i.OutputRegister(), r1);  // Copy R1: Quotient to output
   1700       break;
   1701 #endif
   1702     case kS390_DivU32: {
   1703       ASSEMBLE_BIN_OP(DivU32, DivU32, DivU32);
   1704       break;
   1705     }
   1706     case kS390_DivFloat:
   1707       // InputDoubleRegister(1)=InputDoubleRegister(0)/InputDoubleRegister(1)
   1708       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1709         __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
   1710         __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1711         __ debr(i.OutputDoubleRegister(), kScratchDoubleReg);
   1712       } else {
   1713         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
   1714           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1715         __ debr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1716       }
   1717       break;
   1718     case kS390_DivDouble:
   1719       // InputDoubleRegister(1)=InputDoubleRegister(0)/InputDoubleRegister(1)
   1720       if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
   1721         __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
   1722         __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1723         __ ddbr(i.OutputDoubleRegister(), kScratchDoubleReg);
   1724       } else {
   1725         if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
   1726           __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1727         __ ddbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
   1728       }
   1729       break;
   1730     case kS390_Mod32:
   1731       ASSEMBLE_BIN_OP(Mod32, Mod32, Mod32);
   1732       break;
   1733     case kS390_ModU32:
   1734       ASSEMBLE_BIN_OP(ModU32, ModU32, ModU32);
   1735       break;
   1736 #if V8_TARGET_ARCH_S390X
   1737     case kS390_Mod64:
   1738       __ LoadRR(r1, i.InputRegister(0));
   1739       __ dsgr(r0, i.InputRegister(1));  // R1: Dividend
   1740       __ ltgr(i.OutputRegister(), r0);  // Copy R0: Remainder to output
   1741       break;
   1742     case kS390_ModU64:
   1743       __ LoadRR(r1, i.InputRegister(0));
   1744       __ LoadImmP(r0, Operand::Zero());
   1745       __ dlgr(r0, i.InputRegister(1));  // R0:R1: Dividend
   1746       __ ltgr(i.OutputRegister(), r0);  // Copy R0: Remainder to output
   1747       break;
   1748 #endif
   1749     case kS390_AbsFloat:
   1750       __ lpebr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1751       break;
   1752     case kS390_SqrtFloat:
   1753       ASSEMBLE_FLOAT_UNOP(sqebr);
   1754       break;
   1755     case kS390_FloorFloat:
   1756       __ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1757                 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_NEG_INF);
   1758       break;
   1759     case kS390_CeilFloat:
   1760       __ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1761                 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_POS_INF);
   1762       break;
   1763     case kS390_TruncateFloat:
   1764       __ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1765                 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0);
   1766       break;
   1767     //  Double operations
   1768     case kS390_ModDouble:
   1769       ASSEMBLE_FLOAT_MODULO();
   1770       break;
   1771     case kIeee754Float64Acos:
   1772       ASSEMBLE_IEEE754_UNOP(acos);
   1773       break;
   1774     case kIeee754Float64Acosh:
   1775       ASSEMBLE_IEEE754_UNOP(acosh);
   1776       break;
   1777     case kIeee754Float64Asin:
   1778       ASSEMBLE_IEEE754_UNOP(asin);
   1779       break;
   1780     case kIeee754Float64Asinh:
   1781       ASSEMBLE_IEEE754_UNOP(asinh);
   1782       break;
   1783     case kIeee754Float64Atanh:
   1784       ASSEMBLE_IEEE754_UNOP(atanh);
   1785       break;
   1786     case kIeee754Float64Atan:
   1787       ASSEMBLE_IEEE754_UNOP(atan);
   1788       break;
   1789     case kIeee754Float64Atan2:
   1790       ASSEMBLE_IEEE754_BINOP(atan2);
   1791       break;
   1792     case kIeee754Float64Tan:
   1793       ASSEMBLE_IEEE754_UNOP(tan);
   1794       break;
   1795     case kIeee754Float64Tanh:
   1796       ASSEMBLE_IEEE754_UNOP(tanh);
   1797       break;
   1798     case kIeee754Float64Cbrt:
   1799       ASSEMBLE_IEEE754_UNOP(cbrt);
   1800       break;
   1801     case kIeee754Float64Sin:
   1802       ASSEMBLE_IEEE754_UNOP(sin);
   1803       break;
   1804     case kIeee754Float64Sinh:
   1805       ASSEMBLE_IEEE754_UNOP(sinh);
   1806       break;
   1807     case kIeee754Float64Cos:
   1808       ASSEMBLE_IEEE754_UNOP(cos);
   1809       break;
   1810     case kIeee754Float64Cosh:
   1811       ASSEMBLE_IEEE754_UNOP(cosh);
   1812       break;
   1813     case kIeee754Float64Exp:
   1814       ASSEMBLE_IEEE754_UNOP(exp);
   1815       break;
   1816     case kIeee754Float64Expm1:
   1817       ASSEMBLE_IEEE754_UNOP(expm1);
   1818       break;
   1819     case kIeee754Float64Log:
   1820       ASSEMBLE_IEEE754_UNOP(log);
   1821       break;
   1822     case kIeee754Float64Log1p:
   1823       ASSEMBLE_IEEE754_UNOP(log1p);
   1824       break;
   1825     case kIeee754Float64Log2:
   1826       ASSEMBLE_IEEE754_UNOP(log2);
   1827       break;
   1828     case kIeee754Float64Log10:
   1829       ASSEMBLE_IEEE754_UNOP(log10);
   1830       break;
   1831     case kIeee754Float64Pow: {
   1832       MathPowStub stub(isolate(), MathPowStub::DOUBLE);
   1833       __ CallStub(&stub);
   1834       __ Move(d1, d3);
   1835       break;
   1836     }
   1837     case kS390_Neg32:
   1838       __ lcr(i.OutputRegister(), i.InputRegister(0));
   1839       CHECK_AND_ZERO_EXT_OUTPUT(1);
   1840       break;
   1841     case kS390_Neg64:
   1842       __ lcgr(i.OutputRegister(), i.InputRegister(0));
   1843       break;
   1844     case kS390_MaxFloat:
   1845       ASSEMBLE_FLOAT_MAX();
   1846       break;
   1847     case kS390_MaxDouble:
   1848       ASSEMBLE_DOUBLE_MAX();
   1849       break;
   1850     case kS390_MinFloat:
   1851       ASSEMBLE_FLOAT_MIN();
   1852       break;
   1853     case kS390_MinDouble:
   1854       ASSEMBLE_DOUBLE_MIN();
   1855       break;
   1856     case kS390_AbsDouble:
   1857       __ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   1858       break;
   1859     case kS390_SqrtDouble:
   1860       ASSEMBLE_FLOAT_UNOP(sqdbr);
   1861       break;
   1862     case kS390_FloorDouble:
   1863       __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1864                 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_NEG_INF);
   1865       break;
   1866     case kS390_CeilDouble:
   1867       __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1868                 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_POS_INF);
   1869       break;
   1870     case kS390_TruncateDouble:
   1871       __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1872                 v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0);
   1873       break;
   1874     case kS390_RoundDouble:
   1875       __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
   1876                 v8::internal::Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0);
   1877       break;
   1878     case kS390_NegFloat:
   1879       ASSEMBLE_FLOAT_UNOP(lcebr);
   1880       break;
   1881     case kS390_NegDouble:
   1882       ASSEMBLE_FLOAT_UNOP(lcdbr);
   1883       break;
   1884     case kS390_Cntlz32: {
   1885       __ llgfr(i.OutputRegister(), i.InputRegister(0));
   1886       __ flogr(r0, i.OutputRegister());
   1887       __ Add32(i.OutputRegister(), r0, Operand(-32));
   1888       // No need to zero-ext b/c llgfr is done already
   1889       break;
   1890     }
   1891 #if V8_TARGET_ARCH_S390X
   1892     case kS390_Cntlz64: {
   1893       __ flogr(r0, i.InputRegister(0));
   1894       __ LoadRR(i.OutputRegister(), r0);
   1895       break;
   1896     }
   1897 #endif
   1898     case kS390_Popcnt32:
   1899       __ Popcnt32(i.OutputRegister(), i.InputRegister(0));
   1900       break;
   1901 #if V8_TARGET_ARCH_S390X
   1902     case kS390_Popcnt64:
   1903       __ Popcnt64(i.OutputRegister(), i.InputRegister(0));
   1904       break;
   1905 #endif
   1906     case kS390_Cmp32:
   1907       ASSEMBLE_COMPARE32(Cmp32, CmpLogical32);
   1908       break;
   1909 #if V8_TARGET_ARCH_S390X
   1910     case kS390_Cmp64:
   1911       ASSEMBLE_COMPARE(CmpP, CmpLogicalP);
   1912       break;
   1913 #endif
   1914     case kS390_CmpFloat:
   1915       ASSEMBLE_FLOAT_COMPARE(cebr, ceb, ley);
   1916       // __ cebr(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
   1917       break;
   1918     case kS390_CmpDouble:
   1919       ASSEMBLE_FLOAT_COMPARE(cdbr, cdb, ldy);
   1920       // __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
   1921       break;
   1922     case kS390_Tst32:
   1923       if (HasRegisterInput(instr, 1)) {
   1924         __ And(r0, i.InputRegister(0), i.InputRegister(1));
   1925       } else {
   1926         Operand opnd = i.InputImmediate(1);
   1927         if (is_uint16(opnd.immediate())) {
   1928           __ tmll(i.InputRegister(0), opnd);
   1929         } else {
   1930           __ lr(r0, i.InputRegister(0));
   1931           __ nilf(r0, opnd);
   1932         }
   1933       }
   1934       break;
   1935     case kS390_Tst64:
   1936       if (HasRegisterInput(instr, 1)) {
   1937         __ AndP(r0, i.InputRegister(0), i.InputRegister(1));
   1938       } else {
   1939         Operand opnd = i.InputImmediate(1);
   1940         if (is_uint16(opnd.immediate())) {
   1941           __ tmll(i.InputRegister(0), opnd);
   1942         } else {
   1943           __ AndP(r0, i.InputRegister(0), opnd);
   1944         }
   1945       }
   1946       break;
   1947     case kS390_Float64SilenceNaN: {
   1948       DoubleRegister value = i.InputDoubleRegister(0);
   1949       DoubleRegister result = i.OutputDoubleRegister();
   1950       __ CanonicalizeNaN(result, value);
   1951       break;
   1952     }
   1953     case kS390_Push:
   1954       if (instr->InputAt(0)->IsFPRegister()) {
   1955         __ lay(sp, MemOperand(sp, -kDoubleSize));
   1956         __ StoreDouble(i.InputDoubleRegister(0), MemOperand(sp));
   1957         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1958       } else {
   1959         __ Push(i.InputRegister(0));
   1960         frame_access_state()->IncreaseSPDelta(1);
   1961       }
   1962       break;
   1963     case kS390_PushFrame: {
   1964       int num_slots = i.InputInt32(1);
   1965       __ lay(sp, MemOperand(sp, -num_slots * kPointerSize));
   1966       if (instr->InputAt(0)->IsFPRegister()) {
   1967         LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
   1968         if (op->representation() == MachineRepresentation::kFloat64) {
   1969           __ StoreDouble(i.InputDoubleRegister(0), MemOperand(sp));
   1970         } else {
   1971           DCHECK(op->representation() == MachineRepresentation::kFloat32);
   1972           __ StoreFloat32(i.InputDoubleRegister(0), MemOperand(sp));
   1973         }
   1974       } else {
   1975         __ StoreP(i.InputRegister(0),
   1976                   MemOperand(sp));
   1977       }
   1978       break;
   1979     }
   1980     case kS390_StoreToStackSlot: {
   1981       int slot = i.InputInt32(1);
   1982       if (instr->InputAt(0)->IsFPRegister()) {
   1983         LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
   1984         if (op->representation() == MachineRepresentation::kFloat64) {
   1985           __ StoreDouble(i.InputDoubleRegister(0),
   1986                          MemOperand(sp, slot * kPointerSize));
   1987         } else {
   1988           DCHECK(op->representation() == MachineRepresentation::kFloat32);
   1989           __ StoreFloat32(i.InputDoubleRegister(0),
   1990                           MemOperand(sp, slot * kPointerSize));
   1991         }
   1992       } else {
   1993         __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
   1994       }
   1995       break;
   1996     }
   1997     case kS390_ExtendSignWord8:
   1998       __ lbr(i.OutputRegister(), i.InputRegister(0));
   1999       CHECK_AND_ZERO_EXT_OUTPUT(1);
   2000       break;
   2001     case kS390_ExtendSignWord16:
   2002       __ lhr(i.OutputRegister(), i.InputRegister(0));
   2003       CHECK_AND_ZERO_EXT_OUTPUT(1);
   2004       break;
   2005 #if V8_TARGET_ARCH_S390X
   2006     case kS390_ExtendSignWord32:
   2007       __ lgfr(i.OutputRegister(), i.InputRegister(0));
   2008       break;
   2009     case kS390_Uint32ToUint64:
   2010       // Zero extend
   2011       __ llgfr(i.OutputRegister(), i.InputRegister(0));
   2012       break;
   2013     case kS390_Int64ToInt32:
   2014       // sign extend
   2015       __ lgfr(i.OutputRegister(), i.InputRegister(0));
   2016       break;
   2017     case kS390_Int64ToFloat32:
   2018       __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister());
   2019       break;
   2020     case kS390_Int64ToDouble:
   2021       __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister());
   2022       break;
   2023     case kS390_Uint64ToFloat32:
   2024       __ ConvertUnsignedInt64ToFloat(i.InputRegister(0),
   2025                                      i.OutputDoubleRegister());
   2026       break;
   2027     case kS390_Uint64ToDouble:
   2028       __ ConvertUnsignedInt64ToDouble(i.InputRegister(0),
   2029                                       i.OutputDoubleRegister());
   2030       break;
   2031 #endif
   2032     case kS390_Int32ToFloat32:
   2033       __ ConvertIntToFloat(i.InputRegister(0), i.OutputDoubleRegister());
   2034       break;
   2035     case kS390_Int32ToDouble:
   2036       __ ConvertIntToDouble(i.InputRegister(0), i.OutputDoubleRegister());
   2037       break;
   2038     case kS390_Uint32ToFloat32:
   2039       __ ConvertUnsignedIntToFloat(i.InputRegister(0),
   2040                                    i.OutputDoubleRegister());
   2041       break;
   2042     case kS390_Uint32ToDouble:
   2043       __ ConvertUnsignedIntToDouble(i.InputRegister(0),
   2044                                     i.OutputDoubleRegister());
   2045       break;
   2046     case kS390_DoubleToInt32:
   2047     case kS390_DoubleToUint32:
   2048     case kS390_DoubleToInt64: {
   2049 #if V8_TARGET_ARCH_S390X
   2050       bool check_conversion =
   2051           (opcode == kS390_DoubleToInt64 && i.OutputCount() > 1);
   2052 #endif
   2053       __ ConvertDoubleToInt64(i.InputDoubleRegister(0),
   2054 #if !V8_TARGET_ARCH_S390X
   2055                               kScratchReg,
   2056 #endif
   2057                               i.OutputRegister(0), kScratchDoubleReg);
   2058 #if V8_TARGET_ARCH_S390X
   2059       if (check_conversion) {
   2060         Label conversion_done;
   2061         __ LoadImmP(i.OutputRegister(1), Operand::Zero());
   2062         __ b(Condition(1), &conversion_done);  // special case
   2063         __ LoadImmP(i.OutputRegister(1), Operand(1));
   2064         __ bind(&conversion_done);
   2065       }
   2066 #endif
   2067       break;
   2068     }
   2069     case kS390_Float32ToInt32: {
   2070       bool check_conversion = (i.OutputCount() > 1);
   2071       __ ConvertFloat32ToInt32(i.InputDoubleRegister(0), i.OutputRegister(0),
   2072                                kScratchDoubleReg, kRoundToZero);
   2073       if (check_conversion) {
   2074         Label conversion_done;
   2075         __ LoadImmP(i.OutputRegister(1), Operand::Zero());
   2076         __ b(Condition(1), &conversion_done);  // special case
   2077         __ LoadImmP(i.OutputRegister(1), Operand(1));
   2078         __ bind(&conversion_done);
   2079       }
   2080       break;
   2081     }
   2082     case kS390_Float32ToUint32: {
   2083       bool check_conversion = (i.OutputCount() > 1);
   2084       __ ConvertFloat32ToUnsignedInt32(i.InputDoubleRegister(0),
   2085                                        i.OutputRegister(0), kScratchDoubleReg);
   2086       if (check_conversion) {
   2087         Label conversion_done;
   2088         __ LoadImmP(i.OutputRegister(1), Operand::Zero());
   2089         __ b(Condition(1), &conversion_done);  // special case
   2090         __ LoadImmP(i.OutputRegister(1), Operand(1));
   2091         __ bind(&conversion_done);
   2092       }
   2093       break;
   2094     }
   2095 #if V8_TARGET_ARCH_S390X
   2096     case kS390_Float32ToUint64: {
   2097       bool check_conversion = (i.OutputCount() > 1);
   2098       __ ConvertFloat32ToUnsignedInt64(i.InputDoubleRegister(0),
   2099                                        i.OutputRegister(0), kScratchDoubleReg);
   2100       if (check_conversion) {
   2101         Label conversion_done;
   2102         __ LoadImmP(i.OutputRegister(1), Operand::Zero());
   2103         __ b(Condition(1), &conversion_done);  // special case
   2104         __ LoadImmP(i.OutputRegister(1), Operand(1));
   2105         __ bind(&conversion_done);
   2106       }
   2107       break;
   2108     }
   2109 #endif
   2110     case kS390_Float32ToInt64: {
   2111 #if V8_TARGET_ARCH_S390X
   2112       bool check_conversion =
   2113           (opcode == kS390_Float32ToInt64 && i.OutputCount() > 1);
   2114 #endif
   2115       __ ConvertFloat32ToInt64(i.InputDoubleRegister(0),
   2116 #if !V8_TARGET_ARCH_S390X
   2117                                kScratchReg,
   2118 #endif
   2119                                i.OutputRegister(0), kScratchDoubleReg);
   2120 #if V8_TARGET_ARCH_S390X
   2121       if (check_conversion) {
   2122         Label conversion_done;
   2123         __ LoadImmP(i.OutputRegister(1), Operand::Zero());
   2124         __ b(Condition(1), &conversion_done);  // special case
   2125         __ LoadImmP(i.OutputRegister(1), Operand(1));
   2126         __ bind(&conversion_done);
   2127       }
   2128 #endif
   2129       break;
   2130     }
   2131 #if V8_TARGET_ARCH_S390X
   2132     case kS390_DoubleToUint64: {
   2133       bool check_conversion = (i.OutputCount() > 1);
   2134       __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0),
   2135                                       i.OutputRegister(0), kScratchDoubleReg);
   2136       if (check_conversion) {
   2137         Label conversion_done;
   2138         __ LoadImmP(i.OutputRegister(1), Operand::Zero());
   2139         __ b(Condition(1), &conversion_done);  // special case
   2140         __ LoadImmP(i.OutputRegister(1), Operand(1));
   2141         __ bind(&conversion_done);
   2142       }
   2143       break;
   2144     }
   2145 #endif
   2146     case kS390_DoubleToFloat32:
   2147       __ ledbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   2148       break;
   2149     case kS390_Float32ToDouble:
   2150       __ ldebr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
   2151       break;
   2152     case kS390_DoubleExtractLowWord32:
   2153       __ lgdr(i.OutputRegister(), i.InputDoubleRegister(0));
   2154       __ llgfr(i.OutputRegister(), i.OutputRegister());
   2155       break;
   2156     case kS390_DoubleExtractHighWord32:
   2157       __ lgdr(i.OutputRegister(), i.InputDoubleRegister(0));
   2158       __ srlg(i.OutputRegister(), i.OutputRegister(), Operand(32));
   2159       break;
   2160     case kS390_DoubleInsertLowWord32:
   2161       __ lgdr(kScratchReg, i.OutputDoubleRegister());
   2162       __ lr(kScratchReg, i.InputRegister(1));
   2163       __ ldgr(i.OutputDoubleRegister(), kScratchReg);
   2164       break;
   2165     case kS390_DoubleInsertHighWord32:
   2166       __ sllg(kScratchReg, i.InputRegister(1), Operand(32));
   2167       __ lgdr(r0, i.OutputDoubleRegister());
   2168       __ lr(kScratchReg, r0);
   2169       __ ldgr(i.OutputDoubleRegister(), kScratchReg);
   2170       break;
   2171     case kS390_DoubleConstruct:
   2172       __ sllg(kScratchReg, i.InputRegister(0), Operand(32));
   2173       __ lr(kScratchReg, i.InputRegister(1));
   2174 
   2175       // Bitwise convert from GPR to FPR
   2176       __ ldgr(i.OutputDoubleRegister(), kScratchReg);
   2177       break;
   2178     case kS390_LoadWordS8:
   2179       ASSEMBLE_LOAD_INTEGER(LoadlB);
   2180 #if V8_TARGET_ARCH_S390X
   2181       __ lgbr(i.OutputRegister(), i.OutputRegister());
   2182 #else
   2183       __ lbr(i.OutputRegister(), i.OutputRegister());
   2184 #endif
   2185       break;
   2186     case kS390_BitcastFloat32ToInt32:
   2187       __ MovFloatToInt(i.OutputRegister(), i.InputDoubleRegister(0));
   2188       break;
   2189     case kS390_BitcastInt32ToFloat32:
   2190       __ MovIntToFloat(i.OutputDoubleRegister(), i.InputRegister(0));
   2191       break;
   2192 #if V8_TARGET_ARCH_S390X
   2193     case kS390_BitcastDoubleToInt64:
   2194       __ MovDoubleToInt64(i.OutputRegister(), i.InputDoubleRegister(0));
   2195       break;
   2196     case kS390_BitcastInt64ToDouble:
   2197       __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0));
   2198       break;
   2199 #endif
   2200     case kS390_LoadWordU8:
   2201       ASSEMBLE_LOAD_INTEGER(LoadlB);
   2202       break;
   2203     case kS390_LoadWordU16:
   2204       ASSEMBLE_LOAD_INTEGER(LoadLogicalHalfWordP);
   2205       break;
   2206     case kS390_LoadWordS16:
   2207       ASSEMBLE_LOAD_INTEGER(LoadHalfWordP);
   2208       break;
   2209     case kS390_LoadWordU32:
   2210       ASSEMBLE_LOAD_INTEGER(LoadlW);
   2211       break;
   2212     case kS390_LoadWordS32:
   2213       ASSEMBLE_LOAD_INTEGER(LoadW);
   2214       break;
   2215     case kS390_LoadReverse16:
   2216       ASSEMBLE_LOAD_INTEGER(lrvh);
   2217       break;
   2218     case kS390_LoadReverse32:
   2219       ASSEMBLE_LOAD_INTEGER(lrv);
   2220       break;
   2221     case kS390_LoadReverse64:
   2222       ASSEMBLE_LOAD_INTEGER(lrvg);
   2223       break;
   2224     case kS390_LoadReverse16RR:
   2225       __ lrvr(i.OutputRegister(), i.InputRegister(0));
   2226       __ rll(i.OutputRegister(), i.OutputRegister(), Operand(16));
   2227       break;
   2228     case kS390_LoadReverse32RR:
   2229       __ lrvr(i.OutputRegister(), i.InputRegister(0));
   2230       break;
   2231     case kS390_LoadReverse64RR:
   2232       __ lrvgr(i.OutputRegister(), i.InputRegister(0));
   2233       break;
   2234 #if V8_TARGET_ARCH_S390X
   2235     case kS390_LoadWord64:
   2236       ASSEMBLE_LOAD_INTEGER(lg);
   2237       break;
   2238 #endif
   2239     case kS390_LoadAndTestWord32: {
   2240       ASSEMBLE_LOADANDTEST32(ltr, lt_z);
   2241       break;
   2242     }
   2243     case kS390_LoadAndTestWord64: {
   2244       ASSEMBLE_LOADANDTEST64(ltgr, ltg);
   2245       break;
   2246     }
   2247     case kS390_LoadFloat32:
   2248       ASSEMBLE_LOAD_FLOAT(LoadFloat32);
   2249       break;
   2250     case kS390_LoadDouble:
   2251       ASSEMBLE_LOAD_FLOAT(LoadDouble);
   2252       break;
   2253     case kS390_StoreWord8:
   2254       ASSEMBLE_STORE_INTEGER(StoreByte);
   2255       break;
   2256     case kS390_StoreWord16:
   2257       ASSEMBLE_STORE_INTEGER(StoreHalfWord);
   2258       break;
   2259     case kS390_StoreWord32:
   2260       ASSEMBLE_STORE_INTEGER(StoreW);
   2261       break;
   2262 #if V8_TARGET_ARCH_S390X
   2263     case kS390_StoreWord64:
   2264       ASSEMBLE_STORE_INTEGER(StoreP);
   2265       break;
   2266 #endif
   2267     case kS390_StoreReverse16:
   2268       ASSEMBLE_STORE_INTEGER(strvh);
   2269       break;
   2270     case kS390_StoreReverse32:
   2271       ASSEMBLE_STORE_INTEGER(strv);
   2272       break;
   2273     case kS390_StoreReverse64:
   2274       ASSEMBLE_STORE_INTEGER(strvg);
   2275       break;
   2276     case kS390_StoreFloat32:
   2277       ASSEMBLE_STORE_FLOAT32();
   2278       break;
   2279     case kS390_StoreDouble:
   2280       ASSEMBLE_STORE_DOUBLE();
   2281       break;
   2282     case kS390_Lay:
   2283       __ lay(i.OutputRegister(), i.MemoryOperand());
   2284       break;
   2285     case kCheckedLoadInt8:
   2286       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlB);
   2287 #if V8_TARGET_ARCH_S390X
   2288       __ lgbr(i.OutputRegister(), i.OutputRegister());
   2289 #else
   2290       __ lbr(i.OutputRegister(), i.OutputRegister());
   2291 #endif
   2292       break;
   2293     case kCheckedLoadUint8:
   2294       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlB);
   2295       break;
   2296     case kCheckedLoadInt16:
   2297       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadHalfWordP);
   2298       break;
   2299     case kCheckedLoadUint16:
   2300       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadLogicalHalfWordP);
   2301       break;
   2302     case kCheckedLoadWord32:
   2303       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlW);
   2304       break;
   2305     case kCheckedLoadWord64:
   2306 #if V8_TARGET_ARCH_S390X
   2307       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadP);
   2308 #else
   2309       UNREACHABLE();
   2310 #endif
   2311       break;
   2312     case kCheckedLoadFloat32:
   2313       ASSEMBLE_CHECKED_LOAD_FLOAT(LoadFloat32, 32);
   2314       break;
   2315     case kCheckedLoadFloat64:
   2316       ASSEMBLE_CHECKED_LOAD_FLOAT(LoadDouble, 64);
   2317       break;
   2318     case kCheckedStoreWord8:
   2319       ASSEMBLE_CHECKED_STORE_INTEGER(StoreByte);
   2320       break;
   2321     case kCheckedStoreWord16:
   2322       ASSEMBLE_CHECKED_STORE_INTEGER(StoreHalfWord);
   2323       break;
   2324     case kCheckedStoreWord32:
   2325       ASSEMBLE_CHECKED_STORE_INTEGER(StoreW);
   2326       break;
   2327     case kCheckedStoreWord64:
   2328 #if V8_TARGET_ARCH_S390X
   2329       ASSEMBLE_CHECKED_STORE_INTEGER(StoreP);
   2330 #else
   2331       UNREACHABLE();
   2332 #endif
   2333       break;
   2334     case kCheckedStoreFloat32:
   2335       ASSEMBLE_CHECKED_STORE_FLOAT32();
   2336       break;
   2337     case kCheckedStoreFloat64:
   2338       ASSEMBLE_CHECKED_STORE_DOUBLE();
   2339       break;
   2340     case kAtomicLoadInt8:
   2341       __ LoadB(i.OutputRegister(), i.MemoryOperand());
   2342       break;
   2343     case kAtomicLoadUint8:
   2344       __ LoadlB(i.OutputRegister(), i.MemoryOperand());
   2345       break;
   2346     case kAtomicLoadInt16:
   2347       __ LoadHalfWordP(i.OutputRegister(), i.MemoryOperand());
   2348       break;
   2349     case kAtomicLoadUint16:
   2350       __ LoadLogicalHalfWordP(i.OutputRegister(), i.MemoryOperand());
   2351       break;
   2352     case kAtomicLoadWord32:
   2353       __ LoadlW(i.OutputRegister(), i.MemoryOperand());
   2354       break;
   2355     case kAtomicStoreWord8:
   2356       __ StoreByte(i.InputRegister(0), i.MemoryOperand(NULL, 1));
   2357       break;
   2358     case kAtomicStoreWord16:
   2359       __ StoreHalfWord(i.InputRegister(0), i.MemoryOperand(NULL, 1));
   2360       break;
   2361     case kAtomicStoreWord32:
   2362       __ StoreW(i.InputRegister(0), i.MemoryOperand(NULL, 1));
   2363       break;
   2364     default:
   2365       UNREACHABLE();
   2366       break;
   2367   }
   2368   return kSuccess;
   2369 }  // NOLINT(readability/fn_size)
   2370 
   2371 // Assembles branches after an instruction.
   2372 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
   2373   S390OperandConverter i(this, instr);
   2374   Label* tlabel = branch->true_label;
   2375   Label* flabel = branch->false_label;
   2376   ArchOpcode op = instr->arch_opcode();
   2377   FlagsCondition condition = branch->condition;
   2378 
   2379   Condition cond = FlagsConditionToCondition(condition, op);
   2380   if (op == kS390_CmpDouble) {
   2381     // check for unordered if necessary
   2382     // Branching to flabel/tlabel according to what's expected by tests
   2383     if (cond == le || cond == eq || cond == lt) {
   2384       __ bunordered(flabel);
   2385     } else if (cond == gt || cond == ne || cond == ge) {
   2386       __ bunordered(tlabel);
   2387     }
   2388   }
   2389   __ b(cond, tlabel);
   2390   if (!branch->fallthru) __ b(flabel);  // no fallthru to flabel.
   2391 }
   2392 
   2393 void CodeGenerator::AssembleArchJump(RpoNumber target) {
   2394   if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target));
   2395 }
   2396 
   2397 void CodeGenerator::AssembleArchTrap(Instruction* instr,
   2398                                      FlagsCondition condition) {
   2399   class OutOfLineTrap final : public OutOfLineCode {
   2400    public:
   2401     OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr)
   2402         : OutOfLineCode(gen),
   2403           frame_elided_(frame_elided),
   2404           instr_(instr),
   2405           gen_(gen) {}
   2406 
   2407     void Generate() final {
   2408       S390OperandConverter i(gen_, instr_);
   2409 
   2410       Builtins::Name trap_id =
   2411           static_cast<Builtins::Name>(i.InputInt32(instr_->InputCount() - 1));
   2412       bool old_has_frame = __ has_frame();
   2413       if (frame_elided_) {
   2414         __ set_has_frame(true);
   2415         __ EnterFrame(StackFrame::WASM_COMPILED);
   2416       }
   2417       GenerateCallToTrap(trap_id);
   2418       if (frame_elided_) {
   2419         __ set_has_frame(old_has_frame);
   2420       }
   2421     }
   2422 
   2423    private:
   2424     void GenerateCallToTrap(Builtins::Name trap_id) {
   2425       if (trap_id == Builtins::builtin_count) {
   2426         // We cannot test calls to the runtime in cctest/test-run-wasm.
   2427         // Therefore we emit a call to C here instead of a call to the runtime.
   2428         // We use the context register as the scratch register, because we do
   2429         // not have a context here.
   2430         __ PrepareCallCFunction(0, 0, cp);
   2431         __ CallCFunction(
   2432             ExternalReference::wasm_call_trap_callback_for_testing(isolate()),
   2433             0);
   2434         __ LeaveFrame(StackFrame::WASM_COMPILED);
   2435         __ Ret();
   2436       } else {
   2437         gen_->AssembleSourcePosition(instr_);
   2438         __ Call(handle(isolate()->builtins()->builtin(trap_id), isolate()),
   2439                 RelocInfo::CODE_TARGET);
   2440         ReferenceMap* reference_map =
   2441             new (gen_->zone()) ReferenceMap(gen_->zone());
   2442         gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
   2443                               Safepoint::kNoLazyDeopt);
   2444         if (FLAG_debug_code) {
   2445           __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap));
   2446         }
   2447       }
   2448     }
   2449 
   2450     bool frame_elided_;
   2451     Instruction* instr_;
   2452     CodeGenerator* gen_;
   2453   };
   2454   bool frame_elided = !frame_access_state()->has_frame();
   2455   auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr);
   2456   Label* tlabel = ool->entry();
   2457   Label end;
   2458 
   2459   ArchOpcode op = instr->arch_opcode();
   2460   Condition cond = FlagsConditionToCondition(condition, op);
   2461   if (op == kS390_CmpDouble) {
   2462     // check for unordered if necessary
   2463     if (cond == le) {
   2464       __ bunordered(&end);
   2465       // Unnecessary for eq/lt since only FU bit will be set.
   2466     } else if (cond == gt) {
   2467       __ bunordered(tlabel);
   2468       // Unnecessary for ne/ge since only FU bit will be set.
   2469     }
   2470   }
   2471   __ b(cond, tlabel);
   2472   __ bind(&end);
   2473 }
   2474 
   2475 // Assembles boolean materializations after an instruction.
   2476 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
   2477                                         FlagsCondition condition) {
   2478   S390OperandConverter i(this, instr);
   2479   ArchOpcode op = instr->arch_opcode();
   2480   bool check_unordered = (op == kS390_CmpDouble || op == kS390_CmpFloat);
   2481 
   2482   // Overflow checked for add/sub only.
   2483   DCHECK((condition != kOverflow && condition != kNotOverflow) ||
   2484          (op == kS390_Add32 || kS390_Add64 || op == kS390_Sub32 ||
   2485           op == kS390_Sub64));
   2486 
   2487   // Materialize a full 32-bit 1 or 0 value. The result register is always the
   2488   // last output of the instruction.
   2489   DCHECK_NE(0u, instr->OutputCount());
   2490   Register reg = i.OutputRegister(instr->OutputCount() - 1);
   2491   Condition cond = FlagsConditionToCondition(condition, op);
   2492   Label done;
   2493   if (check_unordered) {
   2494     __ LoadImmP(reg, (cond == eq || cond == le || cond == lt) ? Operand::Zero()
   2495                                                               : Operand(1));
   2496     __ bunordered(&done);
   2497   }
   2498   __ LoadImmP(reg, Operand::Zero());
   2499   __ LoadImmP(kScratchReg, Operand(1));
   2500   // locr is sufficient since reg's upper 32 is guarrantee to be 0
   2501   __ locr(cond, reg, kScratchReg);
   2502   __ bind(&done);
   2503 }
   2504 
   2505 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
   2506   S390OperandConverter i(this, instr);
   2507   Register input = i.InputRegister(0);
   2508   for (size_t index = 2; index < instr->InputCount(); index += 2) {
   2509     __ Cmp32(input, Operand(i.InputInt32(index + 0)));
   2510     __ beq(GetLabel(i.InputRpo(index + 1)));
   2511   }
   2512   AssembleArchJump(i.InputRpo(1));
   2513 }
   2514 
   2515 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
   2516   S390OperandConverter i(this, instr);
   2517   Register input = i.InputRegister(0);
   2518   int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2);
   2519   Label** cases = zone()->NewArray<Label*>(case_count);
   2520   for (int32_t index = 0; index < case_count; ++index) {
   2521     cases[index] = GetLabel(i.InputRpo(index + 2));
   2522   }
   2523   Label* const table = AddJumpTable(cases, case_count);
   2524   __ CmpLogicalP(input, Operand(case_count));
   2525   __ bge(GetLabel(i.InputRpo(1)));
   2526   __ larl(kScratchReg, table);
   2527   __ ShiftLeftP(r1, input, Operand(kPointerSizeLog2));
   2528   __ LoadP(kScratchReg, MemOperand(kScratchReg, r1));
   2529   __ Jump(kScratchReg);
   2530 }
   2531 
   2532 CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
   2533     int deoptimization_id, SourcePosition pos) {
   2534   DeoptimizeKind deoptimization_kind = GetDeoptimizationKind(deoptimization_id);
   2535   DeoptimizeReason deoptimization_reason =
   2536       GetDeoptimizationReason(deoptimization_id);
   2537   Deoptimizer::BailoutType bailout_type =
   2538       deoptimization_kind == DeoptimizeKind::kSoft ? Deoptimizer::SOFT
   2539                                                    : Deoptimizer::EAGER;
   2540   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
   2541       isolate(), deoptimization_id, bailout_type);
   2542   // TODO(turbofan): We should be able to generate better code by sharing the
   2543   // actual final call site and just bl'ing to it here, similar to what we do
   2544   // in the lithium backend.
   2545   if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   2546   __ RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
   2547   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
   2548   return kSuccess;
   2549 }
   2550 
   2551 void CodeGenerator::FinishFrame(Frame* frame) {
   2552   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   2553   const RegList double_saves = descriptor->CalleeSavedFPRegisters();
   2554 
   2555   // Save callee-saved Double registers.
   2556   if (double_saves != 0) {
   2557     frame->AlignSavedCalleeRegisterSlots();
   2558     DCHECK(kNumCalleeSavedDoubles ==
   2559            base::bits::CountPopulation32(double_saves));
   2560     frame->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
   2561                                             (kDoubleSize / kPointerSize));
   2562   }
   2563   // Save callee-saved registers.
   2564   const RegList saves = descriptor->CalleeSavedRegisters();
   2565   if (saves != 0) {
   2566     // register save area does not include the fp or constant pool pointer.
   2567     const int num_saves = kNumCalleeSaved - 1;
   2568     DCHECK(num_saves == base::bits::CountPopulation32(saves));
   2569     frame->AllocateSavedCalleeRegisterSlots(num_saves);
   2570   }
   2571 }
   2572 
   2573 void CodeGenerator::AssembleConstructFrame() {
   2574   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   2575 
   2576   if (frame_access_state()->has_frame()) {
   2577     if (descriptor->IsCFunctionCall()) {
   2578       __ Push(r14, fp);
   2579       __ LoadRR(fp, sp);
   2580     } else if (descriptor->IsJSFunctionCall()) {
   2581       __ Prologue(this->info()->GeneratePreagedPrologue(), ip);
   2582       if (descriptor->PushArgumentCount()) {
   2583         __ Push(kJavaScriptCallArgCountRegister);
   2584       }
   2585     } else {
   2586       StackFrame::Type type = info()->GetOutputStackFrameType();
   2587       // TODO(mbrandy): Detect cases where ip is the entrypoint (for
   2588       // efficient intialization of the constant pool pointer register).
   2589       __ StubPrologue(type);
   2590     }
   2591   }
   2592 
   2593   int shrink_slots =
   2594       frame()->GetTotalFrameSlotCount() - descriptor->CalculateFixedFrameSize();
   2595   if (info()->is_osr()) {
   2596     // TurboFan OSR-compiled functions cannot be entered directly.
   2597     __ Abort(kShouldNotDirectlyEnterOsrFunction);
   2598 
   2599     // Unoptimized code jumps directly to this entrypoint while the unoptimized
   2600     // frame is still on the stack. Optimized code uses OSR values directly from
   2601     // the unoptimized frame. Thus, all that needs to be done is to allocate the
   2602     // remaining stack slots.
   2603     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
   2604     osr_pc_offset_ = __ pc_offset();
   2605     shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   2606   }
   2607 
   2608   const RegList double_saves = descriptor->CalleeSavedFPRegisters();
   2609   if (shrink_slots > 0) {
   2610     __ lay(sp, MemOperand(sp, -shrink_slots * kPointerSize));
   2611   }
   2612 
   2613   // Save callee-saved Double registers.
   2614   if (double_saves != 0) {
   2615     __ MultiPushDoubles(double_saves);
   2616     DCHECK(kNumCalleeSavedDoubles ==
   2617            base::bits::CountPopulation32(double_saves));
   2618   }
   2619 
   2620   // Save callee-saved registers.
   2621   const RegList saves = descriptor->CalleeSavedRegisters();
   2622   if (saves != 0) {
   2623     __ MultiPush(saves);
   2624     // register save area does not include the fp or constant pool pointer.
   2625   }
   2626 }
   2627 
   2628 void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
   2629   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   2630   int pop_count = static_cast<int>(descriptor->StackParameterCount());
   2631 
   2632   // Restore registers.
   2633   const RegList saves = descriptor->CalleeSavedRegisters();
   2634   if (saves != 0) {
   2635     __ MultiPop(saves);
   2636   }
   2637 
   2638   // Restore double registers.
   2639   const RegList double_saves = descriptor->CalleeSavedFPRegisters();
   2640   if (double_saves != 0) {
   2641     __ MultiPopDoubles(double_saves);
   2642   }
   2643 
   2644   S390OperandConverter g(this, nullptr);
   2645   if (descriptor->IsCFunctionCall()) {
   2646     AssembleDeconstructFrame();
   2647   } else if (frame_access_state()->has_frame()) {
   2648     // Canonicalize JSFunction return sites for now unless they have an variable
   2649     // number of stack slot pops
   2650     if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) {
   2651       if (return_label_.is_bound()) {
   2652         __ b(&return_label_);
   2653         return;
   2654       } else {
   2655         __ bind(&return_label_);
   2656         AssembleDeconstructFrame();
   2657       }
   2658     } else {
   2659       AssembleDeconstructFrame();
   2660     }
   2661   }
   2662   if (pop->IsImmediate()) {
   2663     DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type());
   2664     pop_count += g.ToConstant(pop).ToInt32();
   2665   } else {
   2666     __ Drop(g.ToRegister(pop));
   2667   }
   2668   __ Drop(pop_count);
   2669   __ Ret();
   2670 }
   2671 
   2672 void CodeGenerator::AssembleMove(InstructionOperand* source,
   2673                                  InstructionOperand* destination) {
   2674   S390OperandConverter g(this, nullptr);
   2675   // Dispatch on the source and destination operand kinds.  Not all
   2676   // combinations are possible.
   2677   if (source->IsRegister()) {
   2678     DCHECK(destination->IsRegister() || destination->IsStackSlot());
   2679     Register src = g.ToRegister(source);
   2680     if (destination->IsRegister()) {
   2681       __ Move(g.ToRegister(destination), src);
   2682     } else {
   2683       __ StoreP(src, g.ToMemOperand(destination));
   2684     }
   2685   } else if (source->IsStackSlot()) {
   2686     DCHECK(destination->IsRegister() || destination->IsStackSlot());
   2687     MemOperand src = g.ToMemOperand(source);
   2688     if (destination->IsRegister()) {
   2689       __ LoadP(g.ToRegister(destination), src);
   2690     } else {
   2691       Register temp = kScratchReg;
   2692       __ LoadP(temp, src, r0);
   2693       __ StoreP(temp, g.ToMemOperand(destination));
   2694     }
   2695   } else if (source->IsConstant()) {
   2696     Constant src = g.ToConstant(source);
   2697     if (destination->IsRegister() || destination->IsStackSlot()) {
   2698       Register dst =
   2699           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
   2700       switch (src.type()) {
   2701         case Constant::kInt32:
   2702 #if V8_TARGET_ARCH_S390X
   2703           if (RelocInfo::IsWasmSizeReference(src.rmode())) {
   2704 #else
   2705           if (RelocInfo::IsWasmReference(src.rmode())) {
   2706 #endif
   2707             __ mov(dst, Operand(src.ToInt32(), src.rmode()));
   2708           } else {
   2709             __ Load(dst, Operand(src.ToInt32()));
   2710           }
   2711           break;
   2712         case Constant::kInt64:
   2713 #if V8_TARGET_ARCH_S390X
   2714           if (RelocInfo::IsWasmPtrReference(src.rmode())) {
   2715             __ mov(dst, Operand(src.ToInt64(), src.rmode()));
   2716           } else {
   2717             DCHECK(!RelocInfo::IsWasmSizeReference(src.rmode()));
   2718             __ Load(dst, Operand(src.ToInt64()));
   2719           }
   2720 #else
   2721           __ mov(dst, Operand(src.ToInt64()));
   2722 #endif  // V8_TARGET_ARCH_S390X
   2723           break;
   2724         case Constant::kFloat32:
   2725           __ Move(dst,
   2726                   isolate()->factory()->NewNumber(src.ToFloat32(), TENURED));
   2727           break;
   2728         case Constant::kFloat64:
   2729           __ Move(dst,
   2730                   isolate()->factory()->NewNumber(src.ToFloat64(), TENURED));
   2731           break;
   2732         case Constant::kExternalReference:
   2733           __ mov(dst, Operand(src.ToExternalReference()));
   2734           break;
   2735         case Constant::kHeapObject: {
   2736           Handle<HeapObject> src_object = src.ToHeapObject();
   2737           Heap::RootListIndex index;
   2738           if (IsMaterializableFromRoot(src_object, &index)) {
   2739             __ LoadRoot(dst, index);
   2740           } else {
   2741             __ Move(dst, src_object);
   2742           }
   2743           break;
   2744         }
   2745         case Constant::kRpoNumber:
   2746           UNREACHABLE();  // TODO(dcarney): loading RPO constants on S390.
   2747           break;
   2748       }
   2749       if (destination->IsStackSlot()) {
   2750         __ StoreP(dst, g.ToMemOperand(destination), r0);
   2751       }
   2752     } else {
   2753       DoubleRegister dst = destination->IsFPRegister()
   2754                                ? g.ToDoubleRegister(destination)
   2755                                : kScratchDoubleReg;
   2756       double value = (src.type() == Constant::kFloat32) ? src.ToFloat32()
   2757                                                         : src.ToFloat64();
   2758       if (src.type() == Constant::kFloat32) {
   2759         __ LoadFloat32Literal(dst, src.ToFloat32(), kScratchReg);
   2760       } else {
   2761         __ LoadDoubleLiteral(dst, value, kScratchReg);
   2762       }
   2763 
   2764       if (destination->IsFPStackSlot()) {
   2765         __ StoreDouble(dst, g.ToMemOperand(destination));
   2766       }
   2767     }
   2768   } else if (source->IsFPRegister()) {
   2769     DoubleRegister src = g.ToDoubleRegister(source);
   2770     if (destination->IsFPRegister()) {
   2771       DoubleRegister dst = g.ToDoubleRegister(destination);
   2772       __ Move(dst, src);
   2773     } else {
   2774       DCHECK(destination->IsFPStackSlot());
   2775       LocationOperand* op = LocationOperand::cast(source);
   2776       if (op->representation() == MachineRepresentation::kFloat64) {
   2777         __ StoreDouble(src, g.ToMemOperand(destination));
   2778       } else {
   2779         __ StoreFloat32(src, g.ToMemOperand(destination));
   2780       }
   2781     }
   2782   } else if (source->IsFPStackSlot()) {
   2783     DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
   2784     MemOperand src = g.ToMemOperand(source);
   2785     if (destination->IsFPRegister()) {
   2786       LocationOperand* op = LocationOperand::cast(source);
   2787       if (op->representation() == MachineRepresentation::kFloat64) {
   2788         __ LoadDouble(g.ToDoubleRegister(destination), src);
   2789       } else {
   2790         __ LoadFloat32(g.ToDoubleRegister(destination), src);
   2791       }
   2792     } else {
   2793       LocationOperand* op = LocationOperand::cast(source);
   2794       DoubleRegister temp = kScratchDoubleReg;
   2795       if (op->representation() == MachineRepresentation::kFloat64) {
   2796         __ LoadDouble(temp, src);
   2797         __ StoreDouble(temp, g.ToMemOperand(destination));
   2798       } else {
   2799         __ LoadFloat32(temp, src);
   2800         __ StoreFloat32(temp, g.ToMemOperand(destination));
   2801       }
   2802     }
   2803   } else {
   2804     UNREACHABLE();
   2805   }
   2806 }
   2807 
   2808 void CodeGenerator::AssembleSwap(InstructionOperand* source,
   2809                                  InstructionOperand* destination) {
   2810   S390OperandConverter g(this, nullptr);
   2811   // Dispatch on the source and destination operand kinds.  Not all
   2812   // combinations are possible.
   2813   if (source->IsRegister()) {
   2814     // Register-register.
   2815     Register temp = kScratchReg;
   2816     Register src = g.ToRegister(source);
   2817     if (destination->IsRegister()) {
   2818       Register dst = g.ToRegister(destination);
   2819       __ LoadRR(temp, src);
   2820       __ LoadRR(src, dst);
   2821       __ LoadRR(dst, temp);
   2822     } else {
   2823       DCHECK(destination->IsStackSlot());
   2824       MemOperand dst = g.ToMemOperand(destination);
   2825       __ LoadRR(temp, src);
   2826       __ LoadP(src, dst);
   2827       __ StoreP(temp, dst);
   2828     }
   2829 #if V8_TARGET_ARCH_S390X
   2830   } else if (source->IsStackSlot() || source->IsFPStackSlot()) {
   2831 #else
   2832   } else if (source->IsStackSlot()) {
   2833     DCHECK(destination->IsStackSlot());
   2834 #endif
   2835     Register temp_0 = kScratchReg;
   2836     Register temp_1 = r0;
   2837     MemOperand src = g.ToMemOperand(source);
   2838     MemOperand dst = g.ToMemOperand(destination);
   2839     __ LoadP(temp_0, src);
   2840     __ LoadP(temp_1, dst);
   2841     __ StoreP(temp_0, dst);
   2842     __ StoreP(temp_1, src);
   2843   } else if (source->IsFPRegister()) {
   2844     DoubleRegister temp = kScratchDoubleReg;
   2845     DoubleRegister src = g.ToDoubleRegister(source);
   2846     if (destination->IsFPRegister()) {
   2847       DoubleRegister dst = g.ToDoubleRegister(destination);
   2848       __ ldr(temp, src);
   2849       __ ldr(src, dst);
   2850       __ ldr(dst, temp);
   2851     } else {
   2852       DCHECK(destination->IsFPStackSlot());
   2853       MemOperand dst = g.ToMemOperand(destination);
   2854       __ ldr(temp, src);
   2855       __ LoadDouble(src, dst);
   2856       __ StoreDouble(temp, dst);
   2857     }
   2858 #if !V8_TARGET_ARCH_S390X
   2859   } else if (source->IsFPStackSlot()) {
   2860     DCHECK(destination->IsFPStackSlot());
   2861     DoubleRegister temp_0 = kScratchDoubleReg;
   2862     DoubleRegister temp_1 = d0;
   2863     MemOperand src = g.ToMemOperand(source);
   2864     MemOperand dst = g.ToMemOperand(destination);
   2865     // TODO(joransiu): MVC opportunity
   2866     __ LoadDouble(temp_0, src);
   2867     __ LoadDouble(temp_1, dst);
   2868     __ StoreDouble(temp_0, dst);
   2869     __ StoreDouble(temp_1, src);
   2870 #endif
   2871   } else {
   2872     // No other combinations are possible.
   2873     UNREACHABLE();
   2874   }
   2875 }
   2876 
   2877 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
   2878   for (size_t index = 0; index < target_count; ++index) {
   2879     __ emit_label_addr(targets[index]);
   2880   }
   2881 }
   2882 
   2883 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   2884   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
   2885     return;
   2886   }
   2887 
   2888   int space_needed = Deoptimizer::patch_size();
   2889   // Ensure that we have enough space after the previous lazy-bailout
   2890   // instruction for patching the code here.
   2891   int current_pc = masm()->pc_offset();
   2892   if (current_pc < last_lazy_deopt_pc_ + space_needed) {
   2893     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
   2894     DCHECK_EQ(0, padding_size % 2);
   2895     while (padding_size > 0) {
   2896       __ nop();
   2897       padding_size -= 2;
   2898     }
   2899   }
   2900 }
   2901 
   2902 #undef __
   2903 
   2904 }  // namespace compiler
   2905 }  // namespace internal
   2906 }  // namespace v8
   2907