Commit 2618422e authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

ARMv7 ubfx support

Patch from Kun Zhang <zhangk@codeaurora.org>, see http://codereview.chromium.org/569015.
Review URL: http://codereview.chromium.org/573027

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3804 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f119ecbc
......@@ -51,9 +51,14 @@ void CpuFeatures::Probe() {
// If the compiler is allowed to use vfp then we can use vfp too in our
// code generation.
#if !defined(__arm__)
// For the simulator=arm build, always use VFP since the arm simulator has
// VFP support.
supported_ |= 1u << VFP3;
// For the simulator=arm build, use VFP when FLAG_enable_vfp3 is enabled.
if (FLAG_enable_vfp3) {
supported_ |= 1u << VFP3;
}
// For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
if (FLAG_enable_armv7) {
supported_ |= 1u << ARMv7;
}
#else
if (Serializer::enabled()) {
supported_ |= OS::CpuFeaturesImpliedByPlatform();
......@@ -66,6 +71,11 @@ void CpuFeatures::Probe() {
supported_ |= 1u << VFP3;
found_by_runtime_probing_ |= 1u << VFP3;
}
if (OS::ArmCpuHasFeature(ARMv7)) {
supported_ |= 1u << ARMv7;
found_by_runtime_probing_ |= 1u << ARMv7;
}
#endif
}
......@@ -850,6 +860,21 @@ void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t
// Data-processing instructions.
// UBFX <Rd>,<Rn>,#<lsb>,#<width - 1>
// Instruction details available in ARM DDI 0406A, A8-464.
// cond(31-28) | 01111(27-23)| 1(22) | 1(21) | widthm1(20-16) |
// Rd(15-12) | lsb(11-7) | 101(6-4) | Rn(3-0)
void Assembler::ubfx(Register dst, Register src1, const Operand& src2,
const Operand& src3, Condition cond) {
ASSERT(!src2.rm_.is_valid() && !src3.rm_.is_valid());
ASSERT(static_cast<uint32_t>(src2.imm32_) <= 0x1f);
ASSERT(static_cast<uint32_t>(src3.imm32_) <= 0x1f);
emit(cond | 0x3F*B21 | src3.imm32_*B16 |
dst.code()*B12 | src2.imm32_*B7 | 0x5*B4 | src1.code());
}
void Assembler::and_(Register dst, Register src1, const Operand& src2,
SBit s, Condition cond) {
addrmod1(cond | 0*B21 | s, src1, dst, src2);
......
......@@ -628,6 +628,9 @@ class Assembler : public Malloced {
void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
// Data-processing instructions
void ubfx(Register dst, Register src1, const Operand& src2,
const Operand& src3, Condition cond = al);
void and_(Register dst, Register src1, const Operand& src2,
SBit s = LeaveCC, Condition cond = al);
......
......@@ -5843,6 +5843,7 @@ const char* GenericBinaryOpStub::GetName() {
}
void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// r1 : x
// r0 : y
......@@ -6035,9 +6036,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
case Token::SAR:
// Remove tags from right operand.
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // y
// Use only the 5 least significant bits of the shift count.
__ and_(r2, r2, Operand(0x1f));
__ GetLeastBitsFromSmi(r2, r0, 5);
__ mov(r0, Operand(r1, ASR, r2));
// Smi tag result.
__ bic(r0, r0, Operand(kSmiTagMask));
......@@ -6046,9 +6045,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// Remove tags from operands. We can't do this on a 31 bit number
// because then the 0s get shifted into bit 30 instead of bit 31.
__ mov(r3, Operand(r1, ASR, kSmiTagSize)); // x
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // y
// Use only the 5 least significant bits of the shift count.
__ and_(r2, r2, Operand(0x1f));
__ GetLeastBitsFromSmi(r2, r0, 5);
__ mov(r3, Operand(r3, LSR, r2));
// Unsigned shift is not allowed to produce a negative number, so
// check the sign bit and the sign bit after Smi tagging.
......@@ -6060,9 +6057,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
case Token::SHL:
// Remove tags from operands.
__ mov(r3, Operand(r1, ASR, kSmiTagSize)); // x
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // y
// Use only the 5 least significant bits of the shift count.
__ and_(r2, r2, Operand(0x1f));
__ GetLeastBitsFromSmi(r2, r0, 5);
__ mov(r3, Operand(r3, LSL, r2));
// Check that the signed result fits in a Smi.
__ add(r2, r3, Operand(0x40000000), SetCC);
......
......@@ -429,12 +429,22 @@ int Decoder::FormatOption(Instr* instr, const char* format) {
return 3;
}
case 'o': {
if (format[3] == '1') {
if ((format[3] == '1') && (format[4] == '2')) {
// 'off12: 12-bit offset for load and store instructions
ASSERT(STRING_STARTS_WITH(format, "off12"));
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d", instr->Offset12Field());
return 5;
} else if ((format[3] == '1') && (format[4] == '6')) {
ASSERT(STRING_STARTS_WITH(format, "off16to20"));
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d", instr->Bits(20, 16) +1);
return 9;
} else if (format[3] == '7') {
ASSERT(STRING_STARTS_WITH(format, "off7to11"));
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d", instr->ShiftAmountField());
return 8;
}
// 'off8: 8-bit offset for extra load and store instructions
ASSERT(STRING_STARTS_WITH(format, "off8"));
......@@ -795,7 +805,18 @@ void Decoder::DecodeType3(Instr* instr) {
break;
}
case 3: {
Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField());
uint32_t msbit = widthminus1 + lsbit;
if (msbit <= 31) {
Format(instr, "ubfx'cond 'rd, 'rm, #'off7to11, #'off16to20");
} else {
UNREACHABLE();
}
} else {
Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
}
break;
}
default: {
......
......@@ -1106,6 +1106,18 @@ void MacroAssembler::IntegerToDoubleConversionWithVFP3(Register inReg,
}
void MacroAssembler::GetLeastBitsFromSmi(Register dst,
Register src,
int num_least_bits) {
if (CpuFeatures::IsSupported(ARMv7)) {
ubfx(dst, src, Operand(kSmiTagSize), Operand(num_least_bits - 1));
} else {
mov(dst, Operand(src, ASR, kSmiTagSize));
and_(dst, dst, Operand((1 << num_least_bits) - 1));
}
}
void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
// All parameters are on the stack. r0 has the return value after call.
......
......@@ -287,6 +287,9 @@ class MacroAssembler: public Assembler {
// occurred.
void IllegalOperation(int num_arguments);
// Get the number of least significant bits from a register
void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
// Uses VFP instructions to Convert a Smi to a double.
void IntegerToDoubleConversionWithVFP3(Register inReg,
Register outHighReg,
......
......@@ -1741,7 +1741,7 @@ void Simulator::DecodeType2(Instr* instr) {
void Simulator::DecodeType3(Instr* instr) {
ASSERT(instr->Bit(4) == 0);
ASSERT(instr->Bits(6, 4) == 0x5 || instr->Bit(4) == 0);
int rd = instr->RdField();
int rn = instr->RnField();
int32_t rn_val = get_register(rn);
......@@ -1768,10 +1768,26 @@ void Simulator::DecodeType3(Instr* instr) {
break;
}
case 3: {
// Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
addr = rn_val + shifter_operand;
if (instr->HasW()) {
set_register(rn, addr);
if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField());
uint32_t msbit = widthminus1 + lsbit;
if (msbit <= 31) {
uint32_t rm_val =
static_cast<uint32_t>(get_register(instr->RmField()));
uint32_t extr_val = rm_val << (31 - msbit);
extr_val = extr_val >> (31 - widthminus1);
set_register(instr->RdField(), extr_val);
} else {
UNREACHABLE();
}
return;
} else {
// Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
addr = rn_val + shifter_operand;
if (instr->HasW()) {
set_register(rn, addr);
}
}
break;
}
......
......@@ -116,6 +116,8 @@ DEFINE_bool(enable_sahf, true,
"enable use of SAHF instruction if available (X64 only)")
DEFINE_bool(enable_vfp3, true,
"enable use of VFP3 instructions if available (ARM only)")
DEFINE_bool(enable_armv7, true,
"enable use of ARMv7 instructions if available (ARM only)")
// bootstrapper.cc
DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
......
......@@ -612,6 +612,7 @@ enum CpuFeature { SSE3 = 32, // x86
RDTSC = 4, // x86
CPUID = 10, // x86
VFP3 = 1, // ARM
ARMv7 = 2, // ARM
SAHF = 0}; // x86
} } // namespace v8::internal
......
......@@ -89,6 +89,8 @@ uint64_t OS::CpuFeaturesImpliedByPlatform() {
// Here gcc is telling us that we are on an ARM and gcc is assuming that we
// have VFP3 instructions. If gcc can assume it then so can we.
return 1u << VFP3;
#elif CAN_USE_ARMV7_INSTRUCTIONS
return 1u << ARMv7;
#else
return 0; // Linux runs on anything.
#endif
......@@ -113,6 +115,9 @@ bool OS::ArmCpuHasFeature(CpuFeature feature) {
case VFP3:
search_string = "vfp";
break;
case ARMv7:
search_string = "ARMv7";
break;
default:
UNREACHABLE();
}
......
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