39 #if defined(V8_TARGET_ARCH_ARM)
48 bool CpuFeatures::initialized_ =
false;
50 unsigned CpuFeatures::supported_ = 0;
51 unsigned CpuFeatures::found_by_runtime_probing_ = 0;
58 static uint64_t CpuFeaturesImpliedByCompiler() {
60 #ifdef CAN_USE_ARMV7_INSTRUCTIONS
61 answer |= 1u <<
ARMv7;
62 #endif // def CAN_USE_ARMV7_INSTRUCTIONS
63 #ifdef CAN_USE_VFP_INSTRUCTIONS
65 #endif // def CAN_USE_VFP_INSTRUCTIONS
71 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \
72 && !defined(__SOFTFP__)
74 #endif // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__)
84 CpuFeaturesImpliedByCompiler());
85 ASSERT(supported_ == 0 || supported_ == standard_features);
93 supported_ |= standard_features;
103 if (FLAG_enable_vfp3) {
107 if (FLAG_enable_armv7) {
108 supported_ |= 1u <<
ARMv7;
117 found_by_runtime_probing_ |= 1u <<
VFP3 | 1u <<
ARMv7;
121 supported_ |= 1u <<
ARMv7;
122 found_by_runtime_probing_ |= 1u <<
ARMv7;
131 const int RelocInfo::kApplyMask = 0;
134 bool RelocInfo::IsCodedSpecially() {
146 for (
int i = 0; i < instruction_count; i++) {
147 *(pc + i) = *(instr + i);
157 void RelocInfo::PatchCodeWithCall(
Address target,
int guard_bytes) {
167 Operand::Operand(Handle<Object> handle) {
172 if (obj->IsHeapObject()) {
173 imm32_ =
reinterpret_cast<intptr_t
>(handle.location());
174 rmode_ = RelocInfo::EMBEDDED_OBJECT;
177 imm32_ =
reinterpret_cast<intptr_t
>(obj);
183 Operand::Operand(Register rm,
ShiftOp shift_op,
int shift_imm) {
185 ASSERT(shift_op !=
ROR || shift_imm != 0);
188 shift_op_ = shift_op;
189 shift_imm_ = shift_imm & 31;
190 if (shift_op ==
RRX) {
199 Operand::Operand(Register rm,
ShiftOp shift_op, Register rs) {
203 shift_op_ = shift_op;
229 shift_op_ = shift_op;
230 shift_imm_ = shift_imm & 31;
290 static const int kMinimalBufferSize = 4*
KB;
294 : AssemblerBase(arg_isolate),
295 positions_recorder_(this),
296 emit_debug_code_(FLAG_debug_code) {
297 if (buffer ==
NULL) {
303 buffer =
isolate()->assembler_spare_buffer();
307 if (buffer ==
NULL) {
308 buffer_ = NewArray<byte>(buffer_size);
310 buffer_ =
static_cast<byte*
>(buffer);
312 buffer_size_ = buffer_size;
318 buffer_ =
static_cast<byte*
>(buffer);
319 buffer_size_ = buffer_size;
326 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
327 num_pending_reloc_info_ = 0;
328 next_buffer_check_ = 0;
329 const_pool_blocked_nesting_ = 0;
330 no_const_pool_before_ = 0;
331 first_const_pool_use_ = -1;
338 ASSERT(const_pool_blocked_nesting_ == 0);
342 isolate()->set_assembler_spare_buffer(buffer_);
353 ASSERT(num_pending_reloc_info_ == 0);
356 desc->buffer = buffer_;
357 desc->buffer_size = buffer_size_;
359 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
404 return positive ? offset : -offset;
411 if (!positive) offset = -offset;
414 instr = (instr & ~
B23) | (positive ?
B23 : 0);
427 bool positive = offset >= 0;
428 if (!positive) offset = -offset;
431 instr = (instr & ~B23) | (positive ? B23 : 0);
550 const int kEndOfChain = -4;
562 ((instr &
B24) != 0)) {
573 ASSERT(target_pos == kEndOfChain || target_pos >= 0);
589 int imm24 = imm26 >> 2;
595 void Assembler::print(Label*
L) {
596 if (L->is_unused()) {
598 }
else if (L->is_bound()) {
599 PrintF(
"bound label to %d\n", L->pos());
600 }
else if (L->is_linked()) {
603 while (l.is_linked()) {
617 if ((instr &
B24) != 0)
623 case eq: c =
"eq";
break;
624 case ne: c =
"ne";
break;
625 case hs: c =
"hs";
break;
626 case lo: c =
"lo";
break;
627 case mi: c =
"mi";
break;
628 case pl: c =
"pl";
break;
629 case vs: c =
"vs";
break;
630 case vc: c =
"vc";
break;
631 case hi: c =
"hi";
break;
632 case ls: c =
"ls";
break;
633 case ge: c =
"ge";
break;
634 case lt: c =
"lt";
break;
635 case gt: c =
"gt";
break;
636 case le: c =
"le";
break;
637 case al: c =
"";
break;
648 PrintF(
"label in inconsistent state (pos = %d)\n", L->pos_);
653 void Assembler::bind_to(Label* L,
int pos) {
655 while (L->is_linked()) {
656 int fixup_pos = L->pos();
664 if (pos > last_bound_pos_)
665 last_bound_pos_ = pos;
669 void Assembler::link_to(Label* L, Label* appendix) {
670 if (appendix->is_linked()) {
671 if (L->is_linked()) {
679 ASSERT(link == kEndOfChain);
696 void Assembler::next(Label* L) {
699 if (link == kEndOfChain) {
708 static Instr EncodeMovwImmediate(uint32_t immediate) {
709 ASSERT(immediate < 0x10000);
710 return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
718 static bool fits_shifter(uint32_t imm32,
719 uint32_t* rotate_imm,
723 for (
int rot = 0; rot < 16; rot++) {
724 uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
725 if ((imm8 <= 0xff)) {
735 if (fits_shifter(~imm32, rotate_imm, immed_8,
NULL)) {
740 if (imm32 < 0x10000) {
742 *instr |= EncodeMovwImmediate(imm32);
743 *rotate_imm = *immed_8 = 0;
749 if (fits_shifter(-imm32, rotate_imm, immed_8,
NULL)) {
755 if (alu_insn ==
ADD ||
757 if (fits_shifter(-imm32, rotate_imm, immed_8,
NULL)) {
761 }
else if (alu_insn ==
AND ||
763 if (fits_shifter(~imm32, rotate_imm, immed_8,
NULL)) {
778 bool Operand::must_use_constant_pool()
const {
779 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
793 bool Operand::is_single_instruction(
Instr instr)
const {
794 if (rm_.is_valid())
return true;
795 uint32_t dummy1, dummy2;
796 if (must_use_constant_pool() ||
797 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
802 if (must_use_constant_pool() ||
826 void Assembler::addrmod1(
Instr instr,
832 if (!x.rm_.is_valid()) {
836 if (x.must_use_constant_pool() ||
837 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
845 if (x.must_use_constant_pool() ||
847 RecordRelocInfo(x.rmode_, x.imm32_);
851 mov(rd, Operand(x.imm32_ & 0xffff),
LeaveCC, cond);
852 movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
857 if (!x.must_use_constant_pool() &&
861 RecordRelocInfo(x.rmode_, x.imm32_);
864 addrmod1(instr, rn, rd, Operand(
ip));
868 instr |=
I | rotate_imm*
B8 | immed_8;
869 }
else if (!x.rs_.is_valid()) {
871 instr |= x.shift_imm_*
B7 | x.shift_op_ | x.rm_.code();
874 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
875 instr |= x.rs_.code()*
B8 | x.shift_op_ |
B4 | x.rm_.code();
877 emit(instr | rn.code()*
B16 | rd.code()*
B12);
878 if (rn.is(pc) || x.rm_.is(pc)) {
885 void Assembler::addrmod2(
Instr instr, Register rd,
const MemOperand& x) {
888 if (!x.rm_.is_valid()) {
890 int offset_12 = x.offset_;
892 offset_12 = -offset_12;
898 ASSERT(!x.rn_.is(
ip) && ((instr &
L) == L || !rd.is(
ip)));
910 instr |=
B25 | x.shift_imm_*
B7 | x.shift_op_ | x.rm_.code();
912 ASSERT((am & (
P|
W)) ==
P || !x.rn_.is(pc));
913 emit(instr | am | x.rn_.code()*
B16 | rd.code()*
B12);
917 void Assembler::addrmod3(
Instr instr, Register rd,
const MemOperand& x) {
921 if (!x.rm_.is_valid()) {
923 int offset_8 = x.offset_;
925 offset_8 = -offset_8;
931 ASSERT(!x.rn_.is(
ip) && ((instr &
L) == L || !rd.is(
ip)));
937 instr |=
B | (offset_8 >> 4)*
B8 | (offset_8 & 0xf);
938 }
else if (x.shift_imm_ != 0) {
941 ASSERT(!x.rn_.is(
ip) && ((instr &
L) == L || !rd.is(
ip)));
942 mov(
ip, Operand(x.rm_, x.shift_op_, x.shift_imm_),
LeaveCC,
948 ASSERT((am & (
P|
W)) ==
P || !x.rm_.is(pc));
949 instr |= x.rm_.code();
951 ASSERT((am & (
P|
W)) ==
P || !x.rn_.is(pc));
952 emit(instr | am | x.rn_.code()*
B16 | rd.code()*
B12);
956 void Assembler::addrmod4(
Instr instr, Register rn,
RegList rl) {
960 emit(instr | rn.code()*
B16 | rl);
964 void Assembler::addrmod5(
Instr instr, CRegister crd,
const MemOperand& x) {
968 ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
970 int offset_8 = x.offset_;
971 ASSERT((offset_8 & 3) == 0);
974 offset_8 = -offset_8;
978 ASSERT((am & (
P|
W)) ==
P || !x.rn_.is(pc));
985 emit(instr | am | x.rn_.code()*
B16 | crd.code()*
B12 | offset_8);
992 target_pos = L->pos();
994 if (L->is_linked()) {
995 target_pos = L->pos();
997 target_pos = kEndOfChain;
1011 if (L->is_bound()) {
1012 target_pos = L->pos();
1014 if (L->is_linked()) {
1015 target_pos = L->pos();
1017 target_pos = kEndOfChain;
1019 L->link_to(at_offset);
1027 ASSERT((branch_offset & 3) == 0);
1028 int imm24 = branch_offset >> 2;
1041 ASSERT((branch_offset & 3) == 0);
1042 int imm24 = branch_offset >> 2;
1050 ASSERT((branch_offset & 1) == 0);
1051 int h = ((branch_offset & 2) >> 1)*
B24;
1052 int imm24 = branch_offset >> 2;
1074 void Assembler::and_(Register dst, Register src1,
const Operand& src2,
1076 addrmod1(cond |
AND | s, src1, dst, src2);
1080 void Assembler::eor(Register dst, Register src1,
const Operand& src2,
1082 addrmod1(cond |
EOR | s, src1, dst, src2);
1086 void Assembler::sub(Register dst, Register src1,
const Operand& src2,
1088 addrmod1(cond |
SUB | s, src1, dst, src2);
1092 void Assembler::rsb(Register dst, Register src1,
const Operand& src2,
1094 addrmod1(cond |
RSB | s, src1, dst, src2);
1098 void Assembler::add(Register dst, Register src1,
const Operand& src2,
1100 addrmod1(cond |
ADD | s, src1, dst, src2);
1104 void Assembler::adc(Register dst, Register src1,
const Operand& src2,
1106 addrmod1(cond |
ADC | s, src1, dst, src2);
1110 void Assembler::sbc(Register dst, Register src1,
const Operand& src2,
1112 addrmod1(cond |
SBC | s, src1, dst, src2);
1116 void Assembler::rsc(Register dst, Register src1,
const Operand& src2,
1118 addrmod1(cond |
RSC | s, src1, dst, src2);
1123 addrmod1(cond |
TST |
S, src1,
r0, src2);
1128 addrmod1(cond |
TEQ |
S, src1,
r0, src2);
1133 addrmod1(cond |
CMP |
S, src1,
r0, src2);
1138 Register src,
int raw_immediate,
Condition cond) {
1140 emit(cond |
I |
CMP |
S | src.code() << 16 | raw_immediate);
1145 addrmod1(cond |
CMN |
S, src1,
r0, src2);
1149 void Assembler::orr(Register dst, Register src1,
const Operand& src2,
1151 addrmod1(cond |
ORR | s, src1, dst, src2);
1162 ASSERT(!(src.is_reg() && src.rm().is(dst) && s ==
LeaveCC && cond ==
al));
1163 addrmod1(cond |
MOV | s,
r0, dst, src);
1168 ASSERT(immediate < 0x10000);
1174 emit(cond | 0x34*
B20 | reg.code()*
B12 | EncodeMovwImmediate(immediate));
1178 void Assembler::bic(Register dst, Register src1,
const Operand& src2,
1180 addrmod1(cond |
BIC | s, src1, dst, src2);
1185 addrmod1(cond |
MVN | s,
r0, dst, src);
1190 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1192 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1193 emit(cond |
A | s | dst.code()*
B16 | srcA.code()*
B12 |
1194 src2.code()*
B8 |
B7 |
B4 | src1.code());
1200 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1202 emit(cond | s | dst.code()*
B16 | src2.code()*
B8 |
B7 |
B4 | src1.code());
1212 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1214 emit(cond | B23 |
B22 |
A | s | dstH.code()*
B16 | dstL.code()*
B12 |
1215 src2.code()*
B8 |
B7 |
B4 | src1.code());
1225 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1227 emit(cond | B23 |
B22 | s | dstH.code()*
B16 | dstL.code()*
B12 |
1228 src2.code()*
B8 |
B7 |
B4 | src1.code());
1238 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1240 emit(cond | B23 |
A | s | dstH.code()*
B16 | dstL.code()*
B12 |
1241 src2.code()*
B8 |
B7 |
B4 | src1.code());
1251 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1253 emit(cond | B23 | s | dstH.code()*
B16 | dstL.code()*
B12 |
1254 src2.code()*
B8 |
B7 |
B4 | src1.code());
1261 ASSERT(!dst.is(pc) && !src.is(pc));
1263 15*
B8 |
CLZ | src.code());
1276 ASSERT(!dst.is(pc) && !src.rm_.is(pc));
1277 ASSERT((satpos >= 0) && (satpos <= 31));
1278 ASSERT((src.shift_op_ ==
ASR) || (src.shift_op_ ==
LSL));
1282 if (src.shift_op_ ==
ASR) {
1286 emit(cond | 0x6*
B24 | 0xe*
B20 | satpos*
B16 | dst.code()*
B12 |
1287 src.shift_imm_*
B7 | sh*
B6 | 0x1*
B4 | src.rm_.code());
1304 ASSERT(!dst.is(pc) && !src.is(pc));
1305 ASSERT((lsb >= 0) && (lsb <= 31));
1306 ASSERT((width >= 1) && (width <= (32 - lsb)));
1307 emit(cond | 0xf*B23 |
B22 |
B21 | (width - 1)*
B16 | dst.code()*
B12 |
1308 lsb*
B7 |
B6 |
B4 | src.code());
1324 ASSERT(!dst.is(pc) && !src.is(pc));
1325 ASSERT((lsb >= 0) && (lsb <= 31));
1326 ASSERT((width >= 1) && (width <= (32 - lsb)));
1327 emit(cond | 0xf*B23 |
B21 | (width - 1)*
B16 | dst.code()*
B12 |
1328 lsb*
B7 |
B6 |
B4 | src.code());
1340 ASSERT((lsb >= 0) && (lsb <= 31));
1341 ASSERT((width >= 1) && (width <= (32 - lsb)));
1342 int msb = lsb + width - 1;
1343 emit(cond | 0x1f*
B22 | msb*
B16 | dst.code()*
B12 | lsb*
B7 |
B4 | 0xf);
1358 ASSERT(!dst.is(pc) && !src.is(pc));
1359 ASSERT((lsb >= 0) && (lsb <= 31));
1360 ASSERT((width >= 1) && (width <= (32 - lsb)));
1361 int msb = lsb + width - 1;
1362 emit(cond | 0x1f*
B22 | msb*
B16 | dst.code()*
B12 | lsb*
B7 |
B4 |
1370 emit(cond |
B24 | s | 15*
B16 | dst.code()*
B12);
1378 if (!src.rm_.is_valid()) {
1380 uint32_t rotate_imm;
1382 if (src.must_use_constant_pool() ||
1383 !fits_shifter(src.imm32_, &rotate_imm, &immed_8,
NULL)) {
1385 RecordRelocInfo(src.rmode_, src.imm32_);
1387 msr(fields, Operand(
ip), cond);
1390 instr =
I | rotate_imm*
B8 | immed_8;
1392 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);
1393 instr = src.rm_.code();
1395 emit(cond | instr |
B24 |
B21 | fields | 15*
B12);
1404 addrmod2(cond |
B26 | L, dst, src);
1409 addrmod2(cond |
B26, src, dst);
1414 addrmod2(cond |
B26 |
B | L, dst, src);
1419 addrmod2(cond |
B26 |
B, src, dst);
1424 addrmod3(cond | L |
B7 |
H |
B4, dst, src);
1429 addrmod3(cond |
B7 |
H |
B4, src, dst);
1434 addrmod3(cond | L |
B7 |
S6 |
B4, dst, src);
1439 addrmod3(cond | L |
B7 |
S6 |
H |
B4, dst, src);
1449 ASSERT_EQ(dst1.code() + 1, dst2.code());
1450 addrmod3(cond |
B7 |
B6 |
B4, dst1, src);
1459 ASSERT_EQ(src1.code() + 1, src2.code());
1461 addrmod3(cond |
B7 |
B6 |
B5 |
B4, src1, dst);
1472 addrmod4(cond |
B27 | am | L, base, dst);
1475 if (cond ==
al && (dst & pc.bit()) != 0) {
1490 addrmod4(cond |
B27 | am, base, src);
1509 emit(reinterpret_cast<Instr>(msg));
1511 #else // def __arm__
1512 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
1521 #else // ndef CAN_USE_ARMV5_INSTRUCTIONS
1522 svc(0x9f0001, cond);
1523 #endif // ndef CAN_USE_ARMV5_INSTRUCTIONS
1524 #endif // def __arm__
1536 emit(cond | 15*
B24 | imm24);
1550 crd.code()*
B12 | coproc*
B8 | (opcode_2 & 7)*
B5 | crm.code());
1573 rd.code()*
B12 | coproc*
B8 | (opcode_2 & 7)*
B5 |
B4 | crm.code());
1595 emit(cond |
B27 |
B26 |
B25 | (opcode_1 & 7)*
B21 | L | crn.code()*
B16 |
1596 rd.code()*
B12 | coproc*
B8 | (opcode_2 & 7)*
B5 |
B4 | crm.code());
1615 addrmod5(cond |
B27 |
B26 | l | L | coproc*
B8, crd, src);
1627 emit(cond |
B27 |
B26 |
U | l | L | rn.code()*
B16 | crd.code()*
B12 |
1628 coproc*
B8 | (option & 255));
1652 const Register base,
1667 if ((offset % 4) == 0 && (offset / 4) < 256) {
1668 emit(cond | u*B23 | 0xD1*
B20 | base.code()*
B16 | dst.code()*
B12 |
1669 0xB*
B8 | ((offset / 4) & 255));
1675 add(
ip, base, Operand(offset));
1677 sub(
ip, base, Operand(offset));
1687 ASSERT(!operand.rm().is_valid());
1689 vldr(dst, operand.rn(), operand.offset(), cond);
1694 const Register base,
1708 dst.split_code(&sd, &d);
1711 if ((offset % 4) == 0 && (offset / 4) < 256) {
1712 emit(cond | u*B23 | d*
B22 | 0xD1*
B20 | base.code()*
B16 | sd*
B12 |
1713 0xA*
B8 | ((offset / 4) & 255));
1719 add(
ip, base, Operand(offset));
1721 sub(
ip, base, Operand(offset));
1731 ASSERT(!operand.rm().is_valid());
1733 vldr(dst, operand.rn(), operand.offset(), cond);
1738 const Register base,
1752 if ((offset % 4) == 0 && (offset / 4) < 256) {
1753 emit(cond | u*B23 | 0xD0*
B20 | base.code()*
B16 | src.code()*
B12 |
1754 0xB*
B8 | ((offset / 4) & 255));
1760 add(
ip, base, Operand(offset));
1762 sub(
ip, base, Operand(offset));
1772 ASSERT(!operand.rm().is_valid());
1774 vstr(src, operand.rn(), operand.offset(), cond);
1779 const Register base,
1793 src.split_code(&sd, &d);
1795 if ((offset % 4) == 0 && (offset / 4) < 256) {
1796 emit(cond | u*B23 | d*
B22 | 0xD0*
B20 | base.code()*
B16 | sd*
B12 |
1797 0xA*
B8 | ((offset / 4) & 255));
1803 add(
ip, base, Operand(offset));
1805 sub(
ip, base, Operand(offset));
1815 ASSERT(!operand.rm().is_valid());
1817 vldr(src, operand.rn(), operand.offset(), cond);
1823 DwVfpRegister first,
1835 first.split_code(&sd, &d);
1836 int count = last.code() - first.code() + 1;
1844 DwVfpRegister first,
1856 first.split_code(&sd, &d);
1857 int count = last.code() - first.code() + 1;
1864 SwVfpRegister first,
1876 first.split_code(&sd, &d);
1877 int count = last.code() - first.code() + 1;
1885 SwVfpRegister first,
1897 first.split_code(&sd, &d);
1898 int count = last.code() - first.code() + 1;
1903 static void DoubleAsTwoUInt32(
double d, uint32_t*
lo, uint32_t*
hi) {
1907 *lo = i & 0xffffffff;
1913 static bool FitsVMOVDoubleImmediate(
double d, uint32_t *encoding) {
1935 DoubleAsTwoUInt32(d, &lo, &hi);
1938 if ((lo != 0) || ((hi & 0xffff) != 0)) {
1943 if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
1948 if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
1954 *encoding = (hi >> 16) & 0xf;
1955 *encoding |= (hi >> 4) & 0x70000;
1956 *encoding |= (hi >> 12) & 0x80000;
1970 if (FitsVMOVDoubleImmediate(imm, &enc)) {
1972 emit(cond | 0xE*
B24 | 0xB*
B20 | dst.code()*
B12 | 0xB*
B8 | enc);
1982 mov(
ip, Operand(lo));
1987 mov(
ip, Operand(lo));
1988 vmov(dst.low(),
ip, cond);
1992 mov(
ip, Operand(hi));
1993 vmov(dst.high(),
ip, cond);
2000 const SwVfpRegister src,
2006 dst.split_code(&sd, &d);
2007 src.split_code(&sm, &m);
2013 const DwVfpRegister src,
2018 emit(cond | 0xE*
B24 | 0xB*
B20 |
2019 dst.code()*
B12 | 0x5*
B9 |
B8 |
B6 | src.code());
2024 const Register src1,
2025 const Register src2,
2032 ASSERT(!src1.is(pc) && !src2.is(pc));
2033 emit(cond | 0xC*
B24 |
B22 | src2.code()*
B16 |
2034 src1.code()*
B12 | 0xB*
B8 |
B4 | dst.code());
2039 const Register dst2,
2040 const DwVfpRegister src,
2047 ASSERT(!dst1.is(pc) && !dst2.is(pc));
2049 dst1.code()*
B12 | 0xB*
B8 |
B4 | src.code());
2063 dst.split_code(&sn, &n);
2069 const SwVfpRegister src,
2078 src.split_code(&sn, &n);
2085 enum VFPType { S32, U32, F32, F64 };
2088 static bool IsSignedVFPType(VFPType
type) {
2101 static bool IsIntegerVFPType(VFPType type) {
2116 static bool IsDoubleVFPType(VFPType type) {
2133 static void SplitRegCode(VFPType reg_type,
2137 ASSERT((reg_code >= 0) && (reg_code <= 31));
2138 if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
2140 *m = reg_code & 0x1;
2141 *vm = reg_code >> 1;
2144 *m = (reg_code & 0x10) >> 4;
2145 *vm = reg_code & 0x0F;
2151 static Instr EncodeVCVT(
const VFPType dst_type,
2153 const VFPType src_type,
2157 ASSERT(src_type != dst_type);
2159 SplitRegCode(src_type, src_code, &Vm, &M);
2160 SplitRegCode(dst_type, dst_code, &Vd, &D);
2162 if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
2167 ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
2171 if (IsIntegerVFPType(dst_type)) {
2172 opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
2173 sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2176 ASSERT(IsIntegerVFPType(src_type));
2178 sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
2179 op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
2189 int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2190 return (cond | 0xE*
B24 | B23 | D*
B22 | 0x3*
B20 | 0x7*
B16 |
2197 const SwVfpRegister src,
2201 emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
2206 const SwVfpRegister src,
2210 emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
2215 const SwVfpRegister src,
2219 emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
2224 const DwVfpRegister src,
2228 emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
2233 const DwVfpRegister src,
2237 emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
2242 const SwVfpRegister src,
2246 emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
2251 const DwVfpRegister src,
2255 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2260 const DwVfpRegister src,
2263 0x5*
B9 |
B8 |
B6 | src.code());
2268 const DwVfpRegister src,
2270 emit(cond | 0xE*
B24 | 0xB*
B20 | dst.code()*
B12 |
2271 0x5*
B9 |
B8 | 0x3*
B6 | src.code());
2276 const DwVfpRegister src1,
2277 const DwVfpRegister src2,
2285 emit(cond | 0xE*
B24 | 0x3*
B20 | src1.code()*
B16 |
2286 dst.code()*
B12 | 0x5*
B9 |
B8 | src2.code());
2291 const DwVfpRegister src1,
2292 const DwVfpRegister src2,
2300 emit(cond | 0xE*
B24 | 0x3*
B20 | src1.code()*
B16 |
2301 dst.code()*
B12 | 0x5*
B9 |
B8 |
B6 | src2.code());
2306 const DwVfpRegister src1,
2307 const DwVfpRegister src2,
2315 emit(cond | 0xE*
B24 | 0x2*
B20 | src1.code()*
B16 |
2316 dst.code()*
B12 | 0x5*
B9 |
B8 | src2.code());
2321 const DwVfpRegister src1,
2322 const DwVfpRegister src2,
2330 emit(cond | 0xE*
B24 | B23 | src1.code()*
B16 |
2331 dst.code()*
B12 | 0x5*
B9 |
B8 | src2.code());
2336 const DwVfpRegister src2,
2343 emit(cond | 0xE*
B24 |B23 | 0x3*
B20 |
B18 |
2344 src1.code()*
B12 | 0x5*
B9 |
B8 |
B6 | src2.code());
2368 dst.code()*
B12 | 0xA*
B8 |
B4);
2378 dst.code()*
B12 | 0xA*
B8 |
B4);
2383 const DwVfpRegister src,
2388 emit(cond | 0xE*
B24 | B23 | 0x3*
B20 |
B16 |
2389 dst.code()*
B12 | 0x5*
B9 |
B8 | 3*
B6 | src.code());
2396 ASSERT(0 <= type && type <= 14);
2397 emit(
al | 13*
B21 | type*
B12 | type);
2403 ASSERT(0 <= type && type <= 14);
2411 return fits_shifter(imm32, &dummy1, &dummy2,
NULL);
2419 RecordRelocInfo(RelocInfo::JS_RETURN);
2426 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2431 if (FLAG_code_comments) {
2433 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2438 void Assembler::GrowBuffer() {
2439 if (!own_buffer_)
FATAL(
"external code buffer is too small");
2443 if (buffer_size_ < 4*
KB) {
2444 desc.buffer_size = 4*
KB;
2445 }
else if (buffer_size_ < 1*
MB) {
2446 desc.buffer_size = 2*buffer_size_;
2448 desc.buffer_size = buffer_size_ + 1*
MB;
2453 desc.buffer = NewArray<byte>(desc.buffer_size);
2456 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
2459 int pc_delta = desc.buffer - buffer_;
2460 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2461 memmove(desc.buffer, buffer_, desc.instr_size);
2462 memmove(reloc_info_writer.pos() + rc_delta,
2463 reloc_info_writer.pos(), desc.reloc_size);
2467 buffer_ = desc.buffer;
2468 buffer_size_ = desc.buffer_size;
2470 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2471 reloc_info_writer.last_pc() + pc_delta);
2478 for (
int i = 0; i < num_pending_reloc_info_; i++) {
2479 RelocInfo& rinfo = pending_reloc_info_[i];
2480 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2481 rinfo.rmode() != RelocInfo::POSITION);
2482 if (rinfo.rmode() != RelocInfo::JS_RETURN) {
2483 rinfo.set_pc(rinfo.pc() + pc_delta);
2493 ASSERT(num_pending_reloc_info_ == 0);
2495 *
reinterpret_cast<uint8_t*
>(pc_) = data;
2496 pc_ +=
sizeof(uint8_t);
2504 ASSERT(num_pending_reloc_info_ == 0);
2506 *
reinterpret_cast<uint32_t*
>(pc_) = data;
2507 pc_ +=
sizeof(uint32_t);
2511 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2514 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
2516 ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
2517 || RelocInfo::IsJSReturn(rmode)
2518 || RelocInfo::IsComment(rmode)
2519 || RelocInfo::IsPosition(rmode));
2523 if (num_pending_reloc_info_ == 0) {
2526 pending_reloc_info_[num_pending_reloc_info_++] = rinfo;
2533 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2544 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2547 reloc_info_writer.Write(&reloc_info_with_ast_id);
2549 reloc_info_writer.Write(&rinfo);
2557 if (no_const_pool_before_ < pc_limit) {
2560 ASSERT((num_pending_reloc_info_ == 0) ||
2562 no_const_pool_before_ = pc_limit;
2565 if (next_buffer_check_ < no_const_pool_before_) {
2566 next_buffer_check_ = no_const_pool_before_;
2582 if (num_pending_reloc_info_ == 0) {
2584 next_buffer_check_ =
pc_offset() + kCheckPoolInterval;
2594 ASSERT(first_const_pool_use_ >= 0);
2595 int dist =
pc_offset() - first_const_pool_use_;
2596 if (!force_emit && dist < kAvgDistToPool &&
2604 int jump_instr = require_jump ? kInstrSize : 0;
2605 int needed_space = jump_instr + kInstrSize +
2606 num_pending_reloc_info_ * kInstrSize + kGap;
2626 for (
int i = 0; i < num_pending_reloc_info_; i++) {
2627 RelocInfo& rinfo = pending_reloc_info_[i];
2628 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2629 rinfo.rmode() != RelocInfo::POSITION &&
2630 rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
2648 num_pending_reloc_info_ = 0;
2649 first_const_pool_use_ = -1;
2653 if (after_pool.is_linked()) {
2660 next_buffer_check_ =
pc_offset() + kCheckPoolInterval;
2666 #endif // V8_TARGET_ARCH_ARM
void cmp(Register src1, const Operand &src2, Condition cond=al)
static bool IsBranch(Instr instr)
void ldrsb(Register dst, const MemOperand &src, Condition cond=al)
bool ImmediateFitsAddrMode1Instruction(int32_t imm32)
Isolate * isolate() const
void vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void mrc(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0, Condition cond=al)
static int GetBranchOffset(Instr instr)
void ClearRecordedAstId()
void vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
const Instr kLdrRegFpOffsetPattern
static bool IsCmpRegister(Instr instr)
void PrintF(const char *format,...)
const Instr kMovwLeaveCCFlip
void strh(Register src, const MemOperand &dst, Condition cond=al)
void bic(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void mrs(Register dst, SRegister s, Condition cond=al)
const Instr kLdrPCPattern
const Instr kMovMvnPattern
static bool IsStrRegFpNegOffset(Instr instr)
void instr_at_put(int pos, Instr instr)
void vabs(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
void sbc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
static bool IsStrRegisterImmediate(Instr instr)
void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond=al)
void mla(Register dst, Register src1, Register src2, Register srcA, SBit s=LeaveCC, Condition cond=al)
const int kRegister_pc_Code
void bfi(Register dst, Register src, int lsb, int width, Condition cond=al)
static int GetCmpImmediateRawImmediate(Instr instr)
void b(int branch_offset, Condition cond=al)
void cmn(Register src1, const Operand &src2, Condition cond=al)
void ldrb(Register dst, const MemOperand &src, Condition cond=al)
void smull(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsSupported(CpuFeature f)
const Instr kLdrStrOffsetMask
void clz(Register dst, Register src, Condition cond=al)
void vmul(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
static bool IsStrRegFpOffset(Instr instr)
void vsqrt(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
static Register GetRm(Instr instr)
const uint32_t kMaxStopCode
static const int kMinimalBufferSize
#define ASSERT(condition)
friend class BlockConstPoolScope
void svc(uint32_t imm24, Condition cond=al)
static bool IsCmpImmediate(Instr instr)
void stm(BlockAddrMode am, Register base, RegList src, Condition cond=al)
void DoubleAsTwoUInt32(double d, uint32_t *lo, uint32_t *hi)
void ldrd(Register dst1, Register dst2, const MemOperand &src, Condition cond=al)
void ldc2(Coprocessor coproc, CRegister crd, const MemOperand &src, LFlag l=Short)
const Instr kCmpCmnPattern
void blx(int branch_offset)
void target_at_put(int pos, int target_pos)
void vdiv(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
void vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset)
void strb(Register src, const MemOperand &dst, Condition cond=al)
const Instr kPopRegPattern
void ldrh(Register dst, const MemOperand &src, Condition cond=al)
void BlockConstPoolFor(int instructions)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 instructions(ARM only)") DEFINE_bool(enable_armv7
void mvn(Register dst, const Operand &src, SBit s=LeaveCC, Condition cond=al)
static Condition GetCondition(Instr instr)
void vneg(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
const Instr kPushRegPattern
void vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static bool IsPush(Instr instr)
void vmov(const DwVfpRegister dst, double imm, const Condition cond=al)
void vldm(BlockAddrMode am, Register base, DwVfpRegister first, DwVfpRegister last, Condition cond=al)
void sh(Register rd, const MemOperand &rs)
const Instr kLdrStrInstrArgumentMask
const int32_t kDefaultStopCode
void vsub(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const Instr kLdrRegFpNegOffsetPattern
void GetCode(CodeDesc *desc)
void strd(Register src1, Register src2, const MemOperand &dst, Condition cond=al)
static const int kPcLoadDelta
void teq(Register src1, const Operand &src2, Condition cond=al)
int branch_offset(Label *L, bool jump_elimination_allowed)
static void TooLateToEnableNow()
void umlal(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsPop(Instr instr)
const Instr kMovLeaveCCMask
void movt(Register reg, uint32_t immediate, Condition cond=al)
void cdp2(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2)
void vadd(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const Instr kPopInstruction
const Instr kStrRegFpOffsetPattern
static bool ArmCpuHasFeature(CpuFeature feature)
#define ASSERT_LE(v1, v2)
void vmrs(const Register dst, const Condition cond=al)
void str(Register src, const MemOperand &dst, Condition cond=al)
void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond=al)
const int kRegister_fp_Code
void CheckConstPool(bool force_emit, bool require_jump)
void mrc2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0)
const int kRegister_lr_Code
static Register GetRn(Instr instr)
void eor(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void add(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
static Instr SetStrRegisterImmediateOffset(Instr instr, int offset)
static bool IsTstImmediate(Instr instr)
void vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static Register GetRd(Instr instr)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static const int kMaxNumPendingRelocInfo
void RecordDebugBreakSlot()
void vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void ldr(Register dst, const MemOperand &src, Condition cond=al)
void stop(const char *msg, Condition cond=al, int32_t code=kDefaultStopCode)
const int kConstantPoolMarker
void movw(Register reg, uint32_t immediate, Condition cond=al)
static Instr SetAddRegisterImmediateOffset(Instr instr, int offset)
const Instr kMovLeaveCCPattern
const Instr kLdrStrInstrTypeMask
void smlal(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
void vldr(const DwVfpRegister dst, const Register base, int offset, const Condition cond=al)
void RecordComment(const char *msg)
void bl(int branch_offset, Condition cond=al)
void rsb(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void sbfx(Register dst, Register src, int lsb, int width, Condition cond=al)
static Register GetCmpImmediateRegister(Instr instr)
const Instr kBlxRegPattern
bool is_const_pool_blocked() const
static bool IsAddRegisterImmediate(Instr instr)
void vcmp(const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
void mov(Register dst, const Operand &src, SBit s=LeaveCC, Condition cond=al)
static const int kHeaderSize
void vmsr(const Register dst, const Condition cond=al)
void vstr(const DwVfpRegister src, const Register base, int offset, const Condition cond=al)
Assembler(Isolate *isolate, void *buffer, int buffer_size)
void usat(Register dst, int satpos, const Operand &src, Condition cond=al)
void ubfx(Register dst, Register src, int lsb, int width, Condition cond=al)
Condition NegateCondition(Condition cond)
#define ASSERT_EQ(v1, v2)
void bx(Register target, Condition cond=al)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
void ldrsh(Register dst, const MemOperand &src, Condition cond=al)
uint32_t SRegisterFieldMask
void orr(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
PositionsRecorder * positions_recorder()
Condition ConditionField() const
static const int kInstrSize
void cdp(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2, Condition cond=al)
MemOperand(Register rn, int32_t offset=0)
static uint64_t CpuFeaturesImpliedByPlatform()
void bfc(Register dst, int lsb, int width, Condition cond=al)
static void FlushICache(void *start, size_t size)
void and_(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void label_at_put(Label *L, int at_offset)
const Instr kStrRegFpNegOffsetPattern
const int kRegister_sp_Code
void DeleteArray(T *array)
void umull(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsLdrRegisterImmediate(Instr instr)
void msr(SRegisterFieldMask fields, const Operand &src, Condition cond=al)
void ldc(Coprocessor coproc, CRegister crd, const MemOperand &src, LFlag l=Short, Condition cond=al)
static bool IsLdrRegFpNegOffset(Instr instr)
void bkpt(uint32_t imm16)
void vstm(BlockAddrMode am, Register base, DwVfpRegister first, DwVfpRegister last, Condition cond=al)
static int GetLdrRegisterImmediateOffset(Instr instr)
void sub(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
bool emit_debug_code() const
void vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void rsc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void tst(Register src1, const Operand &src2, Condition cond=al)
static bool IsLdrRegFpOffset(Instr instr)
void mcr2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0)
void mul(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsLdrPcImmediateOffset(Instr instr)
void mcr(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0, Condition cond=al)
void c(FPUCondition cond, SecondaryField fmt, FPURegister ft, FPURegister fs, uint16_t cc=0)
static const int kMaxDistToPool
void adc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)