Index: src/compiler/s390/code-generator-s390.cc |
diff --git a/src/compiler/s390/code-generator-s390.cc b/src/compiler/s390/code-generator-s390.cc |
index d6a952d7aa87dd439072bda14c3537045744557f..baa97bf13aff06d16e8a1831572032123011c5b6 100644 |
--- a/src/compiler/s390/code-generator-s390.cc |
+++ b/src/compiler/s390/code-generator-s390.cc |
@@ -131,10 +131,18 @@ class S390OperandConverter final : public InstructionOperandConverter { |
} |
}; |
+static inline bool HasRegisterOutput(Instruction* instr, int index = 0) { |
+ return instr->OutputCount() > 0 && instr->OutputAt(index)->IsRegister(); |
+} |
+ |
static inline bool HasRegisterInput(Instruction* instr, int index) { |
return instr->InputAt(index)->IsRegister(); |
} |
+static inline bool HasFPRegisterInput(Instruction* instr, int index) { |
+ return instr->InputAt(index)->IsFPRegister(); |
+} |
+ |
static inline bool HasImmediateInput(Instruction* instr, size_t index) { |
return instr->InputAt(index)->IsImmediate(); |
} |
@@ -143,6 +151,10 @@ static inline bool HasStackSlotInput(Instruction* instr, size_t index) { |
return instr->InputAt(index)->IsStackSlot(); |
} |
+static inline bool HasFPStackSlotInput(Instruction* instr, size_t index) { |
+ return instr->InputAt(index)->IsFPStackSlot(); |
+} |
+ |
namespace { |
class OutOfLineLoadNAN32 final : public OutOfLineCode { |
@@ -260,17 +272,33 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { |
return eq; |
case kNotEqual: |
return ne; |
- case kSignedLessThan: |
case kUnsignedLessThan: |
+ // unsigned number never less than 0 |
+ if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64) |
+ return CC_NOP; |
+ // fall through |
+ case kSignedLessThan: |
return lt; |
- case kSignedGreaterThanOrEqual: |
case kUnsignedGreaterThanOrEqual: |
+ // unsigned number always greater than or equal 0 |
+ if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64) |
+ return CC_ALWAYS; |
+ // fall through |
+ case kSignedGreaterThanOrEqual: |
return ge; |
- case kSignedLessThanOrEqual: |
case kUnsignedLessThanOrEqual: |
+ // unsigned number never less than 0 |
+ if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64) |
+ return CC_EQ; |
+ // fall through |
+ case kSignedLessThanOrEqual: |
return le; |
- case kSignedGreaterThan: |
case kUnsignedGreaterThan: |
+ // unsigned number always greater than or equal 0 |
+ if (op == kS390_LoadAndTestWord32 || op == kS390_LoadAndTestWord64) |
+ return ne; |
+ // fall through |
+ case kSignedGreaterThan: |
return gt; |
case kOverflow: |
// Overflow checked for AddP/SubP only. |
@@ -496,26 +524,91 @@ void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm, |
} \ |
} while (0) |
-#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)); \ |
- } \ |
- } \ |
+#define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \ |
+ do { \ |
+ AddressingMode mode = AddressingModeField::decode(instr->opcode()); \ |
+ if (mode != kMode_None) { \ |
+ size_t first_index = 1; \ |
+ MemOperand operand = i.MemoryOperand(&mode, &first_index); \ |
+ if (i.CompareLogical()) { \ |
+ __ cmpl_instr(i.InputRegister(0), operand); \ |
+ } else { \ |
+ __ cmp_instr(i.InputRegister(0), operand); \ |
+ } \ |
+ } else 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 (HasImmediateInput(instr, 1)) { \ |
+ if (i.CompareLogical()) { \ |
+ __ cmpl_instr(i.InputRegister(0), i.InputImmediate(1)); \ |
+ } else { \ |
+ __ cmp_instr(i.InputRegister(0), i.InputImmediate(1)); \ |
+ } \ |
+ } else { \ |
+ DCHECK(HasStackSlotInput(instr, 1)); \ |
+ if (i.CompareLogical()) { \ |
+ __ cmpl_instr(i.InputRegister(0), i.InputStackSlot(1)); \ |
+ } else { \ |
+ __ cmp_instr(i.InputRegister(0), i.InputStackSlot(1)); \ |
+ } \ |
+ } \ |
} while (0) |
-#define ASSEMBLE_FLOAT_COMPARE(cmp_instr) \ |
- do { \ |
- __ cmp_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ |
+#define ASSEMBLE_COMPARE32(cmp_instr, cmpl_instr) \ |
+ do { \ |
+ AddressingMode mode = AddressingModeField::decode(instr->opcode()); \ |
+ if (mode != kMode_None) { \ |
+ size_t first_index = 1; \ |
+ MemOperand operand = i.MemoryOperand(&mode, &first_index); \ |
+ if (i.CompareLogical()) { \ |
+ __ cmpl_instr(i.InputRegister(0), operand); \ |
+ } else { \ |
+ __ cmp_instr(i.InputRegister(0), operand); \ |
+ } \ |
+ } else 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 (HasImmediateInput(instr, 1)) { \ |
+ if (i.CompareLogical()) { \ |
+ __ cmpl_instr(i.InputRegister(0), i.InputImmediate(1)); \ |
+ } else { \ |
+ __ cmp_instr(i.InputRegister(0), i.InputImmediate(1)); \ |
+ } \ |
+ } else { \ |
+ DCHECK(HasStackSlotInput(instr, 1)); \ |
+ if (i.CompareLogical()) { \ |
+ __ cmpl_instr(i.InputRegister(0), i.InputStackSlot32(1)); \ |
+ } else { \ |
+ __ cmp_instr(i.InputRegister(0), i.InputStackSlot32(1)); \ |
+ } \ |
+ } \ |
+ } while (0) |
+ |
+#define ASSEMBLE_FLOAT_COMPARE(cmp_rr_instr, cmp_rm_instr, load_instr) \ |
+ do { \ |
+ AddressingMode mode = AddressingModeField::decode(instr->opcode()); \ |
+ if (mode != kMode_None) { \ |
+ size_t first_index = 1; \ |
+ MemOperand operand = i.MemoryOperand(&mode, &first_index); \ |
+ __ cmp_rm_instr(i.InputDoubleRegister(0), operand); \ |
+ } else if (HasFPRegisterInput(instr, 1)) { \ |
+ __ cmp_rr_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ |
+ } else { \ |
+ DCHECK(HasFPStackSlotInput(instr, 1)); \ |
+ MemOperand operand = i.InputStackSlot(1); \ |
+ if (operand.offset() >= 0) { \ |
+ __ cmp_rm_instr(i.InputDoubleRegister(0), operand); \ |
+ } else { \ |
+ __ load_instr(kScratchDoubleReg, operand); \ |
+ __ cmp_rr_instr(i.InputDoubleRegister(0), kScratchDoubleReg); \ |
+ } \ |
+ } \ |
} while (0) |
// Divide instruction dr will implicity use register pair |
@@ -747,6 +840,7 @@ void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm, |
} \ |
__ bind(&done); \ |
} while (0) |
+// |
// Only MRI mode for these instructions available |
#define ASSEMBLE_LOAD_FLOAT(asm_instr) \ |
do { \ |
@@ -764,6 +858,38 @@ void AssembleBinOp(S390OperandConverter& i, MacroAssembler* masm, |
__ asm_instr(result, operand); \ |
} while (0) |
+#define ASSEMBLE_LOADANDTEST64(asm_instr_rr, asm_instr_rm) \ |
+ { \ |
+ AddressingMode mode = AddressingModeField::decode(instr->opcode()); \ |
+ Register dst = HasRegisterOutput(instr) ? i.OutputRegister() : r0; \ |
+ if (mode != kMode_None) { \ |
+ size_t first_index = 0; \ |
+ MemOperand operand = i.MemoryOperand(&mode, &first_index); \ |
+ __ asm_instr_rm(dst, operand); \ |
+ } else if (HasRegisterInput(instr, 0)) { \ |
+ __ asm_instr_rr(dst, i.InputRegister(0)); \ |
+ } else { \ |
+ DCHECK(HasStackSlotInput(instr, 0)); \ |
+ __ asm_instr_rm(dst, i.InputStackSlot(0)); \ |
+ } \ |
+ } |
+ |
+#define ASSEMBLE_LOADANDTEST32(asm_instr_rr, asm_instr_rm) \ |
+ { \ |
+ AddressingMode mode = AddressingModeField::decode(instr->opcode()); \ |
+ Register dst = HasRegisterOutput(instr) ? i.OutputRegister() : r0; \ |
+ if (mode != kMode_None) { \ |
+ size_t first_index = 0; \ |
+ MemOperand operand = i.MemoryOperand(&mode, &first_index); \ |
+ __ asm_instr_rm(dst, operand); \ |
+ } else if (HasRegisterInput(instr, 0)) { \ |
+ __ asm_instr_rr(dst, i.InputRegister(0)); \ |
+ } else { \ |
+ DCHECK(HasStackSlotInput(instr, 0)); \ |
+ __ asm_instr_rm(dst, i.InputStackSlot32(0)); \ |
+ } \ |
+ } |
+ |
#define ASSEMBLE_STORE_FLOAT32() \ |
do { \ |
size_t index = 0; \ |
@@ -1778,7 +1904,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
#endif |
case kS390_Cmp32: |
- ASSEMBLE_COMPARE(Cmp32, CmpLogical32); |
+ ASSEMBLE_COMPARE32(Cmp32, CmpLogical32); |
break; |
#if V8_TARGET_ARCH_S390X |
case kS390_Cmp64: |
@@ -1786,15 +1912,16 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
#endif |
case kS390_CmpFloat: |
- __ cebr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
+ ASSEMBLE_FLOAT_COMPARE(cebr, ceb, ley); |
+ // __ cebr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
break; |
case kS390_CmpDouble: |
- __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
+ ASSEMBLE_FLOAT_COMPARE(cdbr, cdb, ldy); |
+ // __ cdbr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
break; |
case kS390_Tst32: |
if (HasRegisterInput(instr, 1)) { |
- __ lr(r0, i.InputRegister(0)); |
- __ nr(r0, i.InputRegister(1)); |
+ __ And(r0, i.InputRegister(0), i.InputRegister(1)); |
} else { |
Operand opnd = i.InputImmediate(1); |
if (is_uint16(opnd.immediate())) { |
@@ -2109,6 +2236,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
ASSEMBLE_LOAD_INTEGER(lg); |
break; |
#endif |
+ case kS390_LoadAndTestWord32: { |
+ ASSEMBLE_LOADANDTEST32(ltr, lt_z); |
+ break; |
+ } |
+ case kS390_LoadAndTestWord64: { |
+ ASSEMBLE_LOADANDTEST64(ltgr, ltg); |
+ break; |
+ } |
case kS390_LoadFloat32: |
ASSEMBLE_LOAD_FLOAT(LoadFloat32); |
break; |