Revision: 5352
Author: [email protected]
Date: Thu Aug 26 01:53:00 2010
Log: Fix incorrect encoding of single and double precision registers for
some VFP instructions. Also fix incorrect disassembling of vldr/vstr. This
is a commit of http://codereview.chromium.org/3107027 for Rodolph Perfetta.
http://code.google.com/p/v8/source/detail?r=5352
Modified:
/branches/bleeding_edge/src/arm/assembler-arm.cc
/branches/bleeding_edge/src/arm/assembler-arm.h
/branches/bleeding_edge/src/arm/constants-arm.h
/branches/bleeding_edge/src/arm/disasm-arm.cc
/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 Tue Aug 17 01:43:45
2010
+++ /branches/bleeding_edge/src/arm/assembler-arm.cc Thu Aug 26 01:53:00
2010
@@ -1809,6 +1809,7 @@
// Support for VFP.
+
void Assembler::vldr(const DwVfpRegister dst,
const Register base,
int offset,
@@ -1838,7 +1839,9 @@
ASSERT(offset % 4 == 0);
ASSERT((offset / 4) < 256);
ASSERT(offset >= 0);
- emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
+ int sd, d;
+ dst.split_code(&sd, &d);
+ emit(cond | d*B22 | 0xD9*B20 | base.code()*B16 | sd*B12 |
0xA*B8 | ((offset / 4) & 255));
}
@@ -1872,7 +1875,9 @@
ASSERT(offset % 4 == 0);
ASSERT((offset / 4) < 256);
ASSERT(offset >= 0);
- emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 |
+ int sd, d;
+ src.split_code(&sd, &d);
+ emit(cond | d*B22 | 0xD8*B20 | base.code()*B16 | sd*B12 |
0xA*B8 | ((offset / 4) & 255));
}
@@ -1979,8 +1984,10 @@
// Sd = Sm
// Instruction details available in ARM DDI 0406B, A8-642.
ASSERT(CpuFeatures::IsEnabled(VFP3));
- emit(cond | 0xE*B24 | 0xB*B20 |
- dst.code()*B12 | 0x5*B9 | B6 | src.code());
+ int sd, d, sm, m;
+ dst.split_code(&sd, &d);
+ src.split_code(&sm, &m);
+ emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 |
sm);
}
@@ -2034,8 +2041,9 @@
// Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(!src.is(pc));
- emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 |
- src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4);
+ int sn, n;
+ dst.split_code(&sn, &n);
+ emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
}
@@ -2048,8 +2056,9 @@
// Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(!dst.is(pc));
- emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 |
- dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4);
+ int sn, n;
+ src.split_code(&sn, &n);
+ emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 |
B4);
}
@@ -2099,16 +2108,21 @@
}
-// Depending on split_last_bit split binary representation of reg_code
into Vm:M
-// or M:Vm form (where M is single bit).
-static void SplitRegCode(bool split_last_bit,
+// Split five bit reg_code based on size of reg_type.
+// 32-bit register codes are Vm:M
+// 64-bit register codes are M:Vm
+// where Vm is four bits, and M is a single bit.
+static void SplitRegCode(VFPType reg_type,
int reg_code,
int* vm,
int* m) {
- if (split_last_bit) {
+ ASSERT((reg_code >= 0) && (reg_code <= 31));
+ if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
+ // 32 bit type.
*m = reg_code & 0x1;
*vm = reg_code >> 1;
} else {
+ // 64 bit type.
*m = (reg_code & 0x10) >> 4;
*vm = reg_code & 0x0F;
}
@@ -2121,6 +2135,11 @@
const VFPType src_type,
const int src_code,
const Condition cond) {
+ ASSERT(src_type != dst_type);
+ int D, Vd, M, Vm;
+ SplitRegCode(src_type, src_code, &Vm, &M);
+ SplitRegCode(dst_type, dst_code, &Vd, &D);
+
if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
// Conversion between IEEE floating point and 32-bit integer.
// Instruction details available in ARM DDI 0406B, A8.6.295.
@@ -2128,22 +2147,17 @@
// Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
- int sz, opc2, D, Vd, M, Vm, op;
+ int sz, opc2, op;
if (IsIntegerVFPType(dst_type)) {
opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
op = 1; // round towards zero
- SplitRegCode(!IsDoubleVFPType(src_type), src_code, &Vm, &M);
- SplitRegCode(true, dst_code, &Vd, &D);
} else {
ASSERT(IsIntegerVFPType(src_type));
-
opc2 = 0x0;
sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
- SplitRegCode(true, src_code, &Vm, &M);
- SplitRegCode(!IsDoubleVFPType(dst_type), dst_code, &Vd, &D);
}
return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
@@ -2153,13 +2167,7 @@
// Instruction details available in ARM DDI 0406B, A8.6.298.
// cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
// Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
- int sz, D, Vd, M, Vm;
-
- ASSERT(IsDoubleVFPType(dst_type) != IsDoubleVFPType(src_type));
- sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
- SplitRegCode(IsDoubleVFPType(src_type), dst_code, &Vd, &D);
- SplitRegCode(!IsDoubleVFPType(src_type), src_code, &Vm, &M);
-
+ int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
}
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Tue Aug 17 01:43:45 2010
+++ /branches/bleeding_edge/src/arm/assembler-arm.h Thu Aug 26 01:53:00 2010
@@ -120,6 +120,11 @@
ASSERT(is_valid());
return 1 << code_;
}
+ void split_code(int* vm, int* m) const {
+ ASSERT(is_valid());
+ *m = code_ & 0x1;
+ *vm = code_ >> 1;
+ }
int code_;
};
@@ -152,6 +157,11 @@
ASSERT(is_valid());
return 1 << code_;
}
+ void split_code(int* vm, int* m) const {
+ ASSERT(is_valid());
+ *m = (code_ & 0x10) >> 4;
+ *vm = code_ & 0x0F;
+ }
int code_;
};
=======================================
--- /branches/bleeding_edge/src/arm/constants-arm.h Thu Jul 8 05:38:02 2010
+++ /branches/bleeding_edge/src/arm/constants-arm.h Thu Aug 26 01:53:00 2010
@@ -194,6 +194,13 @@
};
+// Type of VFP register. Determines register encoding.
+enum VFPRegPrecision {
+ kSinglePrecision = 0,
+ kDoublePrecision = 1
+};
+
+
typedef int32_t instr_t;
@@ -269,6 +276,15 @@
inline int VCField() const { return Bit(8); }
inline int VAField() const { return Bits(23, 21); }
inline int VBField() const { return Bits(6, 5); }
+ inline int VFPNRegCode(VFPRegPrecision pre) {
+ return VFPGlueRegCode(pre, 16, 7);
+ }
+ inline int VFPMRegCode(VFPRegPrecision pre) {
+ return VFPGlueRegCode(pre, 0, 5);
+ }
+ inline int VFPDRegCode(VFPRegPrecision pre) {
+ return VFPGlueRegCode(pre, 12, 22);
+ }
// Fields used in Data processing instructions
inline Opcode OpcodeField() const {
@@ -343,6 +359,17 @@
static Instr* At(byte* pc) { return reinterpret_cast<Instr*>(pc); }
private:
+ // Join split register codes, depending on single or double precision.
+ // four_bit is the position of the least-significant bit of the four
+ // bit specifier. one_bit is the position of the additional single bit
+ // specifier.
+ inline int VFPGlueRegCode(VFPRegPrecision pre, int four_bit, int
one_bit) {
+ if (pre == kSinglePrecision) {
+ return (Bits(four_bit + 3, four_bit) << 1) | Bit(one_bit);
+ }
+ return (Bit(one_bit) << 4) | Bits(four_bit + 3, four_bit);
+ }
+
// We need to prevent the creation of instances of class Instr.
DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
};
=======================================
--- /branches/bleeding_edge/src/arm/disasm-arm.cc Mon Aug 16 00:52:49 2010
+++ /branches/bleeding_edge/src/arm/disasm-arm.cc Thu Aug 26 01:53:00 2010
@@ -463,7 +463,7 @@
ASSERT((width + lsb) <= 32);
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
- "#%d",
+ "%d",
instr->Bits(width + lsb - 1,
lsb));
return 8;
}
@@ -931,7 +931,7 @@
if (instr->HasW()) {
ASSERT(instr->Bits(5, 4) == 0x1);
if (instr->Bit(22) == 0x1) {
- Format(instr, "usat 'rd, 'im...@16, 'rm'shift_sat");
+ Format(instr, "usat 'rd, #'im...@16, 'rm'shift_sat");
} else {
UNREACHABLE(); // SSAT.
}
@@ -1269,17 +1269,19 @@
if (instr->CoprocessorField() == 0xA) {
switch (instr->OpcodeField()) {
case 0x8:
+ case 0xA:
if (instr->HasL()) {
- Format(instr, "vldr'cond 'Sd, ['rn - 4*'off8]");
+ Format(instr, "vldr'cond 'Sd, ['rn - 4*'im...@00]");
} else {
- Format(instr, "vstr'cond 'Sd, ['rn - 4*'off8]");
+ Format(instr, "vstr'cond 'Sd, ['rn - 4*'im...@00]");
}
break;
case 0xC:
+ case 0xE:
if (instr->HasL()) {
- Format(instr, "vldr'cond 'Sd, ['rn + 4*'off8]");
+ Format(instr, "vldr'cond 'Sd, ['rn + 4*'im...@00]");
} else {
- Format(instr, "vstr'cond 'Sd, ['rn + 4*'off8]");
+ Format(instr, "vstr'cond 'Sd, ['rn + 4*'im...@00]");
}
break;
default:
@@ -1300,16 +1302,16 @@
break;
case 0x8:
if (instr->HasL()) {
- Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]");
+ Format(instr, "vldr'cond 'Dd, ['rn - 4*'im...@00]");
} else {
- Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]");
+ Format(instr, "vstr'cond 'Dd, ['rn - 4*'im...@00]");
}
break;
case 0xC:
if (instr->HasL()) {
- Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]");
+ Format(instr, "vldr'cond 'Dd, ['rn + 4*'im...@00]");
} else {
- Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]");
+ Format(instr, "vstr'cond 'Dd, ['rn + 4*'im...@00]");
}
break;
default:
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Fri Aug 20 02:37:22
2010
+++ /branches/bleeding_edge/src/arm/simulator-arm.cc Thu Aug 26 01:53:00
2010
@@ -2279,13 +2279,6 @@
dbg.Stop(instr);
}
}
-
-
-// Depending on value of last_bit flag glue register code from vm and m
values
-// (where m is expected to be a single bit).
-static int GlueRegCode(bool last_bit, int vm, int m) {
- return last_bit ? ((vm << 1) | m) : ((m << 4) | vm);
-}
// void Simulator::DecodeTypeVFP(Instr* instr)
@@ -2305,9 +2298,10 @@
ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
ASSERT(instr->Bits(11, 9) == 0x5);
- int vm = instr->VmField();
- int vd = instr->VdField();
- int vn = instr->VnField();
+ // Obtain double precision register codes.
+ int vm = instr->VFPMRegCode(kDoublePrecision);
+ int vd = instr->VFPDRegCode(kDoublePrecision);
+ int vn = instr->VFPNRegCode(kDoublePrecision);
if (instr->Bit(4) == 0) {
if (instr->Opc1Field() == 0x7) {
@@ -2315,9 +2309,13 @@
if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) {
// vmov register to register.
if (instr->SzField() == 0x1) {
- set_d_register_from_double(vd, get_double_from_d_register(vm));
+ int m = instr->VFPMRegCode(kDoublePrecision);
+ int d = instr->VFPDRegCode(kDoublePrecision);
+ set_d_register_from_double(d, get_double_from_d_register(m));
} else {
- set_s_register_from_float(vd, get_float_from_s_register(vm));
+ int m = instr->VFPMRegCode(kSinglePrecision);
+ int d = instr->VFPDRegCode(kSinglePrecision);
+ set_s_register_from_float(d, get_float_from_s_register(m));
}
} else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() ==
0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
@@ -2410,7 +2408,7 @@
(instr->VAField() == 0x0));
int t = instr->RtField();
- int n = GlueRegCode(true, instr->VnField(), instr->NField());
+ int n = instr->VFPNRegCode(kSinglePrecision);
bool to_arm_register = (instr->VLField() == 0x1);
if (to_arm_register) {
@@ -2427,22 +2425,25 @@
ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
(instr->Opc3Field() & 0x1));
-
// Comparison.
- bool dp_operation = (instr->SzField() == 1);
+
+ VFPRegPrecision precision = kSinglePrecision;
+ if (instr->SzField() == 1) {
+ precision = kDoublePrecision;
+ }
if (instr->Bit(7) != 0) {
// Raising exceptions for quiet NaNs are not supported.
UNIMPLEMENTED(); // Not used by V8.
}
- int d = GlueRegCode(!dp_operation, instr->VdField(), instr->DField());
+ int d = instr->VFPDRegCode(precision);
int m = 0;
if (instr->Opc2Field() == 0x4) {
- m = GlueRegCode(!dp_operation, instr->VmField(), instr->MField());
+ m = instr->VFPMRegCode(precision);
}
- if (dp_operation) {
+ if (precision == kDoublePrecision) {
double dd_value = get_double_from_d_register(d);
double dm_value = 0.0;
if (instr->Opc2Field() == 0x4) {
@@ -2460,11 +2461,17 @@
ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3));
- bool double_to_single = (instr->SzField() == 1);
- int dst = GlueRegCode(double_to_single, instr->VdField(),
instr->DField());
- int src = GlueRegCode(!double_to_single, instr->VmField(),
instr->MField());
-
- if (double_to_single) {
+ VFPRegPrecision dst_precision = kDoublePrecision;
+ VFPRegPrecision src_precision = kSinglePrecision;
+ if (instr->SzField() == 1) {
+ dst_precision = kSinglePrecision;
+ src_precision = kDoublePrecision;
+ }
+
+ int dst = instr->VFPDRegCode(dst_precision);
+ int src = instr->VFPMRegCode(src_precision);
+
+ if (dst_precision == kSinglePrecision) {
double val = get_double_from_d_register(src);
set_s_register_from_float(dst, static_cast<float>(val));
} else {
@@ -2480,13 +2487,13 @@
(((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() &
0x1)));
// Conversion between floating-point and integer.
- int vd = instr->VdField();
- int d = instr->DField();
- int vm = instr->VmField();
- int m = instr->MField();
-
bool to_integer = (instr->Bit(18) == 1);
- bool dp_operation = (instr->SzField() == 1);
+
+ VFPRegPrecision src_precision = kSinglePrecision;
+ if (instr->SzField() == 1) {
+ src_precision = kDoublePrecision;
+ }
+
if (to_integer) {
bool unsigned_integer = (instr->Bit(16) == 0);
if (instr->Bit(7) != 1) {
@@ -2494,10 +2501,10 @@
UNIMPLEMENTED(); // Not used by V8.
}
- int dst = GlueRegCode(true, vd, d);
- int src = GlueRegCode(!dp_operation, vm, m);
-
- if (dp_operation) {
+ int dst = instr->VFPDRegCode(kSinglePrecision);
+ int src = instr->VFPMRegCode(src_precision);
+
+ if (src_precision == kDoublePrecision) {
double val = get_double_from_d_register(src);
int sint = unsigned_integer ? static_cast<uint32_t>(val) :
@@ -2515,12 +2522,12 @@
} else {
bool unsigned_integer = (instr->Bit(7) == 0);
- int dst = GlueRegCode(!dp_operation, vd, d);
- int src = GlueRegCode(true, vm, m);
+ int dst = instr->VFPDRegCode(src_precision);
+ int src = instr->VFPMRegCode(kSinglePrecision);
int val = get_sinteger_from_s_register(src);
- if (dp_operation) {
+ if (src_precision == kDoublePrecision) {
if (unsigned_integer) {
set_d_register_from_double(dst,
static_cast<double>((uint32_t)val));
@@ -2551,9 +2558,11 @@
if (instr->CoprocessorField() == 0xA) {
switch (instr->OpcodeField()) {
case 0x8:
- case 0xC: { // Load and store float to memory.
+ case 0xA:
+ case 0xC:
+ case 0xE: { // Load and store single precision float to memory.
int rn = instr->RnField();
- int vd = instr->VdField();
+ int vd = instr->VFPDRegCode(kSinglePrecision);
int offset = instr->Immed8Field();
if (!instr->HasU()) {
offset = -offset;
=======================================
--- /branches/bleeding_edge/test/cctest/test-assembler-arm.cc Tue Aug 17
01:43:45 2010
+++ /branches/bleeding_edge/test/cctest/test-assembler-arm.cc Thu Aug 26
01:53:00 2010
@@ -226,13 +226,17 @@
double a;
double b;
double c;
- float d;
- float e;
+ double d;
+ double e;
+ double f;
+ int i;
+ float x;
+ float y;
} T;
T t;
// Create a function that accepts &t, and loads, manipulates, and stores
- // the doubles t.a, t.b, and t.c, and floats t.d, t.e.
+ // the doubles and floats.
Assembler assm(NULL, 0);
Label L, C;
@@ -254,15 +258,34 @@
__ vmov(d4, r2, r3);
__ vstr(d4, r4, OFFSET_OF(T, b));
- // Load t.d and t.e, switch values, and store back to the struct.
- __ vldr(s0, r4, OFFSET_OF(T, d));
- __ vldr(s1, r4, OFFSET_OF(T, e));
- __ vmov(s2, s0);
- __ vmov(s0, s1);
- __ vmov(s1, s2);
- __ vstr(s0, r4, OFFSET_OF(T, d));
- __ vstr(s1, r4, OFFSET_OF(T, e));
-
+ // Load t.x and t.y, switch values, and store back to the struct.
+ __ vldr(s0, r4, OFFSET_OF(T, x));
+ __ vldr(s31, r4, OFFSET_OF(T, y));
+ __ vmov(s16, s0);
+ __ vmov(s0, s31);
+ __ vmov(s31, s16);
+ __ vstr(s0, r4, OFFSET_OF(T, x));
+ __ vstr(s31, r4, OFFSET_OF(T, y));
+
+ // Move a literal into a register that can be encoded in the
instruction.
+ __ vmov(d4, 1.0);
+ __ vstr(d4, r4, OFFSET_OF(T, e));
+
+ // Move a literal into a register that requires 64 bits to encode.
+ // 0x3ff0000010000000 = 1.000000059604644775390625
+ __ vmov(d4, 1.000000059604644775390625);
+ __ vstr(d4, r4, OFFSET_OF(T, d));
+
+ // Convert from floating point to integer.
+ __ vmov(d4, 2.0);
+ __ vcvt_s32_f64(s31, d4);
+ __ vstr(s31, r4, OFFSET_OF(T, i));
+
+ // Convert from integer to floating point.
+ __ mov(lr, Operand(42));
+ __ vmov(s31, lr);
+ __ vcvt_f64_s32(d4, s31);
+ __ vstr(d4, r4, OFFSET_OF(T, f));
__ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
CodeDesc desc;
@@ -278,12 +301,20 @@
t.a = 1.5;
t.b = 2.75;
t.c = 17.17;
- t.d = 4.5;
- t.e = 9.0;
+ t.d = 0.0;
+ t.e = 0.0;
+ t.f = 0.0;
+ t.i = 0;
+ t.x = 4.5;
+ t.y = 9.0;
Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
USE(dummy);
- CHECK_EQ(4.5, t.e);
- CHECK_EQ(9.0, t.d);
+ CHECK_EQ(4.5, t.y);
+ CHECK_EQ(9.0, t.x);
+ CHECK_EQ(2, t.i);
+ CHECK_EQ(42.0, t.f);
+ CHECK_EQ(1.0, t.e);
+ CHECK_EQ(1.000000059604644775390625, t.d);
CHECK_EQ(4.25, t.c);
CHECK_EQ(4.25, t.b);
CHECK_EQ(1.5, t.a);
=======================================
--- /branches/bleeding_edge/test/cctest/test-disasm-arm.cc Wed Jul 21
00:42:51 2010
+++ /branches/bleeding_edge/test/cctest/test-disasm-arm.cc Thu Aug 26
01:53:00 2010
@@ -422,6 +422,19 @@
COMPARE(vmov(d3, d3, eq),
"0eb03b43 vmov.f64eq d3, d3");
+ COMPARE(vmov(s0, s31),
+ "eeb00a6f vmov.f32 s0, s31");
+ COMPARE(vmov(s31, s0),
+ "eef0fa40 vmov.f32 s31, s0");
+ COMPARE(vmov(r0, s0),
+ "ee100a10 vmov r0, s0");
+ COMPARE(vmov(r10, s31),
+ "ee1faa90 vmov r10, s31");
+ COMPARE(vmov(s0, r0),
+ "ee000a10 vmov s0, r0");
+ COMPARE(vmov(s31, r10),
+ "ee0faa90 vmov s31, r10");
+
COMPARE(vadd(d0, d1, d2),
"ee310b02 vadd.f64 d0, d1, d2");
COMPARE(vadd(d3, d4, d5, mi),
@@ -451,6 +464,41 @@
"eeb70b00 vmov.f64 d0, #1");
COMPARE(vmov(d2, -13.0),
"eeba2b0a vmov.f64 d2, #-13");
+
+ COMPARE(vldr(s0, r0, 0),
+ "ed900a00 vldr s0, [r0 + 4*0]");
+ COMPARE(vldr(s1, r1, 4),
+ "edd10a01 vldr s1, [r1 + 4*1]");
+ COMPARE(vldr(s15, r4, 16),
+ "edd47a04 vldr s15, [r4 + 4*4]");
+ COMPARE(vldr(s16, r5, 20),
+ "ed958a05 vldr s16, [r5 + 4*5]");
+ COMPARE(vldr(s31, r10, 1020),
+ "eddafaff vldr s31, [r10 + 4*255]");
+
+ COMPARE(vstr(s0, r0, 0),
+ "ed800a00 vstr s0, [r0 + 4*0]");
+ COMPARE(vstr(s1, r1, 4),
+ "edc10a01 vstr s1, [r1 + 4*1]");
+ COMPARE(vstr(s15, r8, 8),
+ "edc87a02 vstr s15, [r8 + 4*2]");
+ COMPARE(vstr(s16, r9, 12),
+ "ed898a03 vstr s16, [r9 + 4*3]");
+ COMPARE(vstr(s31, r10, 1020),
+ "edcafaff vstr s31, [r10 + 4*255]");
+
+ COMPARE(vldr(d0, r0, 0),
+ "ed900b00 vldr d0, [r0 + 4*0]");
+ COMPARE(vldr(d1, r1, 4),
+ "ed911b01 vldr d1, [r1 + 4*1]");
+ COMPARE(vldr(d15, r10, 1020),
+ "ed9afbff vldr d15, [r10 + 4*255]");
+ COMPARE(vstr(d0, r0, 0),
+ "ed800b00 vstr d0, [r0 + 4*0]");
+ COMPARE(vstr(d1, r1, 4),
+ "ed811b01 vstr d1, [r1 + 4*1]");
+ COMPARE(vstr(d15, r10, 1020),
+ "ed8afbff vstr d15, [r10 + 4*255]");
}
VERIFY_RUN();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev