Chromium Code Reviews| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 return Assembler::target_address_at(pc_); | 66 return Assembler::target_address_at(pc_); |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 Address RelocInfo::target_address_address() { | 70 Address RelocInfo::target_address_address() { |
| 71 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); | 71 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
| 72 return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_)); | 72 return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_)); |
| 73 } | 73 } |
| 74 | 74 |
| 75 | 75 |
| 76 void RelocInfo::set_target_address(Address target) { | 76 void RelocInfo::set_target_address(Address target, bool need_icache_flush) { |
| 77 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); | 77 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
| 78 Assembler::set_target_address_at(pc_, target); | 78 Assembler::set_target_address_at(pc_, target, need_icache_flush); |
| 79 } | 79 } |
| 80 | 80 |
| 81 | 81 |
| 82 Object* RelocInfo::target_object() { | 82 Object* RelocInfo::target_object() { |
| 83 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 83 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 84 return Memory::Object_at(Assembler::target_address_address_at(pc_)); | 84 return Memory::Object_at(Assembler::target_address_address_at(pc_)); |
| 85 } | 85 } |
| 86 | 86 |
| 87 static uint32_t get_movw_movt_address(Address pc) { | |
| 88 Instr instr = Memory::int32_at(pc); | |
| 89 ASSERT((instr & kMovwMovtMask) == kMovwPattern); | |
| 90 Instr instr_movt = Memory::int32_at(pc + Assembler::kInstrSize); | |
| 91 int i = 0; | |
| 92 while ((instr_movt & kMovwMovtMask) != kMovtPattern) { | |
| 93 i++; | |
| 94 instr_movt = Memory::int32_at(pc + Assembler::kInstrSize * i); | |
| 95 } | |
| 96 ASSERT((instr_movt & kMovwMovtMask) == kMovtPattern); | |
| 97 uint32_t offset = ((instr & 0xf0000) >> 4) | (instr & 0xfff); | |
|
Erik Corry
2010/05/03 10:06:28
The name 'offset' seems wrong here. It's the imme
| |
| 98 int32_t offset_movt = ((instr_movt & 0xf0000) >> 4) | (instr_movt & 0xfff); | |
| 99 offset = offset | offset_movt << 16; | |
| 100 return offset; | |
| 101 } | |
| 102 | |
| 87 | 103 |
| 88 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 104 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
| 89 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 105 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 90 return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_)); | 106 Instr instr = Memory::int32_at(pc_); |
| 107 if ((instr & kLdrMask) == kLdrPattern) { | |
| 108 return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_)); | |
| 109 } else { | |
| 110 return reinterpret_cast<Object**>(get_movw_movt_address(pc_)); | |
|
Erik Corry
2010/05/03 10:06:28
This seems wrong. This function is expected to re
| |
| 111 } | |
| 91 } | 112 } |
| 92 | 113 |
| 93 | 114 |
| 94 Object** RelocInfo::target_object_address() { | 115 Object** RelocInfo::target_object_address() { |
| 95 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 116 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 96 return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_)); | 117 return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_)); |
| 97 } | 118 } |
| 98 | 119 |
| 99 | 120 |
| 100 void RelocInfo::set_target_object(Object* target) { | 121 void RelocInfo::set_target_object(Object* target, bool need_icache_flush) { |
| 101 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 122 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 102 Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); | 123 Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target), |
|
Erik Corry
2010/05/03 10:06:28
If all arguments don't fit on one line it is neate
| |
| 124 need_icache_flush); | |
| 103 } | 125 } |
| 104 | 126 |
| 105 | 127 |
| 106 Address* RelocInfo::target_reference_address() { | 128 Address* RelocInfo::target_reference_address() { |
| 107 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 129 ASSERT(rmode_ == EXTERNAL_REFERENCE); |
| 108 return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); | 130 return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); |
| 109 } | 131 } |
| 110 | 132 |
| 111 | 133 |
| 112 Address RelocInfo::call_address() { | 134 Address RelocInfo::call_address() { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 | 259 |
| 238 #ifdef USE_BLX | 260 #ifdef USE_BLX |
| 239 // If we have a blx instruction, the instruction before it is | 261 // If we have a blx instruction, the instruction before it is |
| 240 // what needs to be patched. | 262 // what needs to be patched. |
| 241 if ((instr & kBlxRegMask) == kBlxRegPattern) { | 263 if ((instr & kBlxRegMask) == kBlxRegPattern) { |
| 242 target_pc -= kInstrSize; | 264 target_pc -= kInstrSize; |
| 243 instr = Memory::int32_at(target_pc); | 265 instr = Memory::int32_at(target_pc); |
| 244 } | 266 } |
| 245 #endif | 267 #endif |
| 246 | 268 |
| 247 // Verify that the instruction to patch is a | 269 if ((instr & kLdrMask) == kLdrPattern) { |
| 248 // ldr<cond> <Rd>, [pc +/- offset_12]. | 270 int offset = instr & 0xfff; // offset_12 is unsigned |
| 249 ASSERT((instr & 0x0f7f0000) == 0x051f0000); | 271 // U bit defines offset sign |
| 250 int offset = instr & 0xfff; // offset_12 is unsigned | 272 if ((instr & (1 << 23)) == 0) offset = -offset; |
| 251 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign | 273 // Verify that the constant pool comes after the instruction referencing it. |
| 252 // Verify that the constant pool comes after the instruction referencing it. | 274 ASSERT(offset >= -4); |
| 253 ASSERT(offset >= -4); | 275 return pc + offset + 8; |
| 254 return target_pc + offset + 8; | 276 } else { |
| 277 return (Address) get_movw_movt_address(pc); | |
| 278 } | |
| 255 } | 279 } |
| 256 | 280 |
| 257 | 281 |
| 258 Address Assembler::target_address_at(Address pc) { | 282 Address Assembler::target_address_at(Address pc) { |
| 259 return Memory::Address_at(target_address_address_at(pc)); | 283 Instr instr = Memory::int32_at(pc); |
| 284 if ((instr & kLdrMask) == kLdrPattern) { | |
| 285 return Memory::Address_at(target_address_address_at(pc)); | |
| 286 } else { | |
| 287 return (Address) get_movw_movt_address(pc); | |
| 288 } | |
| 260 } | 289 } |
| 261 | 290 |
| 262 | 291 |
| 263 void Assembler::set_target_at(Address constant_pool_entry, | 292 void Assembler::set_target_at(Address constant_pool_entry, |
| 264 Address target) { | 293 Address target) { |
| 265 Memory::Address_at(constant_pool_entry) = target; | 294 Memory::Address_at(constant_pool_entry) = target; |
| 266 } | 295 } |
| 267 | 296 |
| 268 | 297 |
| 269 void Assembler::set_target_address_at(Address pc, Address target) { | 298 void Assembler::set_target_address_at(Address pc, Address target, |
|
Erik Corry
2010/05/03 10:06:28
Please put arguments either on one line or on a li
| |
| 270 Memory::Address_at(target_address_address_at(pc)) = target; | 299 bool need_icache_flush) { |
| 300 Instr instr = Memory::int32_at(pc); | |
| 301 if ((instr & kLdrMask) == kLdrPattern) { | |
| 302 Memory::Address_at(target_address_address_at(pc)) = target; | |
| 303 } else { | |
| 304 // movw movt instructions. | |
| 305 uint32_t* new_pc = reinterpret_cast<uint32_t*>(pc); | |
| 306 uint32_t new_addr = reinterpret_cast<uint32_t>(target); | |
| 307 *new_pc = (*new_pc & 0xfff0f000) | ((new_addr & 0xf000) << 4) | | |
|
Erik Corry
2010/05/03 10:06:28
Please give this constant, 0xfff0ff000, a name and
| |
| 308 (new_addr & 0xfff); | |
| 309 Instr instr_movt = Memory::int32_at(pc + Assembler::kInstrSize); | |
| 310 int i = 1; | |
| 311 while ((instr_movt & kMovwMovtMask) != kMovtPattern) { | |
| 312 i++; | |
| 313 instr_movt = Memory::int32_at(pc + Assembler::kInstrSize * i); | |
| 314 } | |
| 315 ASSERT((instr_movt & kMovwMovtMask) == kMovtPattern); | |
| 316 int32_t new_movt_addr = new_addr >> 16; | |
| 317 *(new_pc + i) = (*(new_pc + i) & 0xfff0f000) | | |
| 318 ((new_movt_addr & 0xf000) << 4) | (new_movt_addr & 0xfff); | |
| 319 if (need_icache_flush) | |
|
Erik Corry
2010/05/03 10:06:28
Please use braces on multiline if statements. Thi
| |
| 320 CPU::FlushICache(pc, sizeof(target)); | |
|
Erik Corry
2010/05/03 10:06:28
sizeof(target) looks wrong here. With the loop ab
| |
| 321 } | |
| 322 | |
| 271 // Intuitively, we would think it is necessary to flush the instruction cache | 323 // Intuitively, we would think it is necessary to flush the instruction cache |
| 272 // after patching a target address in the code as follows: | 324 // after patching a target address in the code as follows: |
| 273 // CPU::FlushICache(pc, sizeof(target)); | 325 // CPU::FlushICache(pc, sizeof(target)); |
| 274 // However, on ARM, no instruction was actually patched by the assignment | 326 // However, on ARM, no instruction was actually patched by the assignment |
| 275 // above; the target address is not part of an instruction, it is patched in | 327 // above; the target address is not part of an instruction, it is patched in |
| 276 // the constant pool and is read via a data access; the instruction accessing | 328 // the constant pool and is read via a data access; the instruction accessing |
| 277 // this address in the constant pool remains unchanged. | 329 // this address in the constant pool remains unchanged. |
| 278 } | 330 } |
| 279 | 331 |
| 280 } } // namespace v8::internal | 332 } } // namespace v8::internal |
| 281 | 333 |
| 282 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ | 334 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ |
| OLD | NEW |