Commit 66d13be5 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Fix incorrect encoding of single and double precision registers for some VFP...

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.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5352 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6d5451d6
......@@ -1809,6 +1809,7 @@ void Assembler::stc2(Coprocessor coproc,
// Support for VFP.
void Assembler::vldr(const DwVfpRegister dst,
const Register base,
int offset,
......@@ -1838,7 +1839,9 @@ void Assembler::vldr(const SwVfpRegister dst,
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 @@ void Assembler::vstr(const SwVfpRegister src,
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 @@ void Assembler::vmov(const SwVfpRegister dst,
// 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 @@ void Assembler::vmov(const SwVfpRegister dst,
// 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 @@ void Assembler::vmov(const Register dst,
// 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 @@ static bool IsDoubleVFPType(VFPType type) {
}
// 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 @@ static Instr EncodeVCVT(const VFPType dst_type,
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 @@ static Instr EncodeVCVT(const VFPType dst_type,
// 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 @@ static Instr EncodeVCVT(const VFPType dst_type,
// 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);
}
......
......@@ -120,6 +120,11 @@ struct SwVfpRegister {
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 @@ struct DwVfpRegister {
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_;
};
......
......@@ -194,6 +194,13 @@ enum SoftwareInterruptCodes {
};
// Type of VFP register. Determines register encoding.
enum VFPRegPrecision {
kSinglePrecision = 0,
kDoublePrecision = 1
};
typedef int32_t instr_t;
......@@ -269,6 +276,15 @@ class Instr {
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 @@ class Instr {
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);
};
......
......@@ -463,7 +463,7 @@ int Decoder::FormatOption(Instr* instr, const char* format) {
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 @@ void Decoder::DecodeType3(Instr* instr) {
if (instr->HasW()) {
ASSERT(instr->Bits(5, 4) == 0x1);
if (instr->Bit(22) == 0x1) {
Format(instr, "usat 'rd, 'imm05@16, 'rm'shift_sat");
Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
} else {
UNREACHABLE(); // SSAT.
}
......@@ -1269,17 +1269,19 @@ void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
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*'imm08@00]");
} else {
Format(instr, "vstr'cond 'Sd, ['rn - 4*'off8]");
Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
}
break;
case 0xC:
case 0xE:
if (instr->HasL()) {
Format(instr, "vldr'cond 'Sd, ['rn + 4*'off8]");
Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
} else {
Format(instr, "vstr'cond 'Sd, ['rn + 4*'off8]");
Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
}
break;
default:
......@@ -1300,16 +1302,16 @@ void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
break;
case 0x8:
if (instr->HasL()) {
Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]");
Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
} else {
Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]");
Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
}
break;
case 0xC:
if (instr->HasL()) {
Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]");
Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
} else {
Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]");
Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
}
break;
default:
......
......@@ -2281,13 +2281,6 @@ void Simulator::DecodeUnconditional(Instr* 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)
// The Following ARMv7 VFPv instructions are currently supported.
// vmov :Sn = Rt
......@@ -2305,9 +2298,10 @@ void Simulator::DecodeTypeVFP(Instr* instr) {
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 @@ void Simulator::DecodeTypeVFP(Instr* instr) {
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 @@ void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) {
(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 @@ void Simulator::DecodeVCMP(Instr* instr) {
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 @@ void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) {
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());
VFPRegPrecision dst_precision = kDoublePrecision;
VFPRegPrecision src_precision = kSinglePrecision;
if (instr->SzField() == 1) {
dst_precision = kSinglePrecision;
src_precision = kDoublePrecision;
}
if (double_to_single) {
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 @@ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
(((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 @@ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
UNIMPLEMENTED(); // Not used by V8.
}
int dst = GlueRegCode(true, vd, d);
int src = GlueRegCode(!dp_operation, vm, m);
int dst = instr->VFPDRegCode(kSinglePrecision);
int src = instr->VFPMRegCode(src_precision);
if (dp_operation) {
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 @@ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
} 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 @@ void Simulator::DecodeType6CoprocessorIns(Instr* instr) {
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;
......
......@@ -226,13 +226,17 @@ TEST(4) {
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 @@ TEST(4) {
__ 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 @@ TEST(4) {
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);
......
......@@ -422,6 +422,19 @@ TEST(Vfp) {
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 @@ TEST(Vfp) {
"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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment