| 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 Address* RelocInfo::target_reference_address() { | 106 Address* RelocInfo::target_reference_address() { |
| 107 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 107 ASSERT(rmode_ == EXTERNAL_REFERENCE); |
| 108 return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); | 108 return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); |
| 109 } | 109 } |
| 110 | 110 |
| 111 | 111 |
| 112 Address RelocInfo::call_address() { | 112 Address RelocInfo::call_address() { |
| 113 ASSERT(IsPatchedReturnSequence()); | 113 ASSERT(IsPatchedReturnSequence()); |
| 114 // The 2 instructions offset assumes patched return sequence. | 114 // The 2 instructions offset assumes patched return sequence. |
| 115 ASSERT(IsJSReturn(rmode())); | 115 ASSERT(IsJSReturn(rmode())); |
| 116 return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); | 116 return Memory::Address_at(pc_ + 2 * Assembler::kInstrArmSize); |
| 117 } | 117 } |
| 118 | 118 |
| 119 | 119 |
| 120 void RelocInfo::set_call_address(Address target) { | 120 void RelocInfo::set_call_address(Address target) { |
| 121 ASSERT(IsPatchedReturnSequence()); | 121 ASSERT(IsPatchedReturnSequence()); |
| 122 // The 2 instructions offset assumes patched return sequence. | 122 // The 2 instructions offset assumes patched return sequence. |
| 123 ASSERT(IsJSReturn(rmode())); | 123 ASSERT(IsJSReturn(rmode())); |
| 124 Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; | 124 Memory::Address_at(pc_ + 2 * Assembler::kInstrArmSize) = target; |
| 125 } | 125 } |
| 126 | 126 |
| 127 | 127 |
| 128 Object* RelocInfo::call_object() { | 128 Object* RelocInfo::call_object() { |
| 129 return *call_object_address(); | 129 return *call_object_address(); |
| 130 } | 130 } |
| 131 | 131 |
| 132 | 132 |
| 133 Object** RelocInfo::call_object_address() { | 133 Object** RelocInfo::call_object_address() { |
| 134 ASSERT(IsPatchedReturnSequence()); | 134 ASSERT(IsPatchedReturnSequence()); |
| 135 // The 2 instructions offset assumes patched return sequence. | 135 // The 2 instructions offset assumes patched return sequence. |
| 136 ASSERT(IsJSReturn(rmode())); | 136 ASSERT(IsJSReturn(rmode())); |
| 137 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 137 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrArmSize); |
| 138 } | 138 } |
| 139 | 139 |
| 140 | 140 |
| 141 void RelocInfo::set_call_object(Object* target) { | 141 void RelocInfo::set_call_object(Object* target) { |
| 142 *call_object_address() = target; | 142 *call_object_address() = target; |
| 143 } | 143 } |
| 144 | 144 |
| 145 | 145 |
| 146 bool RelocInfo::IsPatchedReturnSequence() { | 146 bool RelocInfo::IsPatchedReturnSequence() { |
| 147 // On ARM a "call instruction" is actually two instructions. | 147 // On ARM a "call instruction" is actually two instructions. |
| 148 // mov lr, pc | 148 // mov lr, pc |
| 149 // ldr pc, [pc, #XXX] | 149 // ldr pc, [pc, #XXX] |
| 150 return (Assembler::instr_at(pc_) == kMovLrPc) | 150 return (Assembler::instr_arm_at(pc_) == kMovLrPc) && |
| 151 && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern) | 151 ((Assembler::instr_arm_at(pc_ + Assembler::kInstrArmSize) & |
| 152 == kLdrPCPattern); | 152 kLdrPCPattern) == kLdrPCPattern); |
| 153 } | 153 } |
| 154 | 154 |
| 155 | 155 |
| 156 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { | 156 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { |
| 157 rm_ = no_reg; | 157 rm_ = no_reg; |
| 158 imm32_ = immediate; | 158 imm32_ = immediate; |
| 159 rmode_ = rmode; | 159 rmode_ = rmode; |
| 160 } | 160 } |
| 161 | 161 |
| 162 | 162 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 | 213 |
| 214 void Assembler::CheckBuffer() { | 214 void Assembler::CheckBuffer() { |
| 215 if (buffer_space() <= kGap) { | 215 if (buffer_space() <= kGap) { |
| 216 GrowBuffer(); | 216 GrowBuffer(); |
| 217 } | 217 } |
| 218 if (pc_offset() >= next_buffer_check_) { | 218 if (pc_offset() >= next_buffer_check_) { |
| 219 CheckConstPool(false, true); | 219 CheckConstPool(false, true); |
| 220 } | 220 } |
| 221 } | 221 } |
| 222 | 222 |
| 223 void Assembler::EnsureArmMode() { |
| 224 if (thumb_mode_) { |
| 225 ASSERT((pc_offset() & 1) == 0); |
| 226 if (pc_offset() & 2 != 0) { |
| 227 DataProcessingImm(ADD, LeaveCC, pc, pc, 1); |
| 228 // Pad with a T1 NOP |
| 229 emit_thumb((int16_t) (b1011 * B12 | b1111 * B8)); |
| 230 } else { |
| 231 DataProcessingImm(SUB, LeaveCC, pc, pc, 1); |
| 232 } |
| 233 ASSERT((pc_offset() & 3) == 0); |
| 234 thumb_mode_ = false; |
| 235 } |
| 236 CheckBuffer(); |
| 237 } |
| 223 | 238 |
| 224 void Assembler::emit(Instr x) { | 239 void Assembler::EnsureThumbMode() { |
| 240 if (!thumb_mode_) { |
| 241 ASSERT((pc_offset() & 1) == 0); |
| 242 emit_arm(al | B25 | B22 | pc.code() * B16 | pc.code() * B12 | 3); |
| 243 thumb_mode_ = true; |
| 244 ASSERT((pc_offset() & 1) == 0); |
| 245 } |
| 225 CheckBuffer(); | 246 CheckBuffer(); |
| 226 *reinterpret_cast<Instr*>(pc_) = x; | 247 } |
| 227 pc_ += kInstrSize; | 248 |
| 249 void Assembler::emit_arm(InstrArm x) { |
| 250 EnsureArmMode(); |
| 251 *reinterpret_cast<InstrArm*>(pc_) = x; |
| 252 pc_ += kInstrArmSize; |
| 253 } |
| 254 |
| 255 void Assembler::emit_int32(int32_t x) { |
| 256 CheckBuffer(); |
| 257 *reinterpret_cast<int32_t*>(pc_) = x; |
| 258 pc_ += sizeof(int32_t); |
| 228 } | 259 } |
| 229 | 260 |
| 230 | 261 |
| 262 void Assembler::emit_thumb(InstrThumb x) { |
| 263 EnsureThumbMode(); |
| 264 *reinterpret_cast<InstrThumb*>(pc_) = x; |
| 265 pc_ += kInstrThumbSize; |
| 266 } |
| 267 |
| 231 Address Assembler::target_address_address_at(Address pc) { | 268 Address Assembler::target_address_address_at(Address pc) { |
| 232 Instr instr = Memory::int32_at(pc); | 269 Address target_pc = pc; |
| 233 // Verify that the instruction at pc is a ldr<cond> <Rd>, [pc +/- offset_12]. | 270 InstrArm instr = Memory::int32_at(target_pc); |
| 271 // If we have a bx instruction, the instruction before the bx is |
| 272 // what we need to patch. |
| 273 static const int32_t kBxInstMask = 0x0ffffff0; |
| 274 static const int32_t kBxInstPattern = 0x012fff10; |
| 275 if ((instr & kBxInstMask) == kBxInstPattern) { |
| 276 target_pc -= kInstrArmSize; |
| 277 instr = Memory::int32_at(target_pc); |
| 278 } |
| 279 // Verify that the instruction to patch is a |
| 280 // ldr<cond> <Rd>, [pc +/- offset_12]. |
| 234 ASSERT((instr & 0x0f7f0000) == 0x051f0000); | 281 ASSERT((instr & 0x0f7f0000) == 0x051f0000); |
| 235 int offset = instr & 0xfff; // offset_12 is unsigned | 282 int offset = instr & 0xfff; // offset_12 is unsigned |
| 236 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign | 283 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign |
| 237 // Verify that the constant pool comes after the instruction referencing it. | 284 // Verify that the constant pool comes after the instruction referencing it. |
| 238 ASSERT(offset >= -4); | 285 ASSERT(offset >= -4); |
| 239 return pc + offset + 8; | 286 return target_pc + offset + 8; |
| 240 } | 287 } |
| 241 | 288 |
| 242 | 289 |
| 243 Address Assembler::target_address_at(Address pc) { | 290 Address Assembler::target_address_at(Address pc) { |
| 244 return Memory::Address_at(target_address_address_at(pc)); | 291 return Memory::Address_at(target_address_address_at(pc)); |
| 245 } | 292 } |
| 246 | 293 |
| 247 | 294 |
| 248 void Assembler::set_target_at(Address constant_pool_entry, | 295 void Assembler::set_target_at(Address constant_pool_entry, |
| 249 Address target) { | 296 Address target) { |
| 250 Memory::Address_at(constant_pool_entry) = target; | 297 Memory::Address_at(constant_pool_entry) = target; |
| 251 } | 298 } |
| 252 | 299 |
| 253 | 300 |
| 254 void Assembler::set_target_address_at(Address pc, Address target) { | 301 void Assembler::set_target_address_at(Address pc, Address target) { |
| 255 Memory::Address_at(target_address_address_at(pc)) = target; | 302 Memory::Address_at(target_address_address_at(pc)) = target; |
| 256 // Intuitively, we would think it is necessary to flush the instruction cache | 303 // Intuitively, we would think it is necessary to flush the instruction cache |
| 257 // after patching a target address in the code as follows: | 304 // after patching a target address in the code as follows: |
| 258 // CPU::FlushICache(pc, sizeof(target)); | 305 // CPU::FlushICache(pc, sizeof(target)); |
| 259 // However, on ARM, no instruction was actually patched by the assignment | 306 // However, on ARM, no instruction was actually patched by the assignment |
| 260 // above; the target address is not part of an instruction, it is patched in | 307 // above; the target address is not part of an instruction, it is patched in |
| 261 // the constant pool and is read via a data access; the instruction accessing | 308 // the constant pool and is read via a data access; the instruction accessing |
| 262 // this address in the constant pool remains unchanged. | 309 // this address in the constant pool remains unchanged. |
| 263 } | 310 } |
| 264 | 311 |
| 265 } } // namespace v8::internal | 312 } } // namespace v8::internal |
| 266 | 313 |
| 267 #endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_ | 314 #endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_ |
| OLD | NEW |