| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 generating_stub_(false), | 44 generating_stub_(false), |
| 45 allow_stub_calls_(true), | 45 allow_stub_calls_(true), |
| 46 has_frame_(false) { | 46 has_frame_(false) { |
| 47 if (isolate() != NULL) { | 47 if (isolate() != NULL) { |
| 48 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), | 48 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), |
| 49 isolate()); | 49 isolate()); |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 // We always generate arm code, never thumb code, even if V8 is compiled to | |
| 55 // thumb, so we require inter-working support | |
| 56 #if defined(__thumb__) && !defined(USE_THUMB_INTERWORK) | |
| 57 #error "flag -mthumb-interwork missing" | |
| 58 #endif | |
| 59 | |
| 60 | |
| 61 // We do not support thumb inter-working with an arm architecture not supporting | |
| 62 // the blx instruction (below v5t). If you know what CPU you are compiling for | |
| 63 // you can use -march=armv7 or similar. | |
| 64 #if defined(USE_THUMB_INTERWORK) && !defined(CAN_USE_THUMB_INSTRUCTIONS) | |
| 65 # error "For thumb inter-working we require an architecture which supports blx" | |
| 66 #endif | |
| 67 | |
| 68 | |
| 69 // Using bx does not yield better code, so use it only when required | |
| 70 #if defined(USE_THUMB_INTERWORK) | |
| 71 #define USE_BX 1 | |
| 72 #endif | |
| 73 | |
| 74 | |
| 75 void MacroAssembler::Jump(Register target, Condition cond) { | 54 void MacroAssembler::Jump(Register target, Condition cond) { |
| 76 #if USE_BX | |
| 77 bx(target, cond); | 55 bx(target, cond); |
| 78 #else | |
| 79 mov(pc, Operand(target), LeaveCC, cond); | |
| 80 #endif | |
| 81 } | 56 } |
| 82 | 57 |
| 83 | 58 |
| 84 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode, | 59 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode, |
| 85 Condition cond) { | 60 Condition cond) { |
| 86 #if USE_BX | |
| 87 mov(ip, Operand(target, rmode)); | 61 mov(ip, Operand(target, rmode)); |
| 88 bx(ip, cond); | 62 bx(ip, cond); |
| 89 #else | |
| 90 mov(pc, Operand(target, rmode), LeaveCC, cond); | |
| 91 #endif | |
| 92 } | 63 } |
| 93 | 64 |
| 94 | 65 |
| 95 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode, | 66 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode, |
| 96 Condition cond) { | 67 Condition cond) { |
| 97 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 68 ASSERT(!RelocInfo::IsCodeTarget(rmode)); |
| 98 Jump(reinterpret_cast<intptr_t>(target), rmode, cond); | 69 Jump(reinterpret_cast<intptr_t>(target), rmode, cond); |
| 99 } | 70 } |
| 100 | 71 |
| 101 | 72 |
| 102 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, | 73 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, |
| 103 Condition cond) { | 74 Condition cond) { |
| 104 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 75 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 105 // 'code' is always generated ARM code, never THUMB code | 76 // 'code' is always generated ARM code, never THUMB code |
| 106 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | 77 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); |
| 107 } | 78 } |
| 108 | 79 |
| 109 | 80 |
| 110 int MacroAssembler::CallSize(Register target, Condition cond) { | 81 int MacroAssembler::CallSize(Register target, Condition cond) { |
| 111 #ifdef USE_BLX | |
| 112 return kInstrSize; | 82 return kInstrSize; |
| 113 #else | |
| 114 return 2 * kInstrSize; | |
| 115 #endif | |
| 116 } | 83 } |
| 117 | 84 |
| 118 | 85 |
| 119 void MacroAssembler::Call(Register target, Condition cond) { | 86 void MacroAssembler::Call(Register target, Condition cond) { |
| 120 // Block constant pool for the call instruction sequence. | 87 // Block constant pool for the call instruction sequence. |
| 121 BlockConstPoolScope block_const_pool(this); | 88 BlockConstPoolScope block_const_pool(this); |
| 122 Label start; | 89 Label start; |
| 123 bind(&start); | 90 bind(&start); |
| 124 #ifdef USE_BLX | |
| 125 blx(target, cond); | 91 blx(target, cond); |
| 126 #else | |
| 127 // set lr for return at current pc + 8 | |
| 128 mov(lr, Operand(pc), LeaveCC, cond); | |
| 129 mov(pc, Operand(target), LeaveCC, cond); | |
| 130 #endif | |
| 131 ASSERT_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start)); | 92 ASSERT_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start)); |
| 132 } | 93 } |
| 133 | 94 |
| 134 | 95 |
| 135 int MacroAssembler::CallSize( | 96 int MacroAssembler::CallSize( |
| 136 Address target, RelocInfo::Mode rmode, Condition cond) { | 97 Address target, RelocInfo::Mode rmode, Condition cond) { |
| 137 int size = 2 * kInstrSize; | 98 int size = 2 * kInstrSize; |
| 138 Instr mov_instr = cond | MOV | LeaveCC; | 99 Instr mov_instr = cond | MOV | LeaveCC; |
| 139 intptr_t immediate = reinterpret_cast<intptr_t>(target); | 100 intptr_t immediate = reinterpret_cast<intptr_t>(target); |
| 140 if (!Operand(immediate, rmode).is_single_instruction(this, mov_instr)) { | 101 if (!Operand(immediate, rmode).is_single_instruction(this, mov_instr)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 163 // Block constant pool for the call instruction sequence. | 124 // Block constant pool for the call instruction sequence. |
| 164 BlockConstPoolScope block_const_pool(this); | 125 BlockConstPoolScope block_const_pool(this); |
| 165 Label start; | 126 Label start; |
| 166 bind(&start); | 127 bind(&start); |
| 167 | 128 |
| 168 bool old_predictable_code_size = predictable_code_size(); | 129 bool old_predictable_code_size = predictable_code_size(); |
| 169 if (mode == NEVER_INLINE_TARGET_ADDRESS) { | 130 if (mode == NEVER_INLINE_TARGET_ADDRESS) { |
| 170 set_predictable_code_size(true); | 131 set_predictable_code_size(true); |
| 171 } | 132 } |
| 172 | 133 |
| 173 #ifdef USE_BLX | |
| 174 // Call sequence on V7 or later may be : | 134 // Call sequence on V7 or later may be : |
| 175 // movw ip, #... @ call address low 16 | 135 // movw ip, #... @ call address low 16 |
| 176 // movt ip, #... @ call address high 16 | 136 // movt ip, #... @ call address high 16 |
| 177 // blx ip | 137 // blx ip |
| 178 // @ return address | 138 // @ return address |
| 179 // Or for pre-V7 or values that may be back-patched | 139 // Or for pre-V7 or values that may be back-patched |
| 180 // to avoid ICache flushes: | 140 // to avoid ICache flushes: |
| 181 // ldr ip, [pc, #...] @ call address | 141 // ldr ip, [pc, #...] @ call address |
| 182 // blx ip | 142 // blx ip |
| 183 // @ return address | 143 // @ return address |
| 184 | 144 |
| 185 // Statement positions are expected to be recorded when the target | 145 // Statement positions are expected to be recorded when the target |
| 186 // address is loaded. The mov method will automatically record | 146 // address is loaded. The mov method will automatically record |
| 187 // positions when pc is the target, since this is not the case here | 147 // positions when pc is the target, since this is not the case here |
| 188 // we have to do it explicitly. | 148 // we have to do it explicitly. |
| 189 positions_recorder()->WriteRecordedPositions(); | 149 positions_recorder()->WriteRecordedPositions(); |
| 190 | 150 |
| 191 mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode)); | 151 mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode)); |
| 192 blx(ip, cond); | 152 blx(ip, cond); |
| 193 | 153 |
| 194 #else | |
| 195 // Set lr for return at current pc + 8. | |
| 196 mov(lr, Operand(pc), LeaveCC, cond); | |
| 197 // Emit a ldr<cond> pc, [pc + offset of target in constant pool]. | |
| 198 mov(pc, Operand(reinterpret_cast<int32_t>(target), rmode), LeaveCC, cond); | |
| 199 #endif | |
| 200 ASSERT_EQ(CallSize(target, rmode, cond), SizeOfCodeGeneratedSince(&start)); | 154 ASSERT_EQ(CallSize(target, rmode, cond), SizeOfCodeGeneratedSince(&start)); |
| 201 if (mode == NEVER_INLINE_TARGET_ADDRESS) { | 155 if (mode == NEVER_INLINE_TARGET_ADDRESS) { |
| 202 set_predictable_code_size(old_predictable_code_size); | 156 set_predictable_code_size(old_predictable_code_size); |
| 203 } | 157 } |
| 204 } | 158 } |
| 205 | 159 |
| 206 | 160 |
| 207 int MacroAssembler::CallSize(Handle<Code> code, | 161 int MacroAssembler::CallSize(Handle<Code> code, |
| 208 RelocInfo::Mode rmode, | 162 RelocInfo::Mode rmode, |
| 209 TypeFeedbackId ast_id, | 163 TypeFeedbackId ast_id, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 223 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { | 177 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { |
| 224 SetRecordedAstId(ast_id); | 178 SetRecordedAstId(ast_id); |
| 225 rmode = RelocInfo::CODE_TARGET_WITH_ID; | 179 rmode = RelocInfo::CODE_TARGET_WITH_ID; |
| 226 } | 180 } |
| 227 // 'code' is always generated ARM code, never THUMB code | 181 // 'code' is always generated ARM code, never THUMB code |
| 228 Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode); | 182 Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode); |
| 229 } | 183 } |
| 230 | 184 |
| 231 | 185 |
| 232 void MacroAssembler::Ret(Condition cond) { | 186 void MacroAssembler::Ret(Condition cond) { |
| 233 #if USE_BX | |
| 234 bx(lr, cond); | 187 bx(lr, cond); |
| 235 #else | |
| 236 mov(pc, Operand(lr), LeaveCC, cond); | |
| 237 #endif | |
| 238 } | 188 } |
| 239 | 189 |
| 240 | 190 |
| 241 void MacroAssembler::Drop(int count, Condition cond) { | 191 void MacroAssembler::Drop(int count, Condition cond) { |
| 242 if (count > 0) { | 192 if (count > 0) { |
| 243 add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); | 193 add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); |
| 244 } | 194 } |
| 245 } | 195 } |
| 246 | 196 |
| 247 | 197 |
| (...skipping 2971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3219 Label loop, entry; | 3169 Label loop, entry; |
| 3220 b(&entry); | 3170 b(&entry); |
| 3221 bind(&loop); | 3171 bind(&loop); |
| 3222 str(filler, MemOperand(start_offset, kPointerSize, PostIndex)); | 3172 str(filler, MemOperand(start_offset, kPointerSize, PostIndex)); |
| 3223 bind(&entry); | 3173 bind(&entry); |
| 3224 cmp(start_offset, end_offset); | 3174 cmp(start_offset, end_offset); |
| 3225 b(lt, &loop); | 3175 b(lt, &loop); |
| 3226 } | 3176 } |
| 3227 | 3177 |
| 3228 | 3178 |
| 3229 void MacroAssembler::CountLeadingZeros(Register zeros, // Answer. | |
| 3230 Register source, // Input. | |
| 3231 Register scratch) { | |
| 3232 ASSERT(!zeros.is(source) || !source.is(scratch)); | |
| 3233 ASSERT(!zeros.is(scratch)); | |
| 3234 ASSERT(!scratch.is(ip)); | |
| 3235 ASSERT(!source.is(ip)); | |
| 3236 ASSERT(!zeros.is(ip)); | |
| 3237 #ifdef CAN_USE_ARMV5_INSTRUCTIONS | |
| 3238 clz(zeros, source); // This instruction is only supported after ARM5. | |
| 3239 #else | |
| 3240 // Order of the next two lines is important: zeros register | |
| 3241 // can be the same as source register. | |
| 3242 Move(scratch, source); | |
| 3243 mov(zeros, Operand::Zero()); | |
| 3244 // Top 16. | |
| 3245 tst(scratch, Operand(0xffff0000)); | |
| 3246 add(zeros, zeros, Operand(16), LeaveCC, eq); | |
| 3247 mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq); | |
| 3248 // Top 8. | |
| 3249 tst(scratch, Operand(0xff000000)); | |
| 3250 add(zeros, zeros, Operand(8), LeaveCC, eq); | |
| 3251 mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq); | |
| 3252 // Top 4. | |
| 3253 tst(scratch, Operand(0xf0000000)); | |
| 3254 add(zeros, zeros, Operand(4), LeaveCC, eq); | |
| 3255 mov(scratch, Operand(scratch, LSL, 4), LeaveCC, eq); | |
| 3256 // Top 2. | |
| 3257 tst(scratch, Operand(0xc0000000)); | |
| 3258 add(zeros, zeros, Operand(2), LeaveCC, eq); | |
| 3259 mov(scratch, Operand(scratch, LSL, 2), LeaveCC, eq); | |
| 3260 // Top bit. | |
| 3261 tst(scratch, Operand(0x80000000u)); | |
| 3262 add(zeros, zeros, Operand(1), LeaveCC, eq); | |
| 3263 #endif | |
| 3264 } | |
| 3265 | |
| 3266 | |
| 3267 void MacroAssembler::CheckFor32DRegs(Register scratch) { | 3179 void MacroAssembler::CheckFor32DRegs(Register scratch) { |
| 3268 mov(scratch, Operand(ExternalReference::cpu_features())); | 3180 mov(scratch, Operand(ExternalReference::cpu_features())); |
| 3269 ldr(scratch, MemOperand(scratch)); | 3181 ldr(scratch, MemOperand(scratch)); |
| 3270 tst(scratch, Operand(1u << VFP32DREGS)); | 3182 tst(scratch, Operand(1u << VFP32DREGS)); |
| 3271 } | 3183 } |
| 3272 | 3184 |
| 3273 | 3185 |
| 3274 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( | 3186 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( |
| 3275 Register first, | 3187 Register first, |
| 3276 Register second, | 3188 Register second, |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3836 void CodePatcher::EmitCondition(Condition cond) { | 3748 void CodePatcher::EmitCondition(Condition cond) { |
| 3837 Instr instr = Assembler::instr_at(masm_.pc_); | 3749 Instr instr = Assembler::instr_at(masm_.pc_); |
| 3838 instr = (instr & ~kCondMask) | cond; | 3750 instr = (instr & ~kCondMask) | cond; |
| 3839 masm_.emit(instr); | 3751 masm_.emit(instr); |
| 3840 } | 3752 } |
| 3841 | 3753 |
| 3842 | 3754 |
| 3843 } } // namespace v8::internal | 3755 } } // namespace v8::internal |
| 3844 | 3756 |
| 3845 #endif // V8_TARGET_ARCH_ARM | 3757 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |