Revision: 6531
Author: [email protected]
Date: Mon Jan 31 02:16:28 2011
Log: ARM: Add support for DoMathAbs with double inputs.
Adds vabs instruction to simulator, assembler, disassembler and tests.
BUG=none
TEST=Added to cctest.
Review URL: http://codereview.chromium.org/6366016
http://code.google.com/p/v8/source/detail?r=6531
Modified:
/branches/bleeding_edge/src/arm/assembler-arm.cc
/branches/bleeding_edge/src/arm/assembler-arm.h
/branches/bleeding_edge/src/arm/disasm-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/simulator-arm.cc
/branches/bleeding_edge/test/cctest/test-assembler-arm.cc
/branches/bleeding_edge/test/cctest/test-disasm-arm.cc
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.cc Wed Jan 26 00:32:54
2011
+++ /branches/bleeding_edge/src/arm/assembler-arm.cc Mon Jan 31 02:16:28
2011
@@ -2226,6 +2226,14 @@
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
}
+
+
+void Assembler::vabs(const DwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond) {
+ emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 |
+ 0x5*B9 | B8 | 0x3*B6 | src.code());
+}
void Assembler::vadd(const DwVfpRegister dst,
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Wed Jan 26 00:32:54 2011
+++ /branches/bleeding_edge/src/arm/assembler-arm.h Mon Jan 31 02:16:28 2011
@@ -975,6 +975,9 @@
ConversionMode mode = RoundToZero,
const Condition cond = al);
+ void vabs(const DwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond = al);
void vadd(const DwVfpRegister dst,
const DwVfpRegister src1,
const DwVfpRegister src2,
=======================================
--- /branches/bleeding_edge/src/arm/disasm-arm.cc Wed Jan 26 00:32:54 2011
+++ /branches/bleeding_edge/src/arm/disasm-arm.cc Mon Jan 31 02:16:28 2011
@@ -1064,6 +1064,9 @@
} else {
Format(instr, "vmov.f32'cond 'Sd, 'Sm");
}
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() ==
0x3)) {
+ // vabs
+ Format(instr, "vabs'cond 'Dd, 'Dm");
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() ==
0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() &
0x1)) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jan 27
00:35:39 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Jan 31
02:16:28 2011
@@ -1174,8 +1174,7 @@
0,
Safepoint::kNoDeoptimizationIndex);
// Overwrite the stored value of r0 with the result of the stub.
- __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters *
- kDoubleSize));
+ __ StoreToSafepointRegistersAndDoublesSlot(r0);
__ PopSafepointRegistersAndDoubles();
}
@@ -2525,6 +2524,7 @@
void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation*
instr) {
+ ASSERT(instr->InputAt(0)->Equals(instr->result()));
Register input = ToRegister(instr->InputAt(0));
Register scratch = scratch0();
@@ -2535,28 +2535,32 @@
DeoptimizeIf(ne, instr->environment());
Label done;
-
- Label negative;
- __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
+ Register exponent = scratch0();
+ scratch = no_reg;
+ __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
// Check the sign of the argument. If the argument is positive, just
// return it. We do not need to patch the stack since |input| and
- // |result| are the same register and |input| will be restored
+ // |result| are the same register and |input| would be restored
// unchanged by popping safepoint registers.
- __ tst(scratch, Operand(HeapNumber::kSignMask));
- __ b(ne, &negative);
- __ jmp(&done);
-
- __ bind(&negative);
+ __ tst(exponent, Operand(HeapNumber::kSignMask));
+ __ b(eq, &done);
+
+ // Input is negative. Reverse its sign.
// Preserve the value of all registers.
__ PushSafepointRegisters();
- Register tmp = input.is(r0) ? r1 : r0;
- Register tmp2 = input.is(r2) ? r3 : r2;
- Register tmp3 = input.is(r4) ? r5 : r4;
+ // Registers were saved at the safepoint, so we can use
+ // many scratch registers.
+ Register tmp1 = input.is(r1) ? r0 : r1;
+ Register tmp2 = input.is(r2) ? r0 : r2;
+ Register tmp3 = input.is(r3) ? r0 : r3;
+ Register tmp4 = input.is(r4) ? r0 : r4;
+
+ // exponent: floating point exponent value.
Label allocated, slow;
- __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
- __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow);
+ __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
__ b(&allocated);
// Slow case: Call the runtime system to do the number allocation.
@@ -2566,20 +2570,20 @@
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
// Set the pointer to the new heap number in tmp.
- if (!tmp.is(r0)) __ mov(tmp, Operand(r0));
-
+ if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
// Restore input_reg after call to runtime.
- MemOperand input_register_slot = masm()->SafepointRegisterSlot(input);
- __ ldr(input, input_register_slot);
+ __ LoadFromSafepointRegisterSlot(input);
+ __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
__ bind(&allocated);
- __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset));
- __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask));
- __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset));
+ // exponent: floating point exponent value.
+ // tmp1: allocated heap number.
+ __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
+ __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
__ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
- __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset));
-
- __ str(tmp, input_register_slot);
+ __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
+
+ __ str(tmp1, masm()->SafepointRegisterSlot(input));
__ PopSafepointRegisters();
__ bind(&done);
@@ -2587,15 +2591,14 @@
void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
- Label is_positive;
- uint32_t kSignMask = 0x80000000u;
Register input = ToRegister(instr->InputAt(0));
- __ tst(input, Operand(kSignMask));
- __ b(eq, &is_positive);
- __ rsb(input, input, Operand(0), SetCC);
+ __ cmp(input, Operand(0));
+ // We can make rsb conditional because the previous cmp instruction
+ // will clear the V (overflow) flag and rsb won't set this flag
+ // if input is positive.
+ __ rsb(input, input, Operand(0), SetCC, mi);
// Deoptimize on overflow.
DeoptimizeIf(vs, instr->environment());
- __ bind(&is_positive);
}
@@ -2617,8 +2620,7 @@
Representation r = instr->hydrogen()->value()->representation();
if (r.IsDouble()) {
DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
- // __ vabs(input, input);
- Abort("Double DoMathAbs unimplemented");
+ __ vabs(input, input);
} else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else {
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Jan 26
00:32:54 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Jan 31
02:16:28 2011
@@ -485,9 +485,19 @@
PopSafepointRegisters();
}
+void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register reg)
{
+ str(reg, SafepointRegistersAndDoublesSlot(reg));
+}
+
+
void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) {
str(reg, SafepointRegisterSlot(reg));
}
+
+
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register reg) {
+ ldr(reg, SafepointRegisterSlot(reg));
+}
int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
@@ -501,6 +511,14 @@
MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) *
kPointerSize);
}
+
+
+MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
+ // General purpose registers are pushed last on the stack.
+ int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
+ int register_offset = SafepointRegisterStackIndex(reg.code()) *
kPointerSize;
+ return MemOperand(sp, doubles_size + register_offset);
+}
void MacroAssembler::Ldrd(Register dst1, Register dst2,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Jan 26
00:32:54 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Jan 31
02:16:28 2011
@@ -235,8 +235,11 @@
void PushSafepointRegistersAndDoubles();
void PopSafepointRegistersAndDoubles();
void StoreToSafepointRegisterSlot(Register reg);
+ void StoreToSafepointRegistersAndDoublesSlot(Register reg);
+ void LoadFromSafepointRegisterSlot(Register reg);
static int SafepointRegisterStackIndex(int reg_code);
static MemOperand SafepointRegisterSlot(Register reg);
+ static MemOperand SafepointRegistersAndDoublesSlot(Register reg);
// Load two consecutive registers with two consecutive memory locations.
void Ldrd(Register dst1,
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Wed Jan 26 00:32:54
2011
+++ /branches/bleeding_edge/src/arm/simulator-arm.cc Mon Jan 31 02:16:28
2011
@@ -2445,6 +2445,11 @@
int d = instr->VFPDRegValue(kSinglePrecision);
set_s_register_from_float(d, get_float_from_s_register(m));
}
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() ==
0x3)) {
+ // vabs
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = fabs(dm_value);
+ set_d_register_from_double(vd, dd_value);
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() ==
0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() &
0x1)) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-assembler-arm.cc Wed Jan 26
01:52:25 2011
+++ /branches/bleeding_edge/test/cctest/test-assembler-arm.cc Mon Jan 31
02:16:28 2011
@@ -229,6 +229,8 @@
double d;
double e;
double f;
+ double g;
+ double h;
int i;
float x;
float y;
@@ -286,6 +288,15 @@
__ vmov(s31, lr);
__ vcvt_f64_s32(d4, s31);
__ vstr(d4, r4, OFFSET_OF(T, f));
+
+ // Test vabs.
+ __ vldr(d1, r4, OFFSET_OF(T, g));
+ __ vabs(d0, d1);
+ __ vstr(d0, r4, OFFSET_OF(T, g));
+ __ vldr(d2, r4, OFFSET_OF(T, h));
+ __ vabs(d0, d2);
+ __ vstr(d0, r4, OFFSET_OF(T, h));
+
__ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
CodeDesc desc;
@@ -305,6 +316,8 @@
t.d = 0.0;
t.e = 0.0;
t.f = 0.0;
+ t.g = -2718.2818;
+ t.h = 31415926.5;
t.i = 0;
t.x = 4.5;
t.y = 9.0;
@@ -313,6 +326,8 @@
CHECK_EQ(4.5, t.y);
CHECK_EQ(9.0, t.x);
CHECK_EQ(2, t.i);
+ CHECK_EQ(2718.2818, t.g);
+ CHECK_EQ(31415926.5, t.h);
CHECK_EQ(42.0, t.f);
CHECK_EQ(1.0, t.e);
CHECK_EQ(1.000000059604644775390625, t.d);
=======================================
--- /branches/bleeding_edge/test/cctest/test-disasm-arm.cc Tue Dec 7
03:01:02 2010
+++ /branches/bleeding_edge/test/cctest/test-disasm-arm.cc Mon Jan 31
02:16:28 2011
@@ -435,6 +435,11 @@
COMPARE(vmov(s31, r10),
"ee0faa90 vmov s31, r10");
+ COMPARE(vabs(d0, d1),
+ "eeb00bc1 vabs d0, d1");
+ COMPARE(vabs(d3, d4, mi),
+ "4eb03bc4 vabsmi d3, d4");
+
COMPARE(vadd(d0, d1, d2),
"ee310b02 vadd.f64 d0, d1, d2");
COMPARE(vadd(d3, d4, d5, mi),
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev