| Index: src/compiler/s390/code-generator-s390.cc
|
| diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/s390/code-generator-s390.cc
|
| similarity index 55%
|
| copy from src/compiler/ppc/code-generator-ppc.cc
|
| copy to src/compiler/s390/code-generator-s390.cc
|
| index 6bf0a7e80a75a59c7f1e0a0d618c6411a707c7d7..0b687210707cc3ca68d8d7d74eff6001831059ad 100644
|
| --- a/src/compiler/ppc/code-generator-ppc.cc
|
| +++ b/src/compiler/s390/code-generator-s390.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2014 the V8 project authors. All rights reserved.
|
| +// Copyright 2015 the V8 project authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| @@ -9,7 +9,7 @@
|
| #include "src/compiler/gap-resolver.h"
|
| #include "src/compiler/node-matchers.h"
|
| #include "src/compiler/osr.h"
|
| -#include "src/ppc/macro-assembler-ppc.h"
|
| +#include "src/s390/macro-assembler-s390.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -17,31 +17,16 @@ namespace compiler {
|
|
|
| #define __ masm()->
|
|
|
| +#define kScratchReg ip
|
|
|
| -#define kScratchReg r11
|
| -
|
| -
|
| -// Adds PPC-specific methods to convert InstructionOperands.
|
| -class PPCOperandConverter final : public InstructionOperandConverter {
|
| +// Adds S390-specific methods to convert InstructionOperands.
|
| +class S390OperandConverter final : public InstructionOperandConverter {
|
| public:
|
| - PPCOperandConverter(CodeGenerator* gen, Instruction* instr)
|
| + S390OperandConverter(CodeGenerator* gen, Instruction* instr)
|
| : InstructionOperandConverter(gen, instr) {}
|
|
|
| size_t OutputCount() { return instr_->OutputCount(); }
|
|
|
| - RCBit OutputRCBit() const {
|
| - switch (instr_->flags_mode()) {
|
| - case kFlags_branch:
|
| - case kFlags_deoptimize:
|
| - case kFlags_set:
|
| - return SetRC;
|
| - case kFlags_none:
|
| - return LeaveRC;
|
| - }
|
| - UNREACHABLE();
|
| - return LeaveRC;
|
| - }
|
| -
|
| bool CompareLogical() const {
|
| switch (instr_->flags_condition()) {
|
| case kUnsignedLessThan:
|
| @@ -68,7 +53,7 @@ class PPCOperandConverter final : public InstructionOperandConverter {
|
| return Operand(
|
| isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
|
| case Constant::kInt64:
|
| -#if V8_TARGET_ARCH_PPC64
|
| +#if V8_TARGET_ARCH_S390X
|
| return Operand(constant.ToInt64());
|
| #endif
|
| case Constant::kExternalReference:
|
| @@ -110,12 +95,10 @@ class PPCOperandConverter final : public InstructionOperandConverter {
|
| }
|
| };
|
|
|
| -
|
| -static inline bool HasRegisterInput(Instruction* instr, size_t index) {
|
| +static inline bool HasRegisterInput(Instruction* instr, int index) {
|
| return instr->InputAt(index)->IsRegister();
|
| }
|
|
|
| -
|
| namespace {
|
|
|
| class OutOfLineLoadNAN32 final : public OutOfLineCode {
|
| @@ -132,7 +115,6 @@ class OutOfLineLoadNAN32 final : public OutOfLineCode {
|
| DoubleRegister const result_;
|
| };
|
|
|
| -
|
| class OutOfLineLoadNAN64 final : public OutOfLineCode {
|
| public:
|
| OutOfLineLoadNAN64(CodeGenerator* gen, DoubleRegister result)
|
| @@ -147,19 +129,17 @@ class OutOfLineLoadNAN64 final : public OutOfLineCode {
|
| DoubleRegister const result_;
|
| };
|
|
|
| -
|
| class OutOfLineLoadZero final : public OutOfLineCode {
|
| public:
|
| OutOfLineLoadZero(CodeGenerator* gen, Register result)
|
| : OutOfLineCode(gen), result_(result) {}
|
|
|
| - void Generate() final { __ li(result_, Operand::Zero()); }
|
| + void Generate() final { __ LoadImmP(result_, Operand::Zero()); }
|
|
|
| private:
|
| Register const result_;
|
| };
|
|
|
| -
|
| class OutOfLineRecordWrite final : public OutOfLineCode {
|
| public:
|
| OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset,
|
| @@ -199,23 +179,21 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
| SaveFPRegsMode const save_fp_mode =
|
| frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
|
| if (!frame()->needs_frame()) {
|
| - // We need to save and restore lr if the frame was elided.
|
| - __ mflr(scratch1_);
|
| - __ Push(scratch1_);
|
| + // We need to save and restore r14 if the frame was elided.
|
| + __ Push(r14);
|
| }
|
| RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
|
| remembered_set_action, save_fp_mode);
|
| if (offset_.is(no_reg)) {
|
| - __ addi(scratch1_, object_, Operand(offset_immediate_));
|
| + __ AddP(scratch1_, object_, Operand(offset_immediate_));
|
| } else {
|
| DCHECK_EQ(0, offset_immediate_);
|
| - __ add(scratch1_, object_, offset_);
|
| + __ AddP(scratch1_, object_, offset_);
|
| }
|
| __ CallStub(&stub);
|
| if (!frame()->needs_frame()) {
|
| - // We need to save and restore lr if the frame was elided.
|
| - __ Pop(scratch1_);
|
| - __ mtlr(scratch1_);
|
| + // We need to save and restore r14 if the frame was elided.
|
| + __ Pop(r14);
|
| }
|
| }
|
|
|
| @@ -229,7 +207,6 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
| RecordWriteMode const mode_;
|
| };
|
|
|
| -
|
| Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| switch (condition) {
|
| case kEqual:
|
| @@ -249,16 +226,16 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| case kUnsignedGreaterThan:
|
| return gt;
|
| case kOverflow:
|
| - // Overflow checked for add/sub only.
|
| + // Overflow checked for AddP/SubP only.
|
| switch (op) {
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Add:
|
| - case kPPC_Sub:
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Add:
|
| + case kS390_Sub:
|
| return lt;
|
| #endif
|
| - case kPPC_AddWithOverflow32:
|
| - case kPPC_SubWithOverflow32:
|
| -#if V8_TARGET_ARCH_PPC64
|
| + case kS390_AddWithOverflow32:
|
| + case kS390_SubWithOverflow32:
|
| +#if V8_TARGET_ARCH_S390X
|
| return ne;
|
| #else
|
| return lt;
|
| @@ -269,14 +246,14 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| break;
|
| case kNotOverflow:
|
| switch (op) {
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Add:
|
| - case kPPC_Sub:
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Add:
|
| + case kS390_Sub:
|
| return ge;
|
| #endif
|
| - case kPPC_AddWithOverflow32:
|
| - case kPPC_SubWithOverflow32:
|
| -#if V8_TARGET_ARCH_PPC64
|
| + case kS390_AddWithOverflow32:
|
| + case kS390_SubWithOverflow32:
|
| +#if V8_TARGET_ARCH_S390X
|
| return eq;
|
| #else
|
| return ge;
|
| @@ -294,20 +271,17 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
|
|
| } // namespace
|
|
|
| -#define ASSEMBLE_FLOAT_UNOP_RC(asm_instr) \
|
| - do { \
|
| - __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
|
| - i.OutputRCBit()); \
|
| +#define ASSEMBLE_FLOAT_UNOP(asm_instr) \
|
| + do { \
|
| + __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_FLOAT_BINOP_RC(asm_instr) \
|
| +#define ASSEMBLE_FLOAT_BINOP(asm_instr) \
|
| do { \
|
| __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
|
| - i.InputDoubleRegister(1), i.OutputRCBit()); \
|
| + i.InputDoubleRegister(1)); \
|
| } while (0)
|
|
|
| -
|
| #define ASSEMBLE_BINOP(asm_instr_reg, asm_instr_imm) \
|
| do { \
|
| if (HasRegisterInput(instr, 1)) { \
|
| @@ -319,31 +293,17 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| } \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_BINOP_RC(asm_instr_reg, asm_instr_imm) \
|
| +#define ASSEMBLE_BINOP_INT(asm_instr_reg, asm_instr_imm) \
|
| do { \
|
| if (HasRegisterInput(instr, 1)) { \
|
| __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \
|
| - i.InputRegister(1), i.OutputRCBit()); \
|
| - } else { \
|
| - __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \
|
| - i.InputImmediate(1), i.OutputRCBit()); \
|
| - } \
|
| - } while (0)
|
| -
|
| -
|
| -#define ASSEMBLE_BINOP_INT_RC(asm_instr_reg, asm_instr_imm) \
|
| - do { \
|
| - if (HasRegisterInput(instr, 1)) { \
|
| - __ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \
|
| - i.InputRegister(1), i.OutputRCBit()); \
|
| + i.InputRegister(1)); \
|
| } else { \
|
| __ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \
|
| - i.InputInt32(1), i.OutputRCBit()); \
|
| + i.InputInt32(1)); \
|
| } \
|
| } while (0)
|
|
|
| -
|
| #define ASSEMBLE_ADD_WITH_OVERFLOW() \
|
| do { \
|
| if (HasRegisterInput(instr, 1)) { \
|
| @@ -355,7 +315,6 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| } \
|
| } while (0)
|
|
|
| -
|
| #define ASSEMBLE_SUB_WITH_OVERFLOW() \
|
| do { \
|
| if (HasRegisterInput(instr, 1)) { \
|
| @@ -367,63 +326,56 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| } \
|
| } while (0)
|
|
|
| -
|
| -#if V8_TARGET_ARCH_PPC64
|
| -#define ASSEMBLE_ADD_WITH_OVERFLOW32() \
|
| - do { \
|
| - ASSEMBLE_BINOP(add, addi); \
|
| - __ TestIfInt32(i.OutputRegister(), r0, cr0); \
|
| +#if V8_TARGET_ARCH_S390X
|
| +#define ASSEMBLE_ADD_WITH_OVERFLOW32() \
|
| + do { \
|
| + ASSEMBLE_BINOP(AddP, AddP); \
|
| + __ TestIfInt32(i.OutputRegister(), r0); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_SUB_WITH_OVERFLOW32() \
|
| - do { \
|
| - ASSEMBLE_BINOP(sub, subi); \
|
| - __ TestIfInt32(i.OutputRegister(), r0, cr0); \
|
| +#define ASSEMBLE_SUB_WITH_OVERFLOW32() \
|
| + do { \
|
| + ASSEMBLE_BINOP(SubP, SubP); \
|
| + __ TestIfInt32(i.OutputRegister(), r0); \
|
| } while (0)
|
| #else
|
| #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW
|
| #define ASSEMBLE_SUB_WITH_OVERFLOW32 ASSEMBLE_SUB_WITH_OVERFLOW
|
| #endif
|
|
|
| -
|
| -#define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \
|
| - do { \
|
| - const CRegister cr = cr0; \
|
| - if (HasRegisterInput(instr, 1)) { \
|
| - if (i.CompareLogical()) { \
|
| - __ cmpl_instr(i.InputRegister(0), i.InputRegister(1), cr); \
|
| - } else { \
|
| - __ cmp_instr(i.InputRegister(0), i.InputRegister(1), cr); \
|
| - } \
|
| - } else { \
|
| - if (i.CompareLogical()) { \
|
| - __ cmpl_instr##i(i.InputRegister(0), i.InputImmediate(1), cr); \
|
| - } else { \
|
| - __ cmp_instr##i(i.InputRegister(0), i.InputImmediate(1), cr); \
|
| - } \
|
| - } \
|
| - DCHECK_EQ(SetRC, i.OutputRCBit()); \
|
| +#define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \
|
| + do { \
|
| + if (HasRegisterInput(instr, 1)) { \
|
| + if (i.CompareLogical()) { \
|
| + __ cmpl_instr(i.InputRegister(0), i.InputRegister(1)); \
|
| + } else { \
|
| + __ cmp_instr(i.InputRegister(0), i.InputRegister(1)); \
|
| + } \
|
| + } else { \
|
| + if (i.CompareLogical()) { \
|
| + __ cmpl_instr(i.InputRegister(0), i.InputImmediate(1)); \
|
| + } else { \
|
| + __ cmp_instr(i.InputRegister(0), i.InputImmediate(1)); \
|
| + } \
|
| + } \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_FLOAT_COMPARE(cmp_instr) \
|
| - do { \
|
| - const CRegister cr = cr0; \
|
| - __ cmp_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1), cr); \
|
| - DCHECK_EQ(SetRC, i.OutputRCBit()); \
|
| - } while (0)
|
| -
|
| -
|
| -#define ASSEMBLE_MODULO(div_instr, mul_instr) \
|
| +#define ASSEMBLE_FLOAT_COMPARE(cmp_instr) \
|
| do { \
|
| - const Register scratch = kScratchReg; \
|
| - __ div_instr(scratch, i.InputRegister(0), i.InputRegister(1)); \
|
| - __ mul_instr(scratch, scratch, i.InputRegister(1)); \
|
| - __ sub(i.OutputRegister(), i.InputRegister(0), scratch, LeaveOE, \
|
| - i.OutputRCBit()); \
|
| + __ cmp_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1); \
|
| } while (0)
|
|
|
| +// Divide instruction dr will implicity use register pair
|
| +// r0 & r1 below.
|
| +// R0:R1 = R1 / divisor - R0 remainder
|
| +// Copy remainder to output reg
|
| +#define ASSEMBLE_MODULO(div_instr, shift_instr) \
|
| + do { \
|
| + __ LoadRR(r0, i.InputRegister(0)); \
|
| + __ shift_instr(r0, Operand(32)); \
|
| + __ div_instr(r0, i.InputRegister(1)); \
|
| + __ ltr(i.OutputRegister(), r0); \
|
| + } while (0)
|
|
|
| #define ASSEMBLE_FLOAT_MODULO() \
|
| do { \
|
| @@ -434,154 +386,116 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), \
|
| 0, 2); \
|
| __ MovFromFloatResult(i.OutputDoubleRegister()); \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_FLOAT_MAX(scratch_reg) \
|
| - do { \
|
| - __ fsub(scratch_reg, i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
|
| - __ fsel(i.OutputDoubleRegister(), scratch_reg, i.InputDoubleRegister(0), \
|
| - i.InputDoubleRegister(1)); \
|
| +#define ASSEMBLE_FLOAT_MAX(double_scratch_reg, general_scratch_reg) \
|
| + do { \
|
| + Label ge, done; \
|
| + __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
|
| + __ bge(&ge, Label::kNear); \
|
| + __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); \
|
| + __ b(&done, Label::kNear); \
|
| + __ bind(&ge); \
|
| + __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
| + __ bind(&done); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_FLOAT_MIN(scratch_reg) \
|
| - do { \
|
| - __ fsub(scratch_reg, i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
|
| - __ fsel(i.OutputDoubleRegister(), scratch_reg, i.InputDoubleRegister(1), \
|
| - i.InputDoubleRegister(0)); \
|
| +#define ASSEMBLE_FLOAT_MIN(double_scratch_reg, general_scratch_reg) \
|
| + do { \
|
| + Label ge, done; \
|
| + __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
|
| + __ bge(&ge, Label::kNear); \
|
| + __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
| + __ b(&done, Label::kNear); \
|
| + __ bind(&ge); \
|
| + __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(1)); \
|
| + __ bind(&done); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_LOAD_FLOAT(asm_instr, asm_instrx) \
|
| +// Only MRI mode for these instructions available
|
| +#define ASSEMBLE_LOAD_FLOAT(asm_instr) \
|
| do { \
|
| DoubleRegister result = i.OutputDoubleRegister(); \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode); \
|
| - if (mode == kMode_MRI) { \
|
| - __ asm_instr(result, operand); \
|
| - } else { \
|
| - __ asm_instrx(result, operand); \
|
| - } \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| + __ asm_instr(result, operand); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_LOAD_INTEGER(asm_instr, asm_instrx) \
|
| - do { \
|
| - Register result = i.OutputRegister(); \
|
| - AddressingMode mode = kMode_None; \
|
| - MemOperand operand = i.MemoryOperand(&mode); \
|
| - if (mode == kMode_MRI) { \
|
| - __ asm_instr(result, operand); \
|
| - } else { \
|
| - __ asm_instrx(result, operand); \
|
| - } \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| +#define ASSEMBLE_LOAD_INTEGER(asm_instr) \
|
| + do { \
|
| + Register result = i.OutputRegister(); \
|
| + AddressingMode mode = kMode_None; \
|
| + MemOperand operand = i.MemoryOperand(&mode); \
|
| + __ asm_instr(result, operand); \
|
| } while (0)
|
|
|
| -
|
| #define ASSEMBLE_STORE_FLOAT32() \
|
| do { \
|
| size_t index = 0; \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode, &index); \
|
| DoubleRegister value = i.InputDoubleRegister(index); \
|
| - __ frsp(kScratchDoubleReg, value); \
|
| - if (mode == kMode_MRI) { \
|
| - __ stfs(kScratchDoubleReg, operand); \
|
| - } else { \
|
| - __ stfsx(kScratchDoubleReg, operand); \
|
| - } \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| + __ StoreFloat32(value, operand); \
|
| } while (0)
|
|
|
| -
|
| #define ASSEMBLE_STORE_DOUBLE() \
|
| do { \
|
| size_t index = 0; \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode, &index); \
|
| DoubleRegister value = i.InputDoubleRegister(index); \
|
| - if (mode == kMode_MRI) { \
|
| - __ stfd(value, operand); \
|
| - } else { \
|
| - __ stfdx(value, operand); \
|
| - } \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| + __ StoreDouble(value, operand); \
|
| } while (0)
|
|
|
| -
|
| -#define ASSEMBLE_STORE_INTEGER(asm_instr, asm_instrx) \
|
| +#define ASSEMBLE_STORE_INTEGER(asm_instr) \
|
| do { \
|
| size_t index = 0; \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode, &index); \
|
| Register value = i.InputRegister(index); \
|
| - if (mode == kMode_MRI) { \
|
| - __ asm_instr(value, operand); \
|
| - } else { \
|
| - __ asm_instrx(value, operand); \
|
| - } \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| + __ asm_instr(value, operand); \
|
| } while (0)
|
|
|
| -
|
| // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
|
| -#define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, asm_instrx, width) \
|
| +#define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, width) \
|
| do { \
|
| DoubleRegister result = i.OutputDoubleRegister(); \
|
| size_t index = 0; \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode, index); \
|
| - DCHECK_EQ(kMode_MRR, mode); \
|
| Register offset = operand.rb(); \
|
| - __ extsw(offset, offset); \
|
| + __ lgfr(offset, offset); \
|
| if (HasRegisterInput(instr, 2)) { \
|
| - __ cmplw(offset, i.InputRegister(2)); \
|
| + __ CmpLogical32(offset, i.InputRegister(2)); \
|
| } else { \
|
| - __ cmplwi(offset, i.InputImmediate(2)); \
|
| + __ CmpLogical32(offset, i.InputImmediate(2)); \
|
| } \
|
| auto ool = new (zone()) OutOfLineLoadNAN##width(this, result); \
|
| __ bge(ool->entry()); \
|
| - if (mode == kMode_MRI) { \
|
| - __ asm_instr(result, operand); \
|
| - } else { \
|
| - __ asm_instrx(result, operand); \
|
| - } \
|
| + __ asm_instr(result, operand); \
|
| __ bind(ool->exit()); \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| } while (0)
|
|
|
| -
|
| // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
|
| -#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr, asm_instrx) \
|
| +#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \
|
| do { \
|
| Register result = i.OutputRegister(); \
|
| size_t index = 0; \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode, index); \
|
| - DCHECK_EQ(kMode_MRR, mode); \
|
| Register offset = operand.rb(); \
|
| - __ extsw(offset, offset); \
|
| + __ lgfr(offset, offset); \
|
| if (HasRegisterInput(instr, 2)) { \
|
| - __ cmplw(offset, i.InputRegister(2)); \
|
| + __ CmpLogical32(offset, i.InputRegister(2)); \
|
| } else { \
|
| - __ cmplwi(offset, i.InputImmediate(2)); \
|
| + __ CmpLogical32(offset, i.InputImmediate(2)); \
|
| } \
|
| auto ool = new (zone()) OutOfLineLoadZero(this, result); \
|
| __ bge(ool->entry()); \
|
| - if (mode == kMode_MRI) { \
|
| - __ asm_instr(result, operand); \
|
| - } else { \
|
| - __ asm_instrx(result, operand); \
|
| - } \
|
| + __ asm_instr(result, operand); \
|
| __ bind(ool->exit()); \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| } while (0)
|
|
|
| -
|
| // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
|
| #define ASSEMBLE_CHECKED_STORE_FLOAT32() \
|
| do { \
|
| @@ -589,27 +503,19 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| size_t index = 0; \
|
| AddressingMode mode = kMode_None; \
|
| MemOperand operand = i.MemoryOperand(&mode, index); \
|
| - DCHECK_EQ(kMode_MRR, mode); \
|
| Register offset = operand.rb(); \
|
| - __ extsw(offset, offset); \
|
| + __ lgfr(offset, offset); \
|
| if (HasRegisterInput(instr, 2)) { \
|
| - __ cmplw(offset, i.InputRegister(2)); \
|
| + __ CmpLogical32(offset, i.InputRegister(2)); \
|
| } else { \
|
| - __ cmplwi(offset, i.InputImmediate(2)); \
|
| + __ CmpLogical32(offset, i.InputImmediate(2)); \
|
| } \
|
| __ bge(&done); \
|
| DoubleRegister value = i.InputDoubleRegister(3); \
|
| - __ frsp(kScratchDoubleReg, value); \
|
| - if (mode == kMode_MRI) { \
|
| - __ stfs(kScratchDoubleReg, operand); \
|
| - } else { \
|
| - __ stfsx(kScratchDoubleReg, operand); \
|
| - } \
|
| + __ StoreFloat32(value, operand); \
|
| __ bind(&done); \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| } while (0)
|
|
|
| -
|
| // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
|
| #define ASSEMBLE_CHECKED_STORE_DOUBLE() \
|
| do { \
|
| @@ -619,64 +525,50 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
| MemOperand operand = i.MemoryOperand(&mode, index); \
|
| DCHECK_EQ(kMode_MRR, mode); \
|
| Register offset = operand.rb(); \
|
| - __ extsw(offset, offset); \
|
| + __ lgfr(offset, offset); \
|
| if (HasRegisterInput(instr, 2)) { \
|
| - __ cmplw(offset, i.InputRegister(2)); \
|
| + __ CmpLogical32(offset, i.InputRegister(2)); \
|
| } else { \
|
| - __ cmplwi(offset, i.InputImmediate(2)); \
|
| + __ CmpLogical32(offset, i.InputImmediate(2)); \
|
| } \
|
| __ bge(&done); \
|
| DoubleRegister value = i.InputDoubleRegister(3); \
|
| - if (mode == kMode_MRI) { \
|
| - __ stfd(value, operand); \
|
| - } else { \
|
| - __ stfdx(value, operand); \
|
| - } \
|
| + __ StoreDouble(value, operand); \
|
| __ bind(&done); \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| } while (0)
|
|
|
| -
|
| // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
|
| -#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr, asm_instrx) \
|
| - do { \
|
| - Label done; \
|
| - size_t index = 0; \
|
| - AddressingMode mode = kMode_None; \
|
| - MemOperand operand = i.MemoryOperand(&mode, index); \
|
| - DCHECK_EQ(kMode_MRR, mode); \
|
| - Register offset = operand.rb(); \
|
| - __ extsw(offset, offset); \
|
| - if (HasRegisterInput(instr, 2)) { \
|
| - __ cmplw(offset, i.InputRegister(2)); \
|
| - } else { \
|
| - __ cmplwi(offset, i.InputImmediate(2)); \
|
| - } \
|
| - __ bge(&done); \
|
| - Register value = i.InputRegister(3); \
|
| - if (mode == kMode_MRI) { \
|
| - __ asm_instr(value, operand); \
|
| - } else { \
|
| - __ asm_instrx(value, operand); \
|
| - } \
|
| - __ bind(&done); \
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
|
| +#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \
|
| + do { \
|
| + Label done; \
|
| + size_t index = 0; \
|
| + AddressingMode mode = kMode_None; \
|
| + MemOperand operand = i.MemoryOperand(&mode, index); \
|
| + Register offset = operand.rb(); \
|
| + __ lgfr(offset, offset); \
|
| + if (HasRegisterInput(instr, 2)) { \
|
| + __ CmpLogical32(offset, i.InputRegister(2)); \
|
| + } else { \
|
| + __ CmpLogical32(offset, i.InputImmediate(2)); \
|
| + } \
|
| + __ bge(&done); \
|
| + Register value = i.InputRegister(3); \
|
| + __ asm_instr(value, operand); \
|
| + __ bind(&done); \
|
| } while (0)
|
|
|
| -
|
| void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
|
| int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
|
| if (sp_slot_delta > 0) {
|
| - __ Add(sp, sp, sp_slot_delta * kPointerSize, r0);
|
| + __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize));
|
| }
|
| frame_access_state()->SetFrameAccessToDefault();
|
| }
|
|
|
| -
|
| void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
|
| int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
|
| if (sp_slot_delta < 0) {
|
| - __ Add(sp, sp, sp_slot_delta * kPointerSize, r0);
|
| + __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize));
|
| frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
|
| }
|
| if (frame()->needs_frame()) {
|
| @@ -685,19 +577,16 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
|
| frame_access_state()->SetFrameAccessToSP();
|
| }
|
|
|
| -
|
| // Assembles an instruction after register allocation, producing machine code.
|
| void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| - PPCOperandConverter i(this, instr);
|
| + S390OperandConverter i(this, instr);
|
| ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode());
|
|
|
| switch (opcode) {
|
| case kArchCallCodeObject: {
|
| - v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
|
| - masm());
|
| EnsureSpaceForLazyDeopt();
|
| if (HasRegisterInput(instr, 0)) {
|
| - __ addi(ip, i.InputRegister(0),
|
| + __ AddP(ip, i.InputRegister(0),
|
| Operand(Code::kHeaderSize - kHeapObjectTag));
|
| __ Call(ip);
|
| } else {
|
| @@ -705,7 +594,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| RelocInfo::CODE_TARGET);
|
| }
|
| RecordCallPosition(instr);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| frame_access_state()->ClearSPDelta();
|
| break;
|
| }
|
| @@ -713,7 +601,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
|
| AssembleDeconstructActivationRecord(stack_param_delta);
|
| if (HasRegisterInput(instr, 0)) {
|
| - __ addi(ip, i.InputRegister(0),
|
| + __ AddP(ip, i.InputRegister(0),
|
| Operand(Code::kHeaderSize - kHeapObjectTag));
|
| __ Jump(ip);
|
| } else {
|
| @@ -723,26 +611,22 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
|
| RelocInfo::CODE_TARGET);
|
| }
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| frame_access_state()->ClearSPDelta();
|
| break;
|
| }
|
| case kArchCallJSFunction: {
|
| - v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
|
| - masm());
|
| EnsureSpaceForLazyDeopt();
|
| Register func = i.InputRegister(0);
|
| if (FLAG_debug_code) {
|
| // Check the function's context matches the context argument.
|
| __ LoadP(kScratchReg,
|
| FieldMemOperand(func, JSFunction::kContextOffset));
|
| - __ cmp(cp, kScratchReg);
|
| + __ CmpP(cp, kScratchReg);
|
| __ Assert(eq, kWrongFunctionContext);
|
| }
|
| __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
|
| __ Call(ip);
|
| RecordCallPosition(instr);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| frame_access_state()->ClearSPDelta();
|
| break;
|
| }
|
| @@ -752,14 +636,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| // Check the function's context matches the context argument.
|
| __ LoadP(kScratchReg,
|
| FieldMemOperand(func, JSFunction::kContextOffset));
|
| - __ cmp(cp, kScratchReg);
|
| + __ CmpP(cp, kScratchReg);
|
| __ Assert(eq, kWrongFunctionContext);
|
| }
|
| int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
|
| AssembleDeconstructActivationRecord(stack_param_delta);
|
| __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
|
| __ Jump(ip);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| frame_access_state()->ClearSPDelta();
|
| break;
|
| }
|
| @@ -788,20 +671,16 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| }
|
| case kArchJmp:
|
| AssembleArchJump(i.InputRpo(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| case kArchLookupSwitch:
|
| AssembleArchLookupSwitch(instr);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| case kArchTableSwitch:
|
| AssembleArchTableSwitch(instr);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| case kArchNop:
|
| case kArchThrowTerminator:
|
| // don't emit code for nops.
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| case kArchDeoptimize: {
|
| int deopt_state_id =
|
| @@ -813,27 +692,23 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| }
|
| case kArchRet:
|
| AssembleReturn();
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| case kArchStackPointer:
|
| - __ mr(i.OutputRegister(), sp);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + __ LoadRR(i.OutputRegister(), sp);
|
| break;
|
| case kArchFramePointer:
|
| - __ mr(i.OutputRegister(), fp);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + __ LoadRR(i.OutputRegister(), fp);
|
| break;
|
| case kArchParentFramePointer:
|
| if (frame_access_state()->frame()->needs_frame()) {
|
| __ LoadP(i.OutputRegister(), MemOperand(fp, 0));
|
| } else {
|
| - __ mr(i.OutputRegister(), fp);
|
| + __ LoadRR(i.OutputRegister(), fp);
|
| }
|
| break;
|
| case kArchTruncateDoubleToI:
|
| // TODO(mbrandy): move slow call to stub out of line.
|
| __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| case kArchStoreWithWriteBarrier: {
|
| RecordWriteMode mode =
|
| @@ -856,7 +731,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| Register offset(i.InputRegister(1));
|
| ool = new (zone()) OutOfLineRecordWrite(this, object, offset, value,
|
| scratch0, scratch1, mode);
|
| - __ StorePX(value, MemOperand(object, offset));
|
| + __ StoreP(value, MemOperand(object, offset));
|
| }
|
| __ CheckPageFlag(object, scratch0,
|
| MemoryChunk::kPointersFromHereAreInterestingMask, ne,
|
| @@ -867,591 +742,768 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| case kArchStackSlot: {
|
| FrameOffset offset =
|
| frame_access_state()->GetFrameOffset(i.InputInt32(0));
|
| - __ addi(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
|
| + __ AddP(i.OutputRegister(), offset.from_stack_pointer() ? sp : fp,
|
| Operand(offset.offset()));
|
| break;
|
| }
|
| - case kPPC_And:
|
| - if (HasRegisterInput(instr, 1)) {
|
| - __ and_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| - } else {
|
| - __ andi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
|
| - }
|
| + case kS390_And:
|
| + ASSEMBLE_BINOP(AndP, AndP);
|
| + break;
|
| + case kS390_AndComplement:
|
| + __ NotP(i.InputRegister(1));
|
| + __ AndP(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| + break;
|
| + case kS390_Or:
|
| + ASSEMBLE_BINOP(OrP, OrP);
|
| + break;
|
| + case kS390_OrComplement:
|
| + __ NotP(i.InputRegister(1));
|
| + __ OrP(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| break;
|
| - case kPPC_AndComplement:
|
| - __ andc(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| + case kS390_Xor:
|
| + ASSEMBLE_BINOP(XorP, XorP);
|
| break;
|
| - case kPPC_Or:
|
| + case kS390_ShiftLeft32:
|
| if (HasRegisterInput(instr, 1)) {
|
| - __ orx(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| + if (i.OutputRegister().is(i.InputRegister(1))) {
|
| + __ LoadRR(kScratchReg, i.InputRegister(1));
|
| + __ ShiftLeft(i.OutputRegister(), i.InputRegister(0), kScratchReg);
|
| + } else {
|
| + ASSEMBLE_BINOP(ShiftLeft, ShiftLeft);
|
| + }
|
| } else {
|
| - __ ori(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + ASSEMBLE_BINOP(ShiftLeft, ShiftLeft);
|
| }
|
| +#if V8_TARGET_ARCH_S390X
|
| + __ lgfr(i.OutputRegister(0), i.OutputRegister(0));
|
| +#endif
|
| break;
|
| - case kPPC_OrComplement:
|
| - __ orc(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_ShiftLeft64:
|
| + ASSEMBLE_BINOP(sllg, sllg);
|
| break;
|
| - case kPPC_Xor:
|
| +#endif
|
| + case kS390_ShiftRight32:
|
| if (HasRegisterInput(instr, 1)) {
|
| - __ xor_(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| + if (i.OutputRegister().is(i.InputRegister(1))) {
|
| + __ LoadRR(kScratchReg, i.InputRegister(1));
|
| + __ ShiftRight(i.OutputRegister(), i.InputRegister(0), kScratchReg);
|
| + } else {
|
| + ASSEMBLE_BINOP(ShiftRight, ShiftRight);
|
| + }
|
| } else {
|
| - __ xori(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + ASSEMBLE_BINOP(ShiftRight, ShiftRight);
|
| }
|
| - break;
|
| - case kPPC_ShiftLeft32:
|
| - ASSEMBLE_BINOP_RC(slw, slwi);
|
| - break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_ShiftLeft64:
|
| - ASSEMBLE_BINOP_RC(sld, sldi);
|
| - break;
|
| +#if V8_TARGET_ARCH_S390X
|
| + __ lgfr(i.OutputRegister(0), i.OutputRegister(0));
|
| #endif
|
| - case kPPC_ShiftRight32:
|
| - ASSEMBLE_BINOP_RC(srw, srwi);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_ShiftRight64:
|
| - ASSEMBLE_BINOP_RC(srd, srdi);
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_ShiftRight64:
|
| + ASSEMBLE_BINOP(srlg, srlg);
|
| break;
|
| #endif
|
| - case kPPC_ShiftRightAlg32:
|
| - ASSEMBLE_BINOP_INT_RC(sraw, srawi);
|
| + case kS390_ShiftRightAlg32:
|
| + if (HasRegisterInput(instr, 1)) {
|
| + if (i.OutputRegister().is(i.InputRegister(1))) {
|
| + __ LoadRR(kScratchReg, i.InputRegister(1));
|
| + __ ShiftRightArith(i.OutputRegister(), i.InputRegister(0),
|
| + kScratchReg);
|
| + } else {
|
| + ASSEMBLE_BINOP(ShiftRightArith, ShiftRightArith);
|
| + }
|
| + } else {
|
| + ASSEMBLE_BINOP(ShiftRightArith, ShiftRightArith);
|
| + }
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_ShiftRightAlg64:
|
| - ASSEMBLE_BINOP_INT_RC(srad, sradi);
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_ShiftRightAlg64:
|
| + ASSEMBLE_BINOP(srag, srag);
|
| break;
|
| #endif
|
| - case kPPC_RotRight32:
|
| + case kS390_RotRight32:
|
| if (HasRegisterInput(instr, 1)) {
|
| - __ subfic(kScratchReg, i.InputRegister(1), Operand(32));
|
| - __ rotlw(i.OutputRegister(), i.InputRegister(0), kScratchReg,
|
| - i.OutputRCBit());
|
| + __ LoadComplementRR(kScratchReg, i.InputRegister(1));
|
| + __ rll(i.OutputRegister(), i.InputRegister(0), kScratchReg);
|
| } else {
|
| - int sh = i.InputInt32(1);
|
| - __ rotrwi(i.OutputRegister(), i.InputRegister(0), sh, i.OutputRCBit());
|
| + __ rll(i.OutputRegister(), i.InputRegister(0),
|
| + Operand(32 - i.InputInt32(1)));
|
| }
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_RotRight64:
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_RotRight64:
|
| if (HasRegisterInput(instr, 1)) {
|
| - __ subfic(kScratchReg, i.InputRegister(1), Operand(64));
|
| - __ rotld(i.OutputRegister(), i.InputRegister(0), kScratchReg,
|
| - i.OutputRCBit());
|
| + __ LoadComplementRR(kScratchReg, i.InputRegister(1));
|
| + __ rll(i.OutputRegister(), i.InputRegister(0), kScratchReg,
|
| + Operand(32));
|
| + __ lgfr(i.OutputRegister(), i.OutputRegister());
|
| } else {
|
| - int sh = i.InputInt32(1);
|
| - __ rotrdi(i.OutputRegister(), i.InputRegister(0), sh, i.OutputRCBit());
|
| + UNIMPLEMENTED(); // Not implemented for now
|
| }
|
| break;
|
| #endif
|
| - case kPPC_Not:
|
| - __ notx(i.OutputRegister(), i.InputRegister(0), i.OutputRCBit());
|
| - break;
|
| - case kPPC_RotLeftAndMask32:
|
| - __ rlwinm(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
|
| - 31 - i.InputInt32(2), 31 - i.InputInt32(3), i.OutputRCBit());
|
| - break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_RotLeftAndClear64:
|
| - __ rldic(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
|
| - 63 - i.InputInt32(2), i.OutputRCBit());
|
| + case kS390_Not:
|
| + __ LoadRR(i.OutputRegister(), i.InputRegister(0));
|
| + __ NotP(i.OutputRegister());
|
| + break;
|
| + case kS390_RotLeftAndMask32:
|
| + if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
|
| + int shiftAmount = i.InputInt32(1);
|
| + int endBit = 63 - i.InputInt32(3);
|
| + int startBit = 63 - i.InputInt32(2);
|
| + __ rll(i.OutputRegister(), i.InputRegister(0), Operand(shiftAmount));
|
| + __ risbg(i.OutputRegister(), i.OutputRegister(), Operand(startBit),
|
| + Operand(endBit), Operand::Zero(), true);
|
| + } else {
|
| + UNIMPLEMENTED();
|
| + }
|
| break;
|
| - case kPPC_RotLeftAndClearLeft64:
|
| - __ rldicl(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
|
| - 63 - i.InputInt32(2), i.OutputRCBit());
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_RotLeftAndClear64:
|
| + UNIMPLEMENTED(); // Find correct instruction
|
| + break;
|
| + case kS390_RotLeftAndClearLeft64:
|
| + if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
|
| + int shiftAmount = i.InputInt32(1);
|
| + int endBit = 63;
|
| + int startBit = 63 - i.InputInt32(2);
|
| + __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
|
| + Operand(endBit), Operand(shiftAmount), true);
|
| + } else {
|
| + UNIMPLEMENTED();
|
| + }
|
| break;
|
| - case kPPC_RotLeftAndClearRight64:
|
| - __ rldicr(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1),
|
| - 63 - i.InputInt32(2), i.OutputRCBit());
|
| + case kS390_RotLeftAndClearRight64:
|
| + if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
|
| + int shiftAmount = i.InputInt32(1);
|
| + int endBit = 63 - i.InputInt32(2);
|
| + int startBit = 0;
|
| + __ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
|
| + Operand(endBit), Operand(shiftAmount), true);
|
| + } else {
|
| + UNIMPLEMENTED();
|
| + }
|
| break;
|
| #endif
|
| - case kPPC_Add:
|
| -#if V8_TARGET_ARCH_PPC64
|
| + case kS390_Add:
|
| +#if V8_TARGET_ARCH_S390X
|
| if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
|
| ASSEMBLE_ADD_WITH_OVERFLOW();
|
| } else {
|
| #endif
|
| - if (HasRegisterInput(instr, 1)) {
|
| - __ add(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - LeaveOE, i.OutputRCBit());
|
| - } else {
|
| - __ addi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - }
|
| -#if V8_TARGET_ARCH_PPC64
|
| + ASSEMBLE_BINOP(AddP, AddP);
|
| +#if V8_TARGET_ARCH_S390X
|
| }
|
| #endif
|
| break;
|
| - case kPPC_AddWithOverflow32:
|
| + case kS390_AddWithOverflow32:
|
| ASSEMBLE_ADD_WITH_OVERFLOW32();
|
| break;
|
| - case kPPC_AddDouble:
|
| - ASSEMBLE_FLOAT_BINOP_RC(fadd);
|
| + case kS390_AddFloat:
|
| + // Ensure we don't clobber right/InputReg(1)
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + ASSEMBLE_FLOAT_UNOP(aebr);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ aebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| + break;
|
| + case kS390_AddDouble:
|
| + // Ensure we don't clobber right/InputReg(1)
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + ASSEMBLE_FLOAT_UNOP(adbr);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ adbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| break;
|
| - case kPPC_Sub:
|
| -#if V8_TARGET_ARCH_PPC64
|
| + case kS390_Sub:
|
| +#if V8_TARGET_ARCH_S390X
|
| if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
|
| ASSEMBLE_SUB_WITH_OVERFLOW();
|
| } else {
|
| #endif
|
| - if (HasRegisterInput(instr, 1)) {
|
| - __ sub(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - LeaveOE, i.OutputRCBit());
|
| - } else {
|
| - __ subi(i.OutputRegister(), i.InputRegister(0), i.InputImmediate(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - }
|
| -#if V8_TARGET_ARCH_PPC64
|
| + ASSEMBLE_BINOP(SubP, SubP);
|
| +#if V8_TARGET_ARCH_S390X
|
| }
|
| #endif
|
| break;
|
| - case kPPC_SubWithOverflow32:
|
| + case kS390_SubWithOverflow32:
|
| ASSEMBLE_SUB_WITH_OVERFLOW32();
|
| break;
|
| - case kPPC_SubDouble:
|
| - ASSEMBLE_FLOAT_BINOP_RC(fsub);
|
| + case kS390_SubFloat:
|
| + // OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1)
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ sebr(i.OutputDoubleRegister(), kScratchDoubleReg);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) {
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + }
|
| + __ sebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| break;
|
| - case kPPC_Mul32:
|
| - __ mullw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - LeaveOE, i.OutputRCBit());
|
| + case kS390_SubDouble:
|
| + // OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1)
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ sdbr(i.OutputDoubleRegister(), kScratchDoubleReg);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0))) {
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + }
|
| + __ sdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Mul64:
|
| - __ mulld(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - LeaveOE, i.OutputRCBit());
|
| + case kS390_Mul32:
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Mul64:
|
| +#endif
|
| + __ Mul(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| + break;
|
| + case kS390_MulHigh32:
|
| + __ LoadRR(r1, i.InputRegister(0));
|
| + __ mr_z(r0, i.InputRegister(1));
|
| + __ LoadRR(i.OutputRegister(), r0);
|
| + break;
|
| + case kS390_MulHighU32:
|
| + __ LoadRR(r1, i.InputRegister(0));
|
| + __ mlr(r0, i.InputRegister(1));
|
| + __ LoadRR(i.OutputRegister(), r0);
|
| + break;
|
| + case kS390_MulFloat:
|
| + // Ensure we don't clobber right
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + ASSEMBLE_FLOAT_UNOP(meebr);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ meebr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| + break;
|
| + case kS390_MulDouble:
|
| + // Ensure we don't clobber right
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + ASSEMBLE_FLOAT_UNOP(mdbr);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ mdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| break;
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Div64:
|
| #endif
|
| - case kPPC_MulHigh32:
|
| - __ mulhw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| + case kS390_Div32:
|
| + __ LoadRR(r0, i.InputRegister(0));
|
| + __ srda(r0, Operand(32));
|
| + __ dr(r0, i.InputRegister(1));
|
| + __ ltr(i.OutputRegister(), r1);
|
| + break;
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_DivU64:
|
| + __ LoadRR(r1, i.InputRegister(0));
|
| + __ LoadImmP(r0, Operand::Zero());
|
| + __ dlgr(r0, i.InputRegister(1)); // R0:R1 = R1 / divisor -
|
| + __ ltgr(i.OutputRegister(), r1); // Copy remainder to output reg
|
| break;
|
| - case kPPC_MulHighU32:
|
| - __ mulhwu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
|
| - i.OutputRCBit());
|
| +#endif
|
| + case kS390_DivU32:
|
| + __ LoadRR(r0, i.InputRegister(0));
|
| + __ srdl(r0, Operand(32));
|
| + __ dlr(r0, i.InputRegister(1)); // R0:R1 = R1 / divisor -
|
| + __ ltr(i.OutputRegister(), r1); // Copy remainder to output reg
|
| + break;
|
| +
|
| + case kS390_DivFloat:
|
| + // InputDoubleRegister(1)=InputDoubleRegister(0)/InputDoubleRegister(1)
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ debr(i.OutputDoubleRegister(), kScratchDoubleReg);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ debr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| break;
|
| - case kPPC_MulDouble:
|
| - ASSEMBLE_FLOAT_BINOP_RC(fmul);
|
| + case kS390_DivDouble:
|
| + // InputDoubleRegister(1)=InputDoubleRegister(0)/InputDoubleRegister(1)
|
| + if (i.OutputDoubleRegister().is(i.InputDoubleRegister(1))) {
|
| + __ ldr(kScratchDoubleReg, i.InputDoubleRegister(1));
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ ddbr(i.OutputDoubleRegister(), kScratchDoubleReg);
|
| + } else {
|
| + if (!i.OutputDoubleRegister().is(i.InputDoubleRegister(0)))
|
| + __ ldr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + __ ddbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
| + }
|
| break;
|
| - case kPPC_Div32:
|
| - __ divw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_Mod32:
|
| + ASSEMBLE_MODULO(dr, srda);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Div64:
|
| - __ divd(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_ModU32:
|
| + ASSEMBLE_MODULO(dlr, srdl);
|
| break;
|
| -#endif
|
| - case kPPC_DivU32:
|
| - __ divwu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Mod64:
|
| + ASSEMBLE_MODULO(dr, srda);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_DivU64:
|
| - __ divdu(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_ModU64:
|
| + ASSEMBLE_MODULO(dlr, srdl);
|
| break;
|
| #endif
|
| - case kPPC_DivDouble:
|
| - ASSEMBLE_FLOAT_BINOP_RC(fdiv);
|
| + case kS390_AbsFloat:
|
| + __ lpebr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| break;
|
| - case kPPC_Mod32:
|
| - ASSEMBLE_MODULO(divw, mullw);
|
| + case kS390_SqrtFloat:
|
| + ASSEMBLE_FLOAT_UNOP(sqebr);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Mod64:
|
| - ASSEMBLE_MODULO(divd, mulld);
|
| + case kS390_FloorFloat:
|
| + // ASSEMBLE_FLOAT_UNOP_RC(frim);
|
| + __ FloatFloor32(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + kScratchReg);
|
| break;
|
| -#endif
|
| - case kPPC_ModU32:
|
| - ASSEMBLE_MODULO(divwu, mullw);
|
| + case kS390_CeilFloat:
|
| + __ FloatCeiling32(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + kScratchReg, kScratchDoubleReg);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_ModU64:
|
| - ASSEMBLE_MODULO(divdu, mulld);
|
| + case kS390_TruncateFloat:
|
| + __ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0);
|
| break;
|
| -#endif
|
| - case kPPC_ModDouble:
|
| - // TODO(bmeurer): We should really get rid of this special instruction,
|
| - // and generate a CallAddress instruction instead.
|
| + // Double operations
|
| + case kS390_ModDouble:
|
| ASSEMBLE_FLOAT_MODULO();
|
| break;
|
| - case kPPC_Neg:
|
| - __ neg(i.OutputRegister(), i.InputRegister(0), LeaveOE, i.OutputRCBit());
|
| - break;
|
| - case kPPC_MaxDouble:
|
| - ASSEMBLE_FLOAT_MAX(kScratchDoubleReg);
|
| - break;
|
| - case kPPC_MinDouble:
|
| - ASSEMBLE_FLOAT_MIN(kScratchDoubleReg);
|
| + case kS390_Neg:
|
| + __ LoadComplementRR(i.OutputRegister(), i.InputRegister(0));
|
| break;
|
| - case kPPC_AbsDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(fabs);
|
| + case kS390_MaxDouble:
|
| + ASSEMBLE_FLOAT_MAX(kScratchDoubleReg, kScratchReg);
|
| break;
|
| - case kPPC_SqrtDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(fsqrt);
|
| + case kS390_MinDouble:
|
| + ASSEMBLE_FLOAT_MIN(kScratchDoubleReg, kScratchReg);
|
| break;
|
| - case kPPC_FloorDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(frim);
|
| + case kS390_AbsDouble:
|
| + __ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| break;
|
| - case kPPC_CeilDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(frip);
|
| + case kS390_SqrtDouble:
|
| + ASSEMBLE_FLOAT_UNOP(sqdbr);
|
| break;
|
| - case kPPC_TruncateDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(friz);
|
| + case kS390_FloorDouble:
|
| + __ FloatFloor64(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + kScratchReg);
|
| break;
|
| - case kPPC_RoundDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(frin);
|
| + case kS390_CeilDouble:
|
| + __ FloatCeiling64(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + kScratchReg, kScratchDoubleReg);
|
| break;
|
| - case kPPC_NegDouble:
|
| - ASSEMBLE_FLOAT_UNOP_RC(fneg);
|
| + case kS390_TruncateDouble:
|
| + __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0);
|
| break;
|
| - case kPPC_Cntlz32:
|
| - __ cntlzw_(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_RoundDouble:
|
| + __ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
|
| + v8::internal::Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Cntlz64:
|
| - __ cntlzd_(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_NegDouble:
|
| + ASSEMBLE_FLOAT_UNOP(lcdbr);
|
| break;
|
| + case kS390_Cntlz32: {
|
| + __ llgfr(i.OutputRegister(), i.InputRegister(0));
|
| + __ flogr(r0, i.OutputRegister());
|
| + __ LoadRR(i.OutputRegister(), r0);
|
| + __ SubP(i.OutputRegister(), Operand(32));
|
| + } break;
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Cntlz64: {
|
| + __ flogr(r0, i.InputRegister(0));
|
| + __ LoadRR(i.OutputRegister(), r0);
|
| + } break;
|
| #endif
|
| - case kPPC_Popcnt32:
|
| - __ popcntw(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_Popcnt32:
|
| + __ Popcnt32(i.OutputRegister(), i.InputRegister(0));
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Popcnt64:
|
| - __ popcntd(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Popcnt64:
|
| + __ Popcnt64(i.OutputRegister(), i.InputRegister(0));
|
| break;
|
| #endif
|
| - case kPPC_Cmp32:
|
| - ASSEMBLE_COMPARE(cmpw, cmplw);
|
| + case kS390_Cmp32:
|
| + ASSEMBLE_COMPARE(Cmp32, CmpLogical32);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Cmp64:
|
| - ASSEMBLE_COMPARE(cmp, cmpl);
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Cmp64:
|
| + ASSEMBLE_COMPARE(CmpP, CmpLogicalP);
|
| break;
|
| #endif
|
| - case kPPC_CmpDouble:
|
| - ASSEMBLE_FLOAT_COMPARE(fcmpu);
|
| + case kS390_CmpFloat:
|
| + __ cebr(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
|
| break;
|
| - case kPPC_Tst32:
|
| + case kS390_CmpDouble:
|
| + __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
|
| + break;
|
| + case kS390_Tst32:
|
| if (HasRegisterInput(instr, 1)) {
|
| - __ and_(r0, i.InputRegister(0), i.InputRegister(1), i.OutputRCBit());
|
| + __ AndP(r0, i.InputRegister(0), i.InputRegister(1));
|
| } else {
|
| - __ andi(r0, i.InputRegister(0), i.InputImmediate(1));
|
| + __ AndP(r0, i.InputRegister(0), i.InputImmediate(1));
|
| }
|
| -#if V8_TARGET_ARCH_PPC64
|
| - __ extsw(r0, r0, i.OutputRCBit());
|
| +#if V8_TARGET_ARCH_S390X
|
| + // TODO(john.yan): use ltgfr here.
|
| + __ lgfr(r0, r0);
|
| + __ LoadAndTestP(r0, r0);
|
| #endif
|
| - DCHECK_EQ(SetRC, i.OutputRCBit());
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_Tst64:
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Tst64:
|
| if (HasRegisterInput(instr, 1)) {
|
| - __ and_(r0, i.InputRegister(0), i.InputRegister(1), i.OutputRCBit());
|
| + __ AndP(r0, i.InputRegister(0), i.InputRegister(1));
|
| } else {
|
| - __ andi(r0, i.InputRegister(0), i.InputImmediate(1));
|
| + __ AndP(r0, i.InputRegister(0), i.InputImmediate(1));
|
| }
|
| - DCHECK_EQ(SetRC, i.OutputRCBit());
|
| break;
|
| #endif
|
| - case kPPC_Push:
|
| + case kS390_Push:
|
| if (instr->InputAt(0)->IsDoubleRegister()) {
|
| - __ stfdu(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
|
| + __ StoreDouble(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
|
| + __ lay(sp, MemOperand(sp, -kDoubleSize));
|
| frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
|
| } else {
|
| __ Push(i.InputRegister(0));
|
| frame_access_state()->IncreaseSPDelta(1);
|
| }
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_PushFrame: {
|
| + case kS390_PushFrame: {
|
| int num_slots = i.InputInt32(1);
|
| if (instr->InputAt(0)->IsDoubleRegister()) {
|
| - __ stfdu(i.InputDoubleRegister(0),
|
| - MemOperand(sp, -num_slots * kPointerSize));
|
| + __ StoreDouble(i.InputDoubleRegister(0),
|
| + MemOperand(sp, -num_slots * kPointerSize));
|
| } else {
|
| - __ StorePU(i.InputRegister(0),
|
| - MemOperand(sp, -num_slots * kPointerSize));
|
| + __ StoreP(i.InputRegister(0),
|
| + MemOperand(sp, -num_slots * kPointerSize));
|
| }
|
| + __ lay(sp, MemOperand(sp, -num_slots * kPointerSize));
|
| break;
|
| }
|
| - case kPPC_StoreToStackSlot: {
|
| + case kS390_StoreToStackSlot: {
|
| int slot = i.InputInt32(1);
|
| if (instr->InputAt(0)->IsDoubleRegister()) {
|
| - __ stfd(i.InputDoubleRegister(0), MemOperand(sp, slot * kPointerSize));
|
| + __ StoreDouble(i.InputDoubleRegister(0),
|
| + MemOperand(sp, slot * kPointerSize));
|
| } else {
|
| __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
|
| }
|
| break;
|
| }
|
| - case kPPC_ExtendSignWord8:
|
| - __ extsb(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_ExtendSignWord8:
|
| +#if V8_TARGET_ARCH_S390X
|
| + __ lgbr(i.OutputRegister(), i.InputRegister(0));
|
| +#else
|
| + __ lbr(i.OutputRegister(), i.InputRegister(0));
|
| +#endif
|
| break;
|
| - case kPPC_ExtendSignWord16:
|
| - __ extsh(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_ExtendSignWord16:
|
| +#if V8_TARGET_ARCH_S390X
|
| + __ lghr(i.OutputRegister(), i.InputRegister(0));
|
| +#else
|
| + __ lhr(i.OutputRegister(), i.InputRegister(0));
|
| +#endif
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_ExtendSignWord32:
|
| - __ extsw(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_ExtendSignWord32:
|
| + __ lgfr(i.OutputRegister(), i.InputRegister(0));
|
| break;
|
| - case kPPC_Uint32ToUint64:
|
| + case kS390_Uint32ToUint64:
|
| // Zero extend
|
| - __ clrldi(i.OutputRegister(), i.InputRegister(0), Operand(32));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + __ llgfr(i.OutputRegister(), i.InputRegister(0));
|
| break;
|
| - case kPPC_Int64ToInt32:
|
| - __ extsw(i.OutputRegister(), i.InputRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| + case kS390_Int64ToInt32:
|
| + // sign extend
|
| + __ lgfr(i.OutputRegister(), i.InputRegister(0));
|
| break;
|
| - case kPPC_Int64ToFloat32:
|
| + case kS390_Int64ToFloat32:
|
| __ ConvertInt64ToFloat(i.InputRegister(0), i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_Int64ToDouble:
|
| + case kS390_Int64ToDouble:
|
| __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_Uint64ToFloat32:
|
| + case kS390_Uint64ToFloat32:
|
| __ ConvertUnsignedInt64ToFloat(i.InputRegister(0),
|
| i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_Uint64ToDouble:
|
| + case kS390_Uint64ToDouble:
|
| __ ConvertUnsignedInt64ToDouble(i.InputRegister(0),
|
| i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| #endif
|
| - case kPPC_Int32ToFloat32:
|
| + case kS390_Int32ToFloat32:
|
| __ ConvertIntToFloat(i.InputRegister(0), i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_Int32ToDouble:
|
| + case kS390_Int32ToDouble:
|
| __ ConvertIntToDouble(i.InputRegister(0), i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_Uint32ToFloat32:
|
| + case kS390_Uint32ToFloat32:
|
| __ ConvertUnsignedIntToFloat(i.InputRegister(0),
|
| i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_Uint32ToDouble:
|
| + case kS390_Uint32ToDouble:
|
| __ ConvertUnsignedIntToDouble(i.InputRegister(0),
|
| i.OutputDoubleRegister());
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_DoubleToInt32:
|
| - case kPPC_DoubleToUint32:
|
| - case kPPC_DoubleToInt64: {
|
| -#if V8_TARGET_ARCH_PPC64
|
| + case kS390_DoubleToInt32:
|
| + case kS390_DoubleToUint32:
|
| + case kS390_DoubleToInt64: {
|
| +#if V8_TARGET_ARCH_S390X
|
| bool check_conversion =
|
| - (opcode == kPPC_DoubleToInt64 && i.OutputCount() > 1);
|
| - if (check_conversion) {
|
| - __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit
|
| - }
|
| + (opcode == kS390_DoubleToInt64 && i.OutputCount() > 1);
|
| #endif
|
| __ ConvertDoubleToInt64(i.InputDoubleRegister(0),
|
| -#if !V8_TARGET_ARCH_PPC64
|
| +#if !V8_TARGET_ARCH_S390X
|
| kScratchReg,
|
| #endif
|
| i.OutputRegister(0), kScratchDoubleReg);
|
| -#if V8_TARGET_ARCH_PPC64
|
| +#if V8_TARGET_ARCH_S390X
|
| if (check_conversion) {
|
| - // Set 2nd output to zero if conversion fails.
|
| - CRegister cr = cr7;
|
| - int crbit = v8::internal::Assembler::encode_crbit(
|
| - cr, static_cast<CRBit>(VXCVI % CRWIDTH));
|
| - __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7
|
| - if (CpuFeatures::IsSupported(ISELECT)) {
|
| - __ li(i.OutputRegister(1), Operand(1));
|
| - __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit);
|
| - } else {
|
| - __ li(i.OutputRegister(1), Operand::Zero());
|
| - __ bc(v8::internal::Assembler::kInstrSize * 2, BT, crbit);
|
| - __ li(i.OutputRegister(1), Operand(1));
|
| - }
|
| + Label conversion_done;
|
| + __ LoadImmP(i.OutputRegister(1), Operand::Zero());
|
| + __ b(Condition(1), &conversion_done); // special case
|
| + __ LoadImmP(i.OutputRegister(1), Operand(1));
|
| + __ bind(&conversion_done);
|
| }
|
| #endif
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| }
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_DoubleToUint64: {
|
| + case kS390_Float32ToInt32: {
|
| bool check_conversion = (i.OutputCount() > 1);
|
| + __ ConvertFloat32ToInt32(i.InputDoubleRegister(0), i.OutputRegister(0),
|
| + kScratchDoubleReg);
|
| if (check_conversion) {
|
| - __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit
|
| + Label conversion_done;
|
| + __ LoadImmP(i.OutputRegister(1), Operand::Zero());
|
| + __ b(Condition(1), &conversion_done); // special case
|
| + __ LoadImmP(i.OutputRegister(1), Operand(1));
|
| + __ bind(&conversion_done);
|
| }
|
| + break;
|
| + }
|
| + case kS390_Float32ToUint32: {
|
| + bool check_conversion = (i.OutputCount() > 1);
|
| + __ ConvertFloat32ToUnsignedInt32(i.InputDoubleRegister(0),
|
| + i.OutputRegister(0), kScratchDoubleReg);
|
| + if (check_conversion) {
|
| + Label conversion_done;
|
| + __ LoadImmP(i.OutputRegister(1), Operand::Zero());
|
| + __ b(Condition(1), &conversion_done); // special case
|
| + __ LoadImmP(i.OutputRegister(1), Operand(1));
|
| + __ bind(&conversion_done);
|
| + }
|
| + break;
|
| + }
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_Float32ToUint64: {
|
| + bool check_conversion = (i.OutputCount() > 1);
|
| + __ ConvertFloat32ToUnsignedInt64(i.InputDoubleRegister(0),
|
| + i.OutputRegister(0), kScratchDoubleReg);
|
| + if (check_conversion) {
|
| + Label conversion_done;
|
| + __ LoadImmP(i.OutputRegister(1), Operand::Zero());
|
| + __ b(Condition(1), &conversion_done); // special case
|
| + __ LoadImmP(i.OutputRegister(1), Operand(1));
|
| + __ bind(&conversion_done);
|
| + }
|
| + break;
|
| + }
|
| +#endif
|
| + case kS390_Float32ToInt64: {
|
| +#if V8_TARGET_ARCH_S390X
|
| + bool check_conversion =
|
| + (opcode == kS390_Float32ToInt64 && i.OutputCount() > 1);
|
| +#endif
|
| + __ ConvertFloat32ToInt64(i.InputDoubleRegister(0),
|
| +#if !V8_TARGET_ARCH_S390X
|
| + kScratchReg,
|
| +#endif
|
| + i.OutputRegister(0), kScratchDoubleReg);
|
| +#if V8_TARGET_ARCH_S390X
|
| + if (check_conversion) {
|
| + Label conversion_done;
|
| + __ LoadImmP(i.OutputRegister(1), Operand::Zero());
|
| + __ b(Condition(1), &conversion_done); // special case
|
| + __ LoadImmP(i.OutputRegister(1), Operand(1));
|
| + __ bind(&conversion_done);
|
| + }
|
| +#endif
|
| + break;
|
| + }
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_DoubleToUint64: {
|
| + bool check_conversion = (i.OutputCount() > 1);
|
| __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0),
|
| i.OutputRegister(0), kScratchDoubleReg);
|
| if (check_conversion) {
|
| - // Set 2nd output to zero if conversion fails.
|
| - CRegister cr = cr7;
|
| - int crbit = v8::internal::Assembler::encode_crbit(
|
| - cr, static_cast<CRBit>(VXCVI % CRWIDTH));
|
| - __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7
|
| - if (CpuFeatures::IsSupported(ISELECT)) {
|
| - __ li(i.OutputRegister(1), Operand(1));
|
| - __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit);
|
| - } else {
|
| - __ li(i.OutputRegister(1), Operand::Zero());
|
| - __ bc(v8::internal::Assembler::kInstrSize * 2, BT, crbit);
|
| - __ li(i.OutputRegister(1), Operand(1));
|
| - }
|
| + Label conversion_done;
|
| + __ LoadImmP(i.OutputRegister(1), Operand::Zero());
|
| + __ b(Condition(1), &conversion_done); // special case
|
| + __ LoadImmP(i.OutputRegister(1), Operand(1));
|
| + __ bind(&conversion_done);
|
| }
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| }
|
| #endif
|
| - case kPPC_DoubleToFloat32:
|
| - ASSEMBLE_FLOAT_UNOP_RC(frsp);
|
| - break;
|
| - case kPPC_Float32ToDouble:
|
| - // Nothing to do.
|
| - __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - break;
|
| - case kPPC_DoubleExtractLowWord32:
|
| - __ MovDoubleLowToInt(i.OutputRegister(), i.InputDoubleRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - break;
|
| - case kPPC_DoubleExtractHighWord32:
|
| - __ MovDoubleHighToInt(i.OutputRegister(), i.InputDoubleRegister(0));
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - break;
|
| - case kPPC_DoubleInsertLowWord32:
|
| - __ InsertDoubleLow(i.OutputDoubleRegister(), i.InputRegister(1), r0);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - break;
|
| - case kPPC_DoubleInsertHighWord32:
|
| - __ InsertDoubleHigh(i.OutputDoubleRegister(), i.InputRegister(1), r0);
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| - break;
|
| - case kPPC_DoubleConstruct:
|
| -#if V8_TARGET_ARCH_PPC64
|
| - __ MovInt64ComponentsToDouble(i.OutputDoubleRegister(),
|
| - i.InputRegister(0), i.InputRegister(1), r0);
|
| + case kS390_DoubleToFloat32:
|
| + __ ledbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + break;
|
| + case kS390_Float32ToDouble:
|
| + __ ldebr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
| + break;
|
| + case kS390_DoubleExtractLowWord32:
|
| + // TODO(john.yan): this can cause problem when interrupting,
|
| + // use freg->greg instruction
|
| + __ stdy(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
|
| + __ LoadlW(i.OutputRegister(),
|
| + MemOperand(sp, -kDoubleSize + Register::kMantissaOffset));
|
| + break;
|
| + case kS390_DoubleExtractHighWord32:
|
| + // TODO(john.yan): this can cause problem when interrupting,
|
| + // use freg->greg instruction
|
| + __ stdy(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
|
| + __ LoadlW(i.OutputRegister(),
|
| + MemOperand(sp, -kDoubleSize + Register::kExponentOffset));
|
| + break;
|
| + case kS390_DoubleInsertLowWord32:
|
| + __ InsertDoubleLow(i.OutputDoubleRegister(), i.InputRegister(1));
|
| + break;
|
| + case kS390_DoubleInsertHighWord32:
|
| + __ InsertDoubleHigh(i.OutputDoubleRegister(), i.InputRegister(1));
|
| + break;
|
| + case kS390_DoubleConstruct:
|
| +// TODO(john.yan): this can cause problem when interrupting,
|
| +// use greg->freg instruction
|
| +#if V8_TARGET_LITTLE_ENDIAN
|
| + __ StoreW(i.InputRegister(0), MemOperand(sp, -kDoubleSize / 2));
|
| + __ StoreW(i.InputRegister(1), MemOperand(sp, -kDoubleSize));
|
| +#else
|
| + __ StoreW(i.InputRegister(1), MemOperand(sp, -kDoubleSize / 2));
|
| + __ StoreW(i.InputRegister(0), MemOperand(sp, -kDoubleSize));
|
| +#endif
|
| + __ ldy(i.OutputDoubleRegister(), MemOperand(sp, -kDoubleSize));
|
| + break;
|
| + case kS390_LoadWordS8:
|
| + ASSEMBLE_LOAD_INTEGER(LoadlB);
|
| +#if V8_TARGET_ARCH_S390X
|
| + __ lgbr(i.OutputRegister(), i.OutputRegister());
|
| #else
|
| - __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0),
|
| - i.InputRegister(1));
|
| + __ lbr(i.OutputRegister(), i.OutputRegister());
|
| #endif
|
| - DCHECK_EQ(LeaveRC, i.OutputRCBit());
|
| break;
|
| - case kPPC_BitcastFloat32ToInt32:
|
| + case kS390_BitcastFloat32ToInt32:
|
| __ MovFloatToInt(i.OutputRegister(), i.InputDoubleRegister(0));
|
| break;
|
| - case kPPC_BitcastInt32ToFloat32:
|
| + case kS390_BitcastInt32ToFloat32:
|
| __ MovIntToFloat(i.OutputDoubleRegister(), i.InputRegister(0));
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_BitcastDoubleToInt64:
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_BitcastDoubleToInt64:
|
| __ MovDoubleToInt64(i.OutputRegister(), i.InputDoubleRegister(0));
|
| break;
|
| - case kPPC_BitcastInt64ToDouble:
|
| + case kS390_BitcastInt64ToDouble:
|
| __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0));
|
| break;
|
| #endif
|
| - case kPPC_LoadWordU8:
|
| - ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
|
| - break;
|
| - case kPPC_LoadWordS8:
|
| - ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
|
| - __ extsb(i.OutputRegister(), i.OutputRegister());
|
| + case kS390_LoadWordU8:
|
| + ASSEMBLE_LOAD_INTEGER(LoadlB);
|
| break;
|
| - case kPPC_LoadWordU16:
|
| - ASSEMBLE_LOAD_INTEGER(lhz, lhzx);
|
| + case kS390_LoadWordU16:
|
| + ASSEMBLE_LOAD_INTEGER(LoadLogicalHalfWordP);
|
| break;
|
| - case kPPC_LoadWordS16:
|
| - ASSEMBLE_LOAD_INTEGER(lha, lhax);
|
| + case kS390_LoadWordS16:
|
| + ASSEMBLE_LOAD_INTEGER(LoadHalfWordP);
|
| break;
|
| - case kPPC_LoadWordS32:
|
| - ASSEMBLE_LOAD_INTEGER(lwa, lwax);
|
| + case kS390_LoadWordS32:
|
| + ASSEMBLE_LOAD_INTEGER(LoadW);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_LoadWord64:
|
| - ASSEMBLE_LOAD_INTEGER(ld, ldx);
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_LoadWord64:
|
| + ASSEMBLE_LOAD_INTEGER(lg);
|
| break;
|
| #endif
|
| - case kPPC_LoadFloat32:
|
| - ASSEMBLE_LOAD_FLOAT(lfs, lfsx);
|
| + case kS390_LoadFloat32:
|
| + ASSEMBLE_LOAD_FLOAT(LoadFloat32);
|
| break;
|
| - case kPPC_LoadDouble:
|
| - ASSEMBLE_LOAD_FLOAT(lfd, lfdx);
|
| + case kS390_LoadDouble:
|
| + ASSEMBLE_LOAD_FLOAT(LoadDouble);
|
| break;
|
| - case kPPC_StoreWord8:
|
| - ASSEMBLE_STORE_INTEGER(stb, stbx);
|
| + case kS390_StoreWord8:
|
| + ASSEMBLE_STORE_INTEGER(StoreByte);
|
| break;
|
| - case kPPC_StoreWord16:
|
| - ASSEMBLE_STORE_INTEGER(sth, sthx);
|
| + case kS390_StoreWord16:
|
| + ASSEMBLE_STORE_INTEGER(StoreHalfWord);
|
| break;
|
| - case kPPC_StoreWord32:
|
| - ASSEMBLE_STORE_INTEGER(stw, stwx);
|
| + case kS390_StoreWord32:
|
| + ASSEMBLE_STORE_INTEGER(StoreW);
|
| break;
|
| -#if V8_TARGET_ARCH_PPC64
|
| - case kPPC_StoreWord64:
|
| - ASSEMBLE_STORE_INTEGER(std, stdx);
|
| +#if V8_TARGET_ARCH_S390X
|
| + case kS390_StoreWord64:
|
| + ASSEMBLE_STORE_INTEGER(StoreP);
|
| break;
|
| #endif
|
| - case kPPC_StoreFloat32:
|
| + case kS390_StoreFloat32:
|
| ASSEMBLE_STORE_FLOAT32();
|
| break;
|
| - case kPPC_StoreDouble:
|
| + case kS390_StoreDouble:
|
| ASSEMBLE_STORE_DOUBLE();
|
| break;
|
| case kCheckedLoadInt8:
|
| - ASSEMBLE_CHECKED_LOAD_INTEGER(lbz, lbzx);
|
| - __ extsb(i.OutputRegister(), i.OutputRegister());
|
| + ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlB);
|
| +#if V8_TARGET_ARCH_S390X
|
| + __ lgbr(i.OutputRegister(), i.OutputRegister());
|
| +#else
|
| + __ lbr(i.OutputRegister(), i.OutputRegister());
|
| +#endif
|
| break;
|
| case kCheckedLoadUint8:
|
| - ASSEMBLE_CHECKED_LOAD_INTEGER(lbz, lbzx);
|
| + ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlB);
|
| break;
|
| case kCheckedLoadInt16:
|
| - ASSEMBLE_CHECKED_LOAD_INTEGER(lha, lhax);
|
| + ASSEMBLE_CHECKED_LOAD_INTEGER(LoadHalfWordP);
|
| break;
|
| case kCheckedLoadUint16:
|
| - ASSEMBLE_CHECKED_LOAD_INTEGER(lhz, lhzx);
|
| + ASSEMBLE_CHECKED_LOAD_INTEGER(LoadLogicalHalfWordP);
|
| break;
|
| case kCheckedLoadWord32:
|
| - ASSEMBLE_CHECKED_LOAD_INTEGER(lwa, lwax);
|
| + ASSEMBLE_CHECKED_LOAD_INTEGER(LoadW);
|
| break;
|
| case kCheckedLoadWord64:
|
| -#if V8_TARGET_ARCH_PPC64
|
| - ASSEMBLE_CHECKED_LOAD_INTEGER(ld, ldx);
|
| +#if V8_TARGET_ARCH_S390X
|
| + ASSEMBLE_CHECKED_LOAD_INTEGER(LoadP);
|
| #else
|
| UNREACHABLE();
|
| #endif
|
| break;
|
| case kCheckedLoadFloat32:
|
| - ASSEMBLE_CHECKED_LOAD_FLOAT(lfs, lfsx, 32);
|
| + ASSEMBLE_CHECKED_LOAD_FLOAT(LoadFloat32, 32);
|
| break;
|
| case kCheckedLoadFloat64:
|
| - ASSEMBLE_CHECKED_LOAD_FLOAT(lfd, lfdx, 64);
|
| + ASSEMBLE_CHECKED_LOAD_FLOAT(LoadDouble, 64);
|
| break;
|
| case kCheckedStoreWord8:
|
| - ASSEMBLE_CHECKED_STORE_INTEGER(stb, stbx);
|
| + ASSEMBLE_CHECKED_STORE_INTEGER(StoreByte);
|
| break;
|
| case kCheckedStoreWord16:
|
| - ASSEMBLE_CHECKED_STORE_INTEGER(sth, sthx);
|
| + ASSEMBLE_CHECKED_STORE_INTEGER(StoreHalfWord);
|
| break;
|
| case kCheckedStoreWord32:
|
| - ASSEMBLE_CHECKED_STORE_INTEGER(stw, stwx);
|
| + ASSEMBLE_CHECKED_STORE_INTEGER(StoreW);
|
| break;
|
| case kCheckedStoreWord64:
|
| -#if V8_TARGET_ARCH_PPC64
|
| - ASSEMBLE_CHECKED_STORE_INTEGER(std, stdx);
|
| +#if V8_TARGET_ARCH_S390X
|
| + ASSEMBLE_CHECKED_STORE_INTEGER(StoreP);
|
| #else
|
| UNREACHABLE();
|
| #endif
|
| @@ -1468,108 +1520,107 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
| }
|
| } // NOLINT(readability/fn_size)
|
|
|
| -
|
| // Assembles branches after an instruction.
|
| void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| - PPCOperandConverter i(this, instr);
|
| + S390OperandConverter i(this, instr);
|
| Label* tlabel = branch->true_label;
|
| Label* flabel = branch->false_label;
|
| ArchOpcode op = instr->arch_opcode();
|
| FlagsCondition condition = branch->condition;
|
| - CRegister cr = cr0;
|
|
|
| Condition cond = FlagsConditionToCondition(condition, op);
|
| - if (op == kPPC_CmpDouble) {
|
| + if (op == kS390_CmpDouble) {
|
| // check for unordered if necessary
|
| - if (cond == le) {
|
| - __ bunordered(flabel, cr);
|
| - // Unnecessary for eq/lt since only FU bit will be set.
|
| - } else if (cond == gt) {
|
| - __ bunordered(tlabel, cr);
|
| - // Unnecessary for ne/ge since only FU bit will be set.
|
| + // Branching to flabel/tlabel according to what's expected by tests
|
| + if (cond == le || cond == eq || cond == lt) {
|
| + __ bunordered(flabel);
|
| + } else if (cond == gt || cond == ne || cond == ge) {
|
| + __ bunordered(tlabel);
|
| }
|
| }
|
| - __ b(cond, tlabel, cr);
|
| + __ b(cond, tlabel);
|
| if (!branch->fallthru) __ b(flabel); // no fallthru to flabel.
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleArchJump(RpoNumber target) {
|
| if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target));
|
| }
|
|
|
| -
|
| // Assembles boolean materializations after an instruction.
|
| void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
| FlagsCondition condition) {
|
| - PPCOperandConverter i(this, instr);
|
| + S390OperandConverter i(this, instr);
|
| Label done;
|
| ArchOpcode op = instr->arch_opcode();
|
| - CRegister cr = cr0;
|
| - int reg_value = -1;
|
| + bool check_unordered = (op == kS390_CmpDouble || kS390_CmpFloat);
|
| +
|
| + // Overflow checked for add/sub only.
|
| + DCHECK((condition != kOverflow && condition != kNotOverflow) ||
|
| + (op == kS390_AddWithOverflow32 || op == kS390_SubWithOverflow32));
|
|
|
| // Materialize a full 32-bit 1 or 0 value. The result register is always the
|
| // last output of the instruction.
|
| DCHECK_NE(0u, instr->OutputCount());
|
| Register reg = i.OutputRegister(instr->OutputCount() - 1);
|
| -
|
| Condition cond = FlagsConditionToCondition(condition, op);
|
| - if (op == kPPC_CmpDouble) {
|
| - // check for unordered if necessary
|
| - if (cond == le) {
|
| - reg_value = 0;
|
| - __ li(reg, Operand::Zero());
|
| - __ bunordered(&done, cr);
|
| - } else if (cond == gt) {
|
| - reg_value = 1;
|
| - __ li(reg, Operand(1));
|
| - __ bunordered(&done, cr);
|
| - }
|
| - // Unnecessary for eq/lt & ne/ge since only FU bit will be set.
|
| - }
|
| -
|
| - if (CpuFeatures::IsSupported(ISELECT)) {
|
| - switch (cond) {
|
| - case eq:
|
| - case lt:
|
| - case gt:
|
| - if (reg_value != 1) __ li(reg, Operand(1));
|
| - __ li(kScratchReg, Operand::Zero());
|
| - __ isel(cond, reg, reg, kScratchReg, cr);
|
| - break;
|
| - case ne:
|
| - case ge:
|
| - case le:
|
| - if (reg_value != 1) __ li(reg, Operand(1));
|
| - // r0 implies logical zero in this form
|
| - __ isel(NegateCondition(cond), reg, r0, reg, cr);
|
| - break;
|
| + switch (cond) {
|
| + case ne:
|
| + case ge:
|
| + case gt:
|
| + if (check_unordered) {
|
| + __ LoadImmP(reg, Operand(1));
|
| + __ LoadImmP(kScratchReg, Operand::Zero());
|
| + __ bunordered(&done);
|
| + Label cond_true;
|
| + __ b(cond, &cond_true, Label::kNear);
|
| + __ LoadRR(reg, kScratchReg);
|
| + __ bind(&cond_true);
|
| + } else {
|
| + Label cond_true, done_here;
|
| + __ LoadImmP(reg, Operand(1));
|
| + __ b(cond, &cond_true, Label::kNear);
|
| + __ LoadImmP(reg, Operand::Zero());
|
| + __ bind(&cond_true);
|
| + }
|
| + break;
|
| + case eq:
|
| + case lt:
|
| + case le:
|
| + if (check_unordered) {
|
| + __ LoadImmP(reg, Operand::Zero());
|
| + __ LoadImmP(kScratchReg, Operand(1));
|
| + __ bunordered(&done);
|
| + Label cond_false;
|
| + __ b(NegateCondition(cond), &cond_false, Label::kNear);
|
| + __ LoadRR(reg, kScratchReg);
|
| + __ bind(&cond_false);
|
| + } else {
|
| + __ LoadImmP(reg, Operand::Zero());
|
| + Label cond_false;
|
| + __ b(NegateCondition(cond), &cond_false, Label::kNear);
|
| + __ LoadImmP(reg, Operand(1));
|
| + __ bind(&cond_false);
|
| + }
|
| + break;
|
| default:
|
| UNREACHABLE();
|
| break;
|
| - }
|
| - } else {
|
| - if (reg_value != 0) __ li(reg, Operand::Zero());
|
| - __ b(NegateCondition(cond), &done, cr);
|
| - __ li(reg, Operand(1));
|
| }
|
| __ bind(&done);
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
|
| - PPCOperandConverter i(this, instr);
|
| + S390OperandConverter i(this, instr);
|
| Register input = i.InputRegister(0);
|
| for (size_t index = 2; index < instr->InputCount(); index += 2) {
|
| - __ Cmpi(input, Operand(i.InputInt32(index + 0)), r0);
|
| + __ CmpP(input, Operand(i.InputInt32(index + 0)));
|
| __ beq(GetLabel(i.InputRpo(index + 1)));
|
| }
|
| AssembleArchJump(i.InputRpo(1));
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
|
| - PPCOperandConverter i(this, instr);
|
| + S390OperandConverter i(this, instr);
|
| Register input = i.InputRegister(0);
|
| int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2);
|
| Label** cases = zone()->NewArray<Label*>(case_count);
|
| @@ -1577,15 +1628,14 @@ void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
|
| cases[index] = GetLabel(i.InputRpo(index + 2));
|
| }
|
| Label* const table = AddJumpTable(cases, case_count);
|
| - __ Cmpli(input, Operand(case_count), r0);
|
| + __ CmpLogicalP(input, Operand(case_count));
|
| __ bge(GetLabel(i.InputRpo(1)));
|
| - __ mov_label_addr(kScratchReg, table);
|
| - __ ShiftLeftImm(r0, input, Operand(kPointerSizeLog2));
|
| - __ LoadPX(kScratchReg, MemOperand(kScratchReg, r0));
|
| + __ larl(kScratchReg, table);
|
| + __ ShiftLeftP(r1, input, Operand(kPointerSizeLog2));
|
| + __ LoadP(kScratchReg, MemOperand(kScratchReg, r1));
|
| __ Jump(kScratchReg);
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleDeoptimizerCall(
|
| int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
|
| Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
|
| @@ -1596,20 +1646,12 @@ void CodeGenerator::AssembleDeoptimizerCall(
|
| __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
|
| }
|
|
|
| -
|
| void CodeGenerator::AssemblePrologue() {
|
| CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
|
| +
|
| if (descriptor->IsCFunctionCall()) {
|
| - __ function_descriptor();
|
| - __ mflr(r0);
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| - __ Push(r0, fp, kConstantPoolRegister);
|
| - // Adjust FP to point to saved FP.
|
| - __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
|
| - } else {
|
| - __ Push(r0, fp);
|
| - __ mr(fp, sp);
|
| - }
|
| + __ Push(r14, fp);
|
| + __ LoadRR(fp, sp);
|
| } else if (descriptor->IsJSFunctionCall()) {
|
| __ Prologue(this->info()->GeneratePreagedPrologue(), ip);
|
| } else if (frame()->needs_frame()) {
|
| @@ -1643,7 +1685,7 @@ void CodeGenerator::AssemblePrologue() {
|
| stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
|
| }
|
| if (stack_shrink_slots > 0) {
|
| - __ Add(sp, sp, -stack_shrink_slots * kPointerSize, r0);
|
| + __ lay(sp, MemOperand(sp, -stack_shrink_slots * kPointerSize));
|
| }
|
|
|
| // Save callee-saved Double registers.
|
| @@ -1656,10 +1698,7 @@ void CodeGenerator::AssemblePrologue() {
|
| }
|
|
|
| // Save callee-saved registers.
|
| - const RegList saves =
|
| - FLAG_enable_embedded_constant_pool
|
| - ? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit()
|
| - : descriptor->CalleeSavedRegisters();
|
| + const RegList saves = descriptor->CalleeSavedRegisters();
|
| if (saves != 0) {
|
| __ MultiPush(saves);
|
| // register save area does not include the fp or constant pool pointer.
|
| @@ -1670,16 +1709,12 @@ void CodeGenerator::AssemblePrologue() {
|
| }
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleReturn() {
|
| CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
|
| int pop_count = static_cast<int>(descriptor->StackParameterCount());
|
|
|
| // Restore registers.
|
| - const RegList saves =
|
| - FLAG_enable_embedded_constant_pool
|
| - ? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit()
|
| - : descriptor->CalleeSavedRegisters();
|
| + const RegList saves = descriptor->CalleeSavedRegisters();
|
| if (saves != 0) {
|
| __ MultiPop(saves);
|
| }
|
| @@ -1707,10 +1742,9 @@ void CodeGenerator::AssembleReturn() {
|
| __ Ret();
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleMove(InstructionOperand* source,
|
| InstructionOperand* destination) {
|
| - PPCOperandConverter g(this, nullptr);
|
| + S390OperandConverter g(this, nullptr);
|
| // Dispatch on the source and destination operand kinds. Not all
|
| // combinations are possible.
|
| if (source->IsRegister()) {
|
| @@ -1719,17 +1753,17 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
| if (destination->IsRegister()) {
|
| __ Move(g.ToRegister(destination), src);
|
| } else {
|
| - __ StoreP(src, g.ToMemOperand(destination), r0);
|
| + __ StoreP(src, g.ToMemOperand(destination));
|
| }
|
| } else if (source->IsStackSlot()) {
|
| DCHECK(destination->IsRegister() || destination->IsStackSlot());
|
| MemOperand src = g.ToMemOperand(source);
|
| if (destination->IsRegister()) {
|
| - __ LoadP(g.ToRegister(destination), src, r0);
|
| + __ LoadP(g.ToRegister(destination), src);
|
| } else {
|
| Register temp = kScratchReg;
|
| __ LoadP(temp, src, r0);
|
| - __ StoreP(temp, g.ToMemOperand(destination), r0);
|
| + __ StoreP(temp, g.ToMemOperand(destination));
|
| }
|
| } else if (source->IsConstant()) {
|
| Constant src = g.ToConstant(source);
|
| @@ -1768,7 +1802,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
| break;
|
| }
|
| case Constant::kRpoNumber:
|
| - UNREACHABLE(); // TODO(dcarney): loading RPO constants on PPC.
|
| + UNREACHABLE(); // TODO(dcarney): loading RPO constants on S390.
|
| break;
|
| }
|
| if (destination->IsStackSlot()) {
|
| @@ -1780,9 +1814,14 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
| : kScratchDoubleReg;
|
| double value = (src.type() == Constant::kFloat32) ? src.ToFloat32()
|
| : src.ToFloat64();
|
| - __ LoadDoubleLiteral(dst, value, kScratchReg);
|
| + if (src.type() == Constant::kFloat32) {
|
| + __ LoadFloat32Literal(dst, src.ToFloat32(), kScratchReg);
|
| + } else {
|
| + __ LoadDoubleLiteral(dst, value, kScratchReg);
|
| + }
|
| +
|
| if (destination->IsDoubleStackSlot()) {
|
| - __ StoreDouble(dst, g.ToMemOperand(destination), r0);
|
| + __ StoreDouble(dst, g.ToMemOperand(destination));
|
| }
|
| }
|
| } else if (source->IsDoubleRegister()) {
|
| @@ -1792,27 +1831,26 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
| __ Move(dst, src);
|
| } else {
|
| DCHECK(destination->IsDoubleStackSlot());
|
| - __ StoreDouble(src, g.ToMemOperand(destination), r0);
|
| + __ StoreDouble(src, g.ToMemOperand(destination));
|
| }
|
| } else if (source->IsDoubleStackSlot()) {
|
| DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
|
| MemOperand src = g.ToMemOperand(source);
|
| if (destination->IsDoubleRegister()) {
|
| - __ LoadDouble(g.ToDoubleRegister(destination), src, r0);
|
| + __ LoadDouble(g.ToDoubleRegister(destination), src);
|
| } else {
|
| DoubleRegister temp = kScratchDoubleReg;
|
| - __ LoadDouble(temp, src, r0);
|
| - __ StoreDouble(temp, g.ToMemOperand(destination), r0);
|
| + __ LoadDouble(temp, src);
|
| + __ StoreDouble(temp, g.ToMemOperand(destination));
|
| }
|
| } else {
|
| UNREACHABLE();
|
| }
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleSwap(InstructionOperand* source,
|
| InstructionOperand* destination) {
|
| - PPCOperandConverter g(this, nullptr);
|
| + S390OperandConverter g(this, nullptr);
|
| // Dispatch on the source and destination operand kinds. Not all
|
| // combinations are possible.
|
| if (source->IsRegister()) {
|
| @@ -1821,17 +1859,17 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
|
| Register src = g.ToRegister(source);
|
| if (destination->IsRegister()) {
|
| Register dst = g.ToRegister(destination);
|
| - __ mr(temp, src);
|
| - __ mr(src, dst);
|
| - __ mr(dst, temp);
|
| + __ LoadRR(temp, src);
|
| + __ LoadRR(src, dst);
|
| + __ LoadRR(dst, temp);
|
| } else {
|
| DCHECK(destination->IsStackSlot());
|
| MemOperand dst = g.ToMemOperand(destination);
|
| - __ mr(temp, src);
|
| + __ LoadRR(temp, src);
|
| __ LoadP(src, dst);
|
| __ StoreP(temp, dst);
|
| }
|
| -#if V8_TARGET_ARCH_PPC64
|
| +#if V8_TARGET_ARCH_S390X
|
| } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) {
|
| #else
|
| } else if (source->IsStackSlot()) {
|
| @@ -1850,27 +1888,28 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
|
| DoubleRegister src = g.ToDoubleRegister(source);
|
| if (destination->IsDoubleRegister()) {
|
| DoubleRegister dst = g.ToDoubleRegister(destination);
|
| - __ fmr(temp, src);
|
| - __ fmr(src, dst);
|
| - __ fmr(dst, temp);
|
| + __ ldr(temp, src);
|
| + __ ldr(src, dst);
|
| + __ ldr(dst, temp);
|
| } else {
|
| DCHECK(destination->IsDoubleStackSlot());
|
| MemOperand dst = g.ToMemOperand(destination);
|
| - __ fmr(temp, src);
|
| - __ lfd(src, dst);
|
| - __ stfd(temp, dst);
|
| + __ ldr(temp, src);
|
| + __ LoadDouble(src, dst);
|
| + __ StoreDouble(temp, dst);
|
| }
|
| -#if !V8_TARGET_ARCH_PPC64
|
| +#if !V8_TARGET_ARCH_S390X
|
| } else if (source->IsDoubleStackSlot()) {
|
| DCHECK(destination->IsDoubleStackSlot());
|
| DoubleRegister temp_0 = kScratchDoubleReg;
|
| DoubleRegister temp_1 = d0;
|
| MemOperand src = g.ToMemOperand(source);
|
| MemOperand dst = g.ToMemOperand(destination);
|
| - __ lfd(temp_0, src);
|
| - __ lfd(temp_1, dst);
|
| - __ stfd(temp_0, dst);
|
| - __ stfd(temp_1, src);
|
| + // TODO(joransiu): MVC opportunity
|
| + __ LoadDouble(temp_0, src);
|
| + __ LoadDouble(temp_1, dst);
|
| + __ StoreDouble(temp_0, dst);
|
| + __ StoreDouble(temp_1, src);
|
| #endif
|
| } else {
|
| // No other combinations are possible.
|
| @@ -1878,19 +1917,16 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
|
| }
|
| }
|
|
|
| -
|
| void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
|
| for (size_t index = 0; index < target_count; ++index) {
|
| __ emit_label_addr(targets[index]);
|
| }
|
| }
|
|
|
| -
|
| void CodeGenerator::AddNopForSmiCodeInlining() {
|
| // We do not insert nops for inlined Smi code.
|
| }
|
|
|
| -
|
| void CodeGenerator::EnsureSpaceForLazyDeopt() {
|
| if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
|
| return;
|
| @@ -1901,14 +1937,11 @@ void CodeGenerator::EnsureSpaceForLazyDeopt() {
|
| // instruction for patching the code here.
|
| int current_pc = masm()->pc_offset();
|
| if (current_pc < last_lazy_deopt_pc_ + space_needed) {
|
| - // Block tramoline pool emission for duration of padding.
|
| - v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
|
| - masm());
|
| int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
|
| - DCHECK_EQ(0, padding_size % v8::internal::Assembler::kInstrSize);
|
| + DCHECK_EQ(0, padding_size % 2);
|
| while (padding_size > 0) {
|
| __ nop();
|
| - padding_size -= v8::internal::Assembler::kInstrSize;
|
| + padding_size -= 2;
|
| }
|
| }
|
| }
|
|
|