Commit b7833cb5 authored by vegorov@chromium.org's avatar vegorov@chromium.org

Port of optimized ICs for external and pixel arrays from ia32 to ARM.

Review URL: http://codereview.chromium.org/993002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4228 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 65115c28
......@@ -1341,11 +1341,28 @@ void Assembler::vldr(const DwVfpRegister dst,
// Vdst(15-12) | 1011(11-8) | offset
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(offset % 4 == 0);
ASSERT((offset / 4) < 256);
emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
0xB*B8 | ((offset / 4) & 255));
}
void Assembler::vldr(const SwVfpRegister dst,
const Register base,
int offset,
const Condition cond) {
// Sdst = MEM(Rbase + offset).
// Instruction details available in ARM DDI 0406A, A8-628.
// cond(31-28) | 1101(27-24)| 1001(23-20) | Rbase(19-16) |
// Vdst(15-12) | 1010(11-8) | offset
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(offset % 4 == 0);
ASSERT((offset / 4) < 256);
emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
0xA*B8 | ((offset / 4) & 255));
}
void Assembler::vstr(const DwVfpRegister src,
const Register base,
int offset,
......@@ -1356,6 +1373,7 @@ void Assembler::vstr(const DwVfpRegister src,
// Vsrc(15-12) | 1011(11-8) | (offset/4)
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(offset % 4 == 0);
ASSERT((offset / 4) < 256);
emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 |
0xB*B8 | ((offset / 4) & 255));
}
......@@ -1419,31 +1437,172 @@ void Assembler::vmov(const Register dst,
}
void Assembler::vcvt(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond) {
// Dd = Sm (integer in Sm converted to IEEE 64-bit doubles in Dd).
// Instruction details available in ARM DDI 0406A, A8-576.
// cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=000(18-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
// Type of data to read from or write to VFP register.
// Used as specifier in generic vcvt instruction.
enum VFPType { S32, U32, F32, F64 };
static bool IsSignedVFPType(VFPType type) {
switch (type) {
case S32:
return true;
case U32:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsIntegerVFPType(VFPType type) {
switch (type) {
case S32:
case U32:
return true;
case F32:
case F64:
return false;
default:
UNREACHABLE();
return false;
}
}
static bool IsDoubleVFPType(VFPType type) {
switch (type) {
case F32:
return false;
case F64:
return true;
default:
UNREACHABLE();
return false;
}
}
// 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,
int reg_code,
int* vm,
int* m) {
if (split_last_bit) {
*m = reg_code & 0x1;
*vm = reg_code >> 1;
} else {
*m = (reg_code & 0x10) >> 4;
*vm = reg_code & 0x0F;
}
}
// Encode vcvt.src_type.dst_type instruction.
static Instr EncodeVCVT(const VFPType dst_type,
const int dst_code,
const VFPType src_type,
const int src_code,
const Condition cond) {
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.
// cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
// 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;
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 |
Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
} else {
// Conversion between IEEE double and single precision.
// 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);
return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
}
}
void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 |
dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 |
(0x1 & src.code())*B5 | (src.code() >> 1));
emit(EncodeVCVT(F64, dst.code(), S32, src.code(), cond));
}
void Assembler::vcvt(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond) {
// Sd = Dm (IEEE 64-bit doubles in Dm converted to 32 bit integer in Sd).
// Instruction details available in ARM DDI 0406A, A8-576.
// cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)|
// Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0)
void Assembler::vcvt_f32_s32(const SwVfpRegister dst,
const SwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(EncodeVCVT(F32, dst.code(), S32, src.code(), cond));
}
void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(EncodeVCVT(F64, dst.code(), U32, src.code(), cond));
}
void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(EncodeVCVT(S32, dst.code(), F64, src.code(), cond));
}
void Assembler::vcvt_u32_f64(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(EncodeVCVT(U32, dst.code(), F64, src.code(), cond));
}
void Assembler::vcvt_f64_f32(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(EncodeVCVT(F64, dst.code(), F32, src.code(), cond));
}
void Assembler::vcvt_f32_f64(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 |
0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 |
0x5*B9 | B8 | B7 | B6 | src.code());
emit(EncodeVCVT(F32, dst.code(), F64, src.code(), cond));
}
......
......@@ -826,6 +826,12 @@ class Assembler : public Malloced {
const Register base,
int offset, // Offset must be a multiple of 4.
const Condition cond = al);
void vldr(const SwVfpRegister dst,
const Register base,
int offset, // Offset must be a multiple of 4.
const Condition cond = al);
void vstr(const DwVfpRegister src,
const Register base,
int offset, // Offset must be a multiple of 4.
......@@ -844,12 +850,27 @@ class Assembler : public Malloced {
void vmov(const Register dst,
const SwVfpRegister src,
const Condition cond = al);
void vcvt(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond = al);
void vcvt(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond = al);
void vcvt_f64_s32(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond = al);
void vcvt_f32_s32(const SwVfpRegister dst,
const SwVfpRegister src,
const Condition cond = al);
void vcvt_f64_u32(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond = al);
void vcvt_s32_f64(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond = al);
void vcvt_u32_f64(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond = al);
void vcvt_f64_f32(const DwVfpRegister dst,
const SwVfpRegister src,
const Condition cond = al);
void vcvt_f32_f64(const SwVfpRegister dst,
const DwVfpRegister src,
const Condition cond = al);
void vadd(const DwVfpRegister dst,
const DwVfpRegister src1,
......
This diff is collapsed.
......@@ -660,6 +660,46 @@ class StringCompareStub: public CodeStub {
};
// This stub can convert a signed int32 to a heap number (double). It does
// not work for int32s that are in Smi range! No GC occurs during this stub
// so you don't have to set up the frame.
class WriteInt32ToHeapNumberStub : public CodeStub {
public:
WriteInt32ToHeapNumberStub(Register the_int,
Register the_heap_number,
Register scratch)
: the_int_(the_int),
the_heap_number_(the_heap_number),
scratch_(scratch) { }
private:
Register the_int_;
Register the_heap_number_;
Register scratch_;
// Minor key encoding in 16 bits.
class IntRegisterBits: public BitField<int, 0, 4> {};
class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
class ScratchRegisterBits: public BitField<int, 8, 4> {};
Major MajorKey() { return WriteInt32ToHeapNumber; }
int MinorKey() {
// Encode the parameters in a unique 16 bit value.
return IntRegisterBits::encode(the_int_.code())
| HeapNumberRegisterBits::encode(the_heap_number_.code())
| ScratchRegisterBits::encode(scratch_.code());
}
void Generate(MacroAssembler* masm);
const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
#ifdef DEBUG
void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
#endif
};
class NumberToStringStub: public CodeStub {
public:
NumberToStringStub() { }
......
......@@ -81,9 +81,27 @@ const char* VFPRegisters::names_[kNumVFPRegisters] = {
};
const char* VFPRegisters::Name(int reg) {
const char* VFPRegisters::Name(int reg, bool is_double) {
ASSERT((0 <= reg) && (reg < kNumVFPRegisters));
return names_[reg];
return names_[reg + is_double ? kNumVFPSingleRegisters : 0];
}
int VFPRegisters::Number(const char* name, bool* is_double) {
for (int i = 0; i < kNumVFPRegisters; i++) {
if (strcmp(names_[i], name) == 0) {
if (i < kNumVFPSingleRegisters) {
*is_double = false;
return i;
} else {
*is_double = true;
return i - kNumVFPSingleRegisters;
}
}
}
// No register with the requested name found.
return kNoRegister;
}
......@@ -104,7 +122,7 @@ int Registers::Number(const char* name) {
i++;
}
// No register with the reguested name found.
// No register with the requested name found.
return kNoRegister;
}
......
......@@ -84,7 +84,10 @@ namespace arm {
static const int kNumRegisters = 16;
// VFP support.
static const int kNumVFPRegisters = 48;
static const int kNumVFPSingleRegisters = 32;
static const int kNumVFPDoubleRegisters = 16;
static const int kNumVFPRegisters =
kNumVFPSingleRegisters + kNumVFPDoubleRegisters;
// PC is register 15.
static const int kPCRegister = 15;
......@@ -254,6 +257,14 @@ class Instr {
inline int RtField() const { return Bits(15, 12); }
inline int PField() const { return Bit(24); }
inline int UField() const { return Bit(23); }
inline int Opc1Field() const { return (Bit(23) << 2) | Bits(21, 20); }
inline int Opc2Field() const { return Bits(19, 16); }
inline int Opc3Field() const { return Bits(7, 6); }
inline int SzField() const { return Bit(8); }
inline int VLField() const { return Bit(20); }
inline int VCField() const { return Bit(8); }
inline int VAField() const { return Bits(23, 21); }
inline int VBField() const { return Bits(6, 5); }
// Fields used in Data processing instructions
inline Opcode OpcodeField() const {
......@@ -344,7 +355,12 @@ class Registers {
class VFPRegisters {
public:
// Return the name of the register.
static const char* Name(int reg);
static const char* Name(int reg, bool is_double);
// Lookup the register number for the name provided.
// Set flag pointed by is_double to true if register
// is double-precision.
static int Number(const char* name, bool* is_double);
private:
static const char* names_[kNumVFPRegisters];
......
......@@ -129,6 +129,10 @@ class Decoder {
void DecodeTypeVFP(Instr* instr);
void DecodeType6CoprocessorIns(Instr* instr);
void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr);
void DecodeVCMP(Instr* instr);
void DecodeVCVTBetweenDoubleAndSingle(Instr* instr);
void DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr);
const disasm::NameConverter& converter_;
v8::internal::Vector<char> out_buffer_;
......@@ -181,12 +185,12 @@ void Decoder::PrintRegister(int reg) {
// Print the VFP S register name according to the active name converter.
void Decoder::PrintSRegister(int reg) {
Print(assembler::arm::VFPRegisters::Name(reg));
Print(assembler::arm::VFPRegisters::Name(reg, false));
}
// Print the VFP D register name according to the active name converter.
void Decoder::PrintDRegister(int reg) {
Print(assembler::arm::VFPRegisters::Name(reg + 32));
Print(assembler::arm::VFPRegisters::Name(reg, true));
}
......@@ -930,87 +934,151 @@ void Decoder::DecodeUnconditional(Instr* instr) {
// VMRS
void Decoder::DecodeTypeVFP(Instr* instr) {
ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
if (instr->Bit(23) == 1) {
if ((instr->Bits(21, 19) == 0x7) &&
(instr->Bits(18, 16) == 0x5) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 1) &&
(instr->Bit(6) == 1) &&
(instr->Bit(4) == 0)) {
Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
} else if ((instr->Bits(21, 19) == 0x7) &&
(instr->Bits(18, 16) == 0x0) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 1) &&
(instr->Bit(7) == 1) &&
(instr->Bit(6) == 1) &&
(instr->Bit(4) == 0)) {
Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
} else if ((instr->Bit(21) == 0x0) &&
(instr->Bit(20) == 0x0) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 1) &&
(instr->Bit(6) == 0) &&
(instr->Bit(4) == 0)) {
ASSERT(instr->Bits(11, 9) == 0x5);
if (instr->Bit(4) == 0) {
if (instr->Opc1Field() == 0x7) {
// Other data processing instructions
if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) {
DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) {
DecodeVCVTBetweenFloatingPointAndInteger(instr);
} else if (((instr->Opc2Field() >> 1) == 0x6) &&
(instr->Opc3Field() & 0x1)) {
DecodeVCVTBetweenFloatingPointAndInteger(instr);
} else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
(instr->Opc3Field() & 0x1)) {
DecodeVCMP(instr);
} else {
Unknown(instr); // Not used by V8.
}
} else if (instr->Opc1Field() == 0x3) {
if (instr->SzField() == 0x1) {
if (instr->Opc3Field() & 0x1) {
Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
} else {
Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
}
} else {
Unknown(instr); // Not used by V8.
}
} else if ((instr->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) {
if (instr->SzField() == 0x1) {
Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
} else {
Unknown(instr); // Not used by V8.
}
} else if ((instr->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) {
if (instr->SzField() == 0x1) {
Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
} else if ((instr->Bits(21, 20) == 0x3) &&
(instr->Bits(19, 16) == 0x4) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 0x1) &&
(instr->Bit(6) == 0x1) &&
(instr->Bit(4) == 0x0)) {
Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
} else if ((instr->Bits(23, 20) == 0xF) &&
(instr->Bits(19, 16) == 0x1) &&
(instr->Bits(11, 8) == 0xA) &&
(instr->Bits(7, 5) == 0x0) &&
(instr->Bit(4) == 0x1) &&
(instr->Bits(3, 0) == 0x0)) {
if (instr->Bits(15, 12) == 0xF)
Format(instr, "vmrs'cond APSR, FPSCR");
else
Unknown(instr); // Not used by V8.
} else {
Unknown(instr); // Not used by V8.
}
} else {
Unknown(instr); // Not used by V8.
}
} else if (instr->Bit(21) == 1) {
if ((instr->Bit(20) == 0x1) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 0x1) &&
(instr->Bit(6) == 0) &&
(instr->Bit(4) == 0)) {
Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
} else if ((instr->Bit(20) == 0x1) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 0x1) &&
(instr->Bit(6) == 1) &&
(instr->Bit(4) == 0)) {
Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
} else if ((instr->Bit(20) == 0x0) &&
(instr->Bits(11, 9) == 0x5) &&
(instr->Bit(8) == 0x1) &&
(instr->Bit(6) == 0) &&
(instr->Bit(4) == 0)) {
Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
} else {
if ((instr->VCField() == 0x0) &&
(instr->VAField() == 0x0)) {
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
} else if ((instr->VLField() == 0x1) &&
(instr->VCField() == 0x0) &&
(instr->VAField() == 0x7) &&
(instr->Bits(19, 16) == 0x1)) {
if (instr->Bits(15, 12) == 0xF)
Format(instr, "vmrs'cond APSR, FPSCR");
else
Unknown(instr); // Not used by V8.
} else {
Unknown(instr); // Not used by V8.
}
}
}
void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) {
ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) &&
(instr->VAField() == 0x0));
bool to_arm_register = (instr->VLField() == 0x1);
if (to_arm_register) {
Format(instr, "vmov'cond 'rt, 'Sn");
} else {
Format(instr, "vmov'cond 'Sn, 'rt");
}
}
void Decoder::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);
bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
if (dp_operation && !raise_exception_for_qnan) {
Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
} else {
Unknown(instr); // Not used by V8.
}
}
void Decoder::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);
if (double_to_single) {
Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm");
} else {
Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm");
}
}
void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) ||
(((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1)));
bool to_integer = (instr->Bit(18) == 1);
bool dp_operation = (instr->SzField() == 1);
if (to_integer) {
bool unsigned_integer = (instr->Bit(16) == 0);
if (dp_operation) {
if (unsigned_integer) {
Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm");
} else {
Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
}
} else {
if (unsigned_integer) {
Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm");
} else {
Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm");
}
}
} else {
if ((instr->Bit(20) == 0x0) &&
(instr->Bits(11, 8) == 0xA) &&
(instr->Bits(6, 5) == 0x0) &&
(instr->Bit(4) == 1) &&
(instr->Bits(3, 0) == 0x0)) {
Format(instr, "vmov'cond 'Sn, 'rt");
} else if ((instr->Bit(20) == 0x1) &&
(instr->Bits(11, 8) == 0xA) &&
(instr->Bits(6, 5) == 0x0) &&
(instr->Bit(4) == 1) &&
(instr->Bits(3, 0) == 0x0)) {
Format(instr, "vmov'cond 'rt, 'Sn");
bool unsigned_integer = (instr->Bit(7) == 0);
if (dp_operation) {
if (unsigned_integer) {
Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm");
} else {
Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
}
} else {
Unknown(instr); // Not used by V8.
if (unsigned_integer) {
Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm");
} else {
Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm");
}
}
}
}
......@@ -1024,9 +1092,27 @@ void Decoder::DecodeTypeVFP(Instr* instr) {
void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
ASSERT((instr->TypeField() == 6));
if (instr->CoprocessorField() != 0xB) {
Unknown(instr); // Not used by V8.
} else {
if (instr->CoprocessorField() == 0xA) {
switch (instr->OpcodeField()) {
case 0x8:
if (instr->HasL()) {
Format(instr, "vldr'cond 'Sd, ['rn - 4*'off8]");
} else {
Format(instr, "vstr'cond 'Sd, ['rn - 4*'off8]");
}
break;
case 0xC:
if (instr->HasL()) {
Format(instr, "vldr'cond 'Sd, ['rn + 4*'off8]");
} else {
Format(instr, "vstr'cond 'Sd, ['rn + 4*'off8]");
}
break;
default:
Unknown(instr); // Not used by V8.
break;
}
} else if (instr->CoprocessorField() == 0xB) {
switch (instr->OpcodeField()) {
case 0x2:
// Load and store double to two GP registers
......@@ -1056,6 +1142,8 @@ void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
Unknown(instr); // Not used by V8.
break;
}
} else {
UNIMPLEMENTED(); // Not used by V8.
}
}
......
This diff is collapsed.
......@@ -1192,7 +1192,7 @@ void MacroAssembler::IntegerToDoubleConversionWithVFP3(Register inReg,
// ARMv7 VFP3 instructions to implement integer to double conversion.
mov(r7, Operand(inReg, ASR, kSmiTagSize));
vmov(s15, r7);
vcvt(d7, s15);
vcvt_f64_s32(d7, s15);
vmov(outLowReg, outHighReg, d7);
}
......@@ -1455,6 +1455,58 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
}
// Allocates a heap number or jumps to the need_gc label if the young space
// is full and a scavenge is needed.
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
Label* gc_required) {
// Allocate an object in the heap for the heap number and tag it as a heap
// object.
AllocateInNewSpace(HeapNumber::kSize / kPointerSize,
result,
scratch1,
scratch2,
gc_required,
TAG_OBJECT);
// Get heap number map and store it in the allocated object.
LoadRoot(scratch1, Heap::kHeapNumberMapRootIndex);
str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
}
void MacroAssembler::CountLeadingZeros(Register source,
Register scratch,
Register zeros) {
#ifdef CAN_USE_ARMV5_INSTRUCTIONS
clz(zeros, source); // This instruction is only supported after ARM5.
#else
mov(zeros, Operand(0));
mov(scratch, source);
// Top 16.
tst(scratch, Operand(0xffff0000));
add(zeros, zeros, Operand(16), LeaveCC, eq);
mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq);
// Top 8.
tst(scratch, Operand(0xff000000));
add(zeros, zeros, Operand(8), LeaveCC, eq);
mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq);
// Top 4.
tst(scratch, Operand(0xf0000000));
add(zeros, zeros, Operand(4), LeaveCC, eq);
mov(scratch, Operand(scratch, LSL, 4), LeaveCC, eq);
// Top 2.
tst(scratch, Operand(0xc0000000));
add(zeros, zeros, Operand(2), LeaveCC, eq);
mov(scratch, Operand(scratch, LSL, 2), LeaveCC, eq);
// Top bit.
tst(scratch, Operand(0x80000000u));
add(zeros, zeros, Operand(1), LeaveCC, eq);
#endif
}
void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
Register first,
Register second,
......
......@@ -239,6 +239,12 @@ class MacroAssembler: public Assembler {
Register scratch2,
Label* gc_required);
// Allocates a heap number or jumps to the need_gc label if the young space
// is full and a scavenge is needed.
void AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
Label* gc_required);
// ---------------------------------------------------------------------------
// Support functions.
......@@ -319,6 +325,12 @@ class MacroAssembler: public Assembler {
Register outHighReg,
Register outLowReg);
// Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz
// instruction. On pre-ARM5 hardware this routine gives the wrong answer
// for 0 (31 instead of 32).
void CountLeadingZeros(Register source,
Register scratch,
Register zeros);
// ---------------------------------------------------------------------------
// Runtime calls
......
This diff is collapsed.
......@@ -231,6 +231,11 @@ class Simulator {
void DecodeTypeVFP(Instr* instr);
void DecodeType6CoprocessorIns(Instr* instr);
void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr);
void DecodeVCMP(Instr* instr);
void DecodeVCVTBetweenDoubleAndSingle(Instr* instr);
void DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr);
// Executes one instruction.
void InstructionDecode(Instr* instr);
......
......@@ -174,6 +174,15 @@ const int kBitsPerByteLog2 = 3;
const int kBitsPerPointer = kPointerSize * kBitsPerByte;
const int kBitsPerInt = kIntSize * kBitsPerByte;
// IEEE 754 single precision floating point number bit layout.
const uint32_t kBinary32SignMask = 0x80000000u;
const uint32_t kBinary32ExponentMask = 0x7f800000u;
const uint32_t kBinary32MantissaMask = 0x007fffffu;
const int kBinary32ExponentBias = 127;
const int kBinary32MaxExponent = 0xFE;
const int kBinary32MinExponent = 0x01;
const int kBinary32MantissaBits = 23;
const int kBinary32ExponentShift = 23;
// Zap-value: The value used for zapping dead objects.
// Should be a recognizable hex value tagged as a heap object pointer.
......
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