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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 137 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
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 Instr current_instr = Assembler::instr_at(pc_); |
148 // mov lr, pc | 148 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); |
149 // ldr pc, [pc, #XXX] | 149 #ifdef USE_BLX |
150 return (Assembler::instr_at(pc_) == kMovLrPc) | 150 // A patched return sequence is: |
151 && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern) | 151 // ldr ip, [pc, #0] |
152 == kLdrPCPattern); | 152 // blx ip |
| 153 return ((current_instr & kLdrPCMask) == kLdrPCPattern) |
| 154 && ((next_instr & kBlxRegMask) == kBlxRegPattern); |
| 155 #else |
| 156 // A patched return sequence is: |
| 157 // mov lr, pc |
| 158 // ldr pc, [pc, #-4] |
| 159 return (current_instr == kMovLrPc) |
| 160 && ((next_instr & kLdrPCMask) == kLdrPCPattern); |
| 161 #endif |
153 } | 162 } |
154 | 163 |
155 | 164 |
156 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { | 165 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { |
157 rm_ = no_reg; | 166 rm_ = no_reg; |
158 imm32_ = immediate; | 167 imm32_ = immediate; |
159 rmode_ = rmode; | 168 rmode_ = rmode; |
160 } | 169 } |
161 | 170 |
162 | 171 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 Address target_pc = pc; | 227 Address target_pc = pc; |
219 Instr instr = Memory::int32_at(target_pc); | 228 Instr instr = Memory::int32_at(target_pc); |
220 // If we have a bx instruction, the instruction before the bx is | 229 // If we have a bx instruction, the instruction before the bx is |
221 // what we need to patch. | 230 // what we need to patch. |
222 static const int32_t kBxInstMask = 0x0ffffff0; | 231 static const int32_t kBxInstMask = 0x0ffffff0; |
223 static const int32_t kBxInstPattern = 0x012fff10; | 232 static const int32_t kBxInstPattern = 0x012fff10; |
224 if ((instr & kBxInstMask) == kBxInstPattern) { | 233 if ((instr & kBxInstMask) == kBxInstPattern) { |
225 target_pc -= kInstrSize; | 234 target_pc -= kInstrSize; |
226 instr = Memory::int32_at(target_pc); | 235 instr = Memory::int32_at(target_pc); |
227 } | 236 } |
| 237 |
| 238 #ifdef USE_BLX |
| 239 // If we have a blx instruction, the instruction before it is |
| 240 // what needs to be patched. |
| 241 if ((instr & kBlxRegMask) == kBlxRegPattern) { |
| 242 target_pc -= kInstrSize; |
| 243 instr = Memory::int32_at(target_pc); |
| 244 } |
| 245 #endif |
| 246 |
228 // Verify that the instruction to patch is a | 247 // Verify that the instruction to patch is a |
229 // ldr<cond> <Rd>, [pc +/- offset_12]. | 248 // ldr<cond> <Rd>, [pc +/- offset_12]. |
230 ASSERT((instr & 0x0f7f0000) == 0x051f0000); | 249 ASSERT((instr & 0x0f7f0000) == 0x051f0000); |
231 int offset = instr & 0xfff; // offset_12 is unsigned | 250 int offset = instr & 0xfff; // offset_12 is unsigned |
232 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign | 251 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign |
233 // Verify that the constant pool comes after the instruction referencing it. | 252 // Verify that the constant pool comes after the instruction referencing it. |
234 ASSERT(offset >= -4); | 253 ASSERT(offset >= -4); |
235 return target_pc + offset + 8; | 254 return target_pc + offset + 8; |
236 } | 255 } |
237 | 256 |
(...skipping 16 matching lines...) Expand all Loading... |
254 // CPU::FlushICache(pc, sizeof(target)); | 273 // CPU::FlushICache(pc, sizeof(target)); |
255 // However, on ARM, no instruction was actually patched by the assignment | 274 // However, on ARM, no instruction was actually patched by the assignment |
256 // above; the target address is not part of an instruction, it is patched in | 275 // above; the target address is not part of an instruction, it is patched in |
257 // the constant pool and is read via a data access; the instruction accessing | 276 // the constant pool and is read via a data access; the instruction accessing |
258 // this address in the constant pool remains unchanged. | 277 // this address in the constant pool remains unchanged. |
259 } | 278 } |
260 | 279 |
261 } } // namespace v8::internal | 280 } } // namespace v8::internal |
262 | 281 |
263 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ | 282 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ |
OLD | NEW |