OLD | NEW |
---|---|
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 static const Instr kStrRegFpNegOffsetPattern = | 310 static const Instr kStrRegFpNegOffsetPattern = |
311 al | B26 | NegOffset | fp.code() * B16; | 311 al | B26 | NegOffset | fp.code() * B16; |
312 static const Instr kLdrStrInstrTypeMask = 0xffff0000; | 312 static const Instr kLdrStrInstrTypeMask = 0xffff0000; |
313 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; | 313 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; |
314 static const Instr kLdrStrOffsetMask = 0x00000fff; | 314 static const Instr kLdrStrOffsetMask = 0x00000fff; |
315 | 315 |
316 // Spare buffer. | 316 // Spare buffer. |
317 static const int kMinimalBufferSize = 4*KB; | 317 static const int kMinimalBufferSize = 4*KB; |
318 static byte* spare_buffer_ = NULL; | 318 static byte* spare_buffer_ = NULL; |
319 | 319 |
320 Assembler::Assembler(void* buffer, int buffer_size) { | 320 Assembler::Assembler(void* buffer, int buffer_size) |
321 : positions_recorder_(this) { | |
321 if (buffer == NULL) { | 322 if (buffer == NULL) { |
322 // Do our own buffer management. | 323 // Do our own buffer management. |
323 if (buffer_size <= kMinimalBufferSize) { | 324 if (buffer_size <= kMinimalBufferSize) { |
324 buffer_size = kMinimalBufferSize; | 325 buffer_size = kMinimalBufferSize; |
325 | 326 |
326 if (spare_buffer_ != NULL) { | 327 if (spare_buffer_ != NULL) { |
327 buffer = spare_buffer_; | 328 buffer = spare_buffer_; |
328 spare_buffer_ = NULL; | 329 spare_buffer_ = NULL; |
329 } | 330 } |
330 } | 331 } |
(...skipping 16 matching lines...) Expand all Loading... | |
347 // Setup buffer pointers. | 348 // Setup buffer pointers. |
348 ASSERT(buffer_ != NULL); | 349 ASSERT(buffer_ != NULL); |
349 pc_ = buffer_; | 350 pc_ = buffer_; |
350 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 351 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
351 num_prinfo_ = 0; | 352 num_prinfo_ = 0; |
352 next_buffer_check_ = 0; | 353 next_buffer_check_ = 0; |
353 const_pool_blocked_nesting_ = 0; | 354 const_pool_blocked_nesting_ = 0; |
354 no_const_pool_before_ = 0; | 355 no_const_pool_before_ = 0; |
355 last_const_pool_end_ = 0; | 356 last_const_pool_end_ = 0; |
356 last_bound_pos_ = 0; | 357 last_bound_pos_ = 0; |
357 current_statement_position_ = RelocInfo::kNoPosition; | |
358 current_position_ = RelocInfo::kNoPosition; | |
359 written_statement_position_ = current_statement_position_; | |
360 written_position_ = current_position_; | |
361 } | 358 } |
362 | 359 |
363 | 360 |
364 Assembler::~Assembler() { | 361 Assembler::~Assembler() { |
365 ASSERT(const_pool_blocked_nesting_ == 0); | 362 ASSERT(const_pool_blocked_nesting_ == 0); |
366 if (own_buffer_) { | 363 if (own_buffer_) { |
367 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 364 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
368 spare_buffer_ = buffer_; | 365 spare_buffer_ = buffer_; |
369 } else { | 366 } else { |
370 DeleteArray(buffer_); | 367 DeleteArray(buffer_); |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
992 | 989 |
993 void Assembler::bl(int branch_offset, Condition cond) { | 990 void Assembler::bl(int branch_offset, Condition cond) { |
994 ASSERT((branch_offset & 3) == 0); | 991 ASSERT((branch_offset & 3) == 0); |
995 int imm24 = branch_offset >> 2; | 992 int imm24 = branch_offset >> 2; |
996 ASSERT(is_int24(imm24)); | 993 ASSERT(is_int24(imm24)); |
997 emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask)); | 994 emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask)); |
998 } | 995 } |
999 | 996 |
1000 | 997 |
1001 void Assembler::blx(int branch_offset) { // v5 and above | 998 void Assembler::blx(int branch_offset) { // v5 and above |
1002 WriteRecordedPositions(); | 999 positions_recorder()->WriteRecordedPositions(); |
Søren Thygesen Gjesse
2010/11/04 15:08:24
Why not just positions_recorder_. instead of posit
| |
1003 ASSERT((branch_offset & 1) == 0); | 1000 ASSERT((branch_offset & 1) == 0); |
1004 int h = ((branch_offset & 2) >> 1)*B24; | 1001 int h = ((branch_offset & 2) >> 1)*B24; |
1005 int imm24 = branch_offset >> 2; | 1002 int imm24 = branch_offset >> 2; |
1006 ASSERT(is_int24(imm24)); | 1003 ASSERT(is_int24(imm24)); |
1007 emit(nv | B27 | B25 | h | (imm24 & Imm24Mask)); | 1004 emit(nv | B27 | B25 | h | (imm24 & Imm24Mask)); |
1008 } | 1005 } |
1009 | 1006 |
1010 | 1007 |
1011 void Assembler::blx(Register target, Condition cond) { // v5 and above | 1008 void Assembler::blx(Register target, Condition cond) { // v5 and above |
1012 WriteRecordedPositions(); | 1009 positions_recorder()->WriteRecordedPositions(); |
1013 ASSERT(!target.is(pc)); | 1010 ASSERT(!target.is(pc)); |
1014 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); | 1011 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); |
1015 } | 1012 } |
1016 | 1013 |
1017 | 1014 |
1018 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t | 1015 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t |
1019 WriteRecordedPositions(); | 1016 positions_recorder()->WriteRecordedPositions(); |
1020 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged | 1017 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged |
1021 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); | 1018 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); |
1022 } | 1019 } |
1023 | 1020 |
1024 | 1021 |
1025 // Data-processing instructions. | 1022 // Data-processing instructions. |
1026 | 1023 |
1027 void Assembler::and_(Register dst, Register src1, const Operand& src2, | 1024 void Assembler::and_(Register dst, Register src1, const Operand& src2, |
1028 SBit s, Condition cond) { | 1025 SBit s, Condition cond) { |
1029 addrmod1(cond | 0*B21 | s, src1, dst, src2); | 1026 addrmod1(cond | 0*B21 | s, src1, dst, src2); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1107 | 1104 |
1108 | 1105 |
1109 void Assembler::orr(Register dst, Register src1, const Operand& src2, | 1106 void Assembler::orr(Register dst, Register src1, const Operand& src2, |
1110 SBit s, Condition cond) { | 1107 SBit s, Condition cond) { |
1111 addrmod1(cond | 12*B21 | s, src1, dst, src2); | 1108 addrmod1(cond | 12*B21 | s, src1, dst, src2); |
1112 } | 1109 } |
1113 | 1110 |
1114 | 1111 |
1115 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { | 1112 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { |
1116 if (dst.is(pc)) { | 1113 if (dst.is(pc)) { |
1117 WriteRecordedPositions(); | 1114 positions_recorder()->WriteRecordedPositions(); |
1118 } | 1115 } |
1119 // Don't allow nop instructions in the form mov rn, rn to be generated using | 1116 // Don't allow nop instructions in the form mov rn, rn to be generated using |
1120 // the mov instruction. They must be generated using nop(int) | 1117 // the mov instruction. They must be generated using nop(int) |
1121 // pseudo instructions. | 1118 // pseudo instructions. |
1122 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); | 1119 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); |
1123 addrmod1(cond | 13*B21 | s, r0, dst, src); | 1120 addrmod1(cond | 13*B21 | s, r0, dst, src); |
1124 } | 1121 } |
1125 | 1122 |
1126 | 1123 |
1127 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { | 1124 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1352 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed | 1349 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed |
1353 instr = src.rm_.code(); | 1350 instr = src.rm_.code(); |
1354 } | 1351 } |
1355 emit(cond | instr | B24 | B21 | fields | 15*B12); | 1352 emit(cond | instr | B24 | B21 | fields | 15*B12); |
1356 } | 1353 } |
1357 | 1354 |
1358 | 1355 |
1359 // Load/Store instructions. | 1356 // Load/Store instructions. |
1360 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { | 1357 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { |
1361 if (dst.is(pc)) { | 1358 if (dst.is(pc)) { |
1362 WriteRecordedPositions(); | 1359 positions_recorder()->WriteRecordedPositions(); |
1363 } | 1360 } |
1364 addrmod2(cond | B26 | L, dst, src); | 1361 addrmod2(cond | B26 | L, dst, src); |
1365 | 1362 |
1366 // Eliminate pattern: push(ry), pop(rx) | 1363 // Eliminate pattern: push(ry), pop(rx) |
1367 // str(ry, MemOperand(sp, 4, NegPreIndex), al) | 1364 // str(ry, MemOperand(sp, 4, NegPreIndex), al) |
1368 // ldr(rx, MemOperand(sp, 4, PostIndex), al) | 1365 // ldr(rx, MemOperand(sp, 4, PostIndex), al) |
1369 // Both instructions can be eliminated if ry = rx. | 1366 // Both instructions can be eliminated if ry = rx. |
1370 // If ry != rx, a register copy from ry to rx is inserted | 1367 // If ry != rx, a register copy from ry to rx is inserted |
1371 // after eliminating the push and the pop instructions. | 1368 // after eliminating the push and the pop instructions. |
1372 if (can_peephole_optimize(2)) { | 1369 if (can_peephole_optimize(2)) { |
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2370 } | 2367 } |
2371 | 2368 |
2372 | 2369 |
2373 void Assembler::BlockConstPoolFor(int instructions) { | 2370 void Assembler::BlockConstPoolFor(int instructions) { |
2374 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); | 2371 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); |
2375 } | 2372 } |
2376 | 2373 |
2377 | 2374 |
2378 // Debugging. | 2375 // Debugging. |
2379 void Assembler::RecordJSReturn() { | 2376 void Assembler::RecordJSReturn() { |
2380 WriteRecordedPositions(); | 2377 positions_recorder()->WriteRecordedPositions(); |
2381 CheckBuffer(); | 2378 CheckBuffer(); |
2382 RecordRelocInfo(RelocInfo::JS_RETURN); | 2379 RecordRelocInfo(RelocInfo::JS_RETURN); |
2383 } | 2380 } |
2384 | 2381 |
2385 | 2382 |
2386 void Assembler::RecordDebugBreakSlot() { | 2383 void Assembler::RecordDebugBreakSlot() { |
2387 WriteRecordedPositions(); | 2384 positions_recorder()->WriteRecordedPositions(); |
2388 CheckBuffer(); | 2385 CheckBuffer(); |
2389 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); | 2386 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); |
2390 } | 2387 } |
2391 | 2388 |
2392 | 2389 |
2393 void Assembler::RecordComment(const char* msg) { | 2390 void Assembler::RecordComment(const char* msg) { |
2394 if (FLAG_debug_code) { | 2391 if (FLAG_debug_code) { |
2395 CheckBuffer(); | 2392 CheckBuffer(); |
2396 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); | 2393 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); |
2397 } | 2394 } |
2398 } | 2395 } |
2399 | 2396 |
2400 | 2397 |
2401 void Assembler::RecordPosition(int pos) { | |
2402 if (pos == RelocInfo::kNoPosition) return; | |
2403 ASSERT(pos >= 0); | |
2404 current_position_ = pos; | |
2405 } | |
2406 | |
2407 | |
2408 void Assembler::RecordStatementPosition(int pos) { | |
2409 if (pos == RelocInfo::kNoPosition) return; | |
2410 ASSERT(pos >= 0); | |
2411 current_statement_position_ = pos; | |
2412 } | |
2413 | |
2414 | |
2415 bool Assembler::WriteRecordedPositions() { | |
2416 bool written = false; | |
2417 | |
2418 // Write the statement position if it is different from what was written last | |
2419 // time. | |
2420 if (current_statement_position_ != written_statement_position_) { | |
2421 CheckBuffer(); | |
2422 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_); | |
2423 written_statement_position_ = current_statement_position_; | |
2424 written = true; | |
2425 } | |
2426 | |
2427 // Write the position if it is different from what was written last time and | |
2428 // also different from the written statement position. | |
2429 if (current_position_ != written_position_ && | |
2430 current_position_ != written_statement_position_) { | |
2431 CheckBuffer(); | |
2432 RecordRelocInfo(RelocInfo::POSITION, current_position_); | |
2433 written_position_ = current_position_; | |
2434 written = true; | |
2435 } | |
2436 | |
2437 // Return whether something was written. | |
2438 return written; | |
2439 } | |
2440 | |
2441 | |
2442 void Assembler::GrowBuffer() { | 2398 void Assembler::GrowBuffer() { |
2443 if (!own_buffer_) FATAL("external code buffer is too small"); | 2399 if (!own_buffer_) FATAL("external code buffer is too small"); |
2444 | 2400 |
2445 // Compute new buffer size. | 2401 // Compute new buffer size. |
2446 CodeDesc desc; // the new buffer | 2402 CodeDesc desc; // the new buffer |
2447 if (buffer_size_ < 4*KB) { | 2403 if (buffer_size_ < 4*KB) { |
2448 desc.buffer_size = 4*KB; | 2404 desc.buffer_size = 4*KB; |
2449 } else if (buffer_size_ < 1*MB) { | 2405 } else if (buffer_size_ < 1*MB) { |
2450 desc.buffer_size = 2*buffer_size_; | 2406 desc.buffer_size = 2*buffer_size_; |
2451 } else { | 2407 } else { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2628 | 2584 |
2629 // Since a constant pool was just emitted, move the check offset forward by | 2585 // Since a constant pool was just emitted, move the check offset forward by |
2630 // the standard interval. | 2586 // the standard interval. |
2631 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2587 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
2632 } | 2588 } |
2633 | 2589 |
2634 | 2590 |
2635 } } // namespace v8::internal | 2591 } } // namespace v8::internal |
2636 | 2592 |
2637 #endif // V8_TARGET_ARCH_ARM | 2593 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |