| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 | 199 |
| 200 void Assembler::CheckBuffer() { | 200 void Assembler::CheckBuffer() { |
| 201 if (buffer_space() <= kGap) { | 201 if (buffer_space() <= kGap) { |
| 202 GrowBuffer(); | 202 GrowBuffer(); |
| 203 } | 203 } |
| 204 if (pc_offset() >= next_buffer_check_) { | 204 if (pc_offset() >= next_buffer_check_) { |
| 205 CheckConstPool(false, true); | 205 CheckConstPool(false, true); |
| 206 } | 206 } |
| 207 } | 207 } |
| 208 | 208 |
| 209 | 209 void Assembler::EnsureArmMode() { |
| 210 void Assembler::emit(Instr x) { | 210 if (thumb_mode_) { |
| 211 ASSERT((pc_offset() & 1) == 0); |
| 212 if ((pc_offset() & 2) != 0) { |
| 213 DataProcessingImm(ADD, LeaveCC, pc, pc, 1); |
| 214 // Pad with a 16 bit Thumb NOP. |
| 215 emit_thumb((int16_t) 0xbf00); |
| 216 } else { |
| 217 DataProcessingImm(SUB, LeaveCC, pc, pc, 1); |
| 218 } |
| 219 ASSERT((pc_offset() & 3) == 0); |
| 220 thumb_mode_ = false; |
| 221 } |
| 211 CheckBuffer(); | 222 CheckBuffer(); |
| 212 *reinterpret_cast<Instr*>(pc_) = x; | |
| 213 pc_ += kInstrSize; | |
| 214 } | 223 } |
| 215 | 224 |
| 225 void Assembler::EnsureThumbMode() { |
| 226 if (!thumb_mode_) { |
| 227 ASSERT((pc_offset() & 1) == 0); |
| 228 // Substract 3 from the PC (which is pointing to the current |
| 229 // instruction + 4) to go into thumb mode for the next instruction. |
| 230 emit_arm(al | B25 | B22 | pc.code() * B16 | pc.code() * B12 | 3); |
| 231 thumb_mode_ = true; |
| 232 ASSERT((pc_offset() & 1) == 0); |
| 233 } |
| 234 CheckBuffer(); |
| 235 } |
| 236 |
| 237 void Assembler::emit_arm(InstrArm x) { |
| 238 EnsureArmMode(); |
| 239 *reinterpret_cast<InstrArm*>(pc_) = x; |
| 240 pc_ += kInstrArmSize; |
| 241 } |
| 242 |
| 243 void Assembler::emit_int32(int32_t x) { |
| 244 CheckBuffer(); |
| 245 *reinterpret_cast<int32_t*>(pc_) = x; |
| 246 pc_ += sizeof(int32_t); |
| 247 } |
| 248 |
| 249 |
| 250 void Assembler::emit_thumb(InstrThumb x) { |
| 251 EnsureThumbMode(); |
| 252 *reinterpret_cast<InstrThumb*>(pc_) = x; |
| 253 pc_ += kInstrThumbSize; |
| 254 } |
| 216 | 255 |
| 217 Address Assembler::target_address_address_at(Address pc) { | 256 Address Assembler::target_address_address_at(Address pc) { |
| 218 Address target_pc = pc; | 257 Address target_pc = pc; |
| 219 Instr instr = Memory::int32_at(target_pc); | 258 Instr instr = Memory::int32_at(target_pc); |
| 220 // If we have a bx instruction, the instruction before the bx is | 259 // If we have a bx instruction, the instruction before the bx is |
| 221 // what we need to patch. | 260 // what we need to patch. |
| 222 static const int32_t kBxInstMask = 0x0ffffff0; | 261 static const int32_t kBxInstMask = 0x0ffffff0; |
| 223 static const int32_t kBxInstPattern = 0x012fff10; | 262 static const int32_t kBxInstPattern = 0x012fff10; |
| 224 if ((instr & kBxInstMask) == kBxInstPattern) { | 263 if ((instr & kBxInstMask) == kBxInstPattern) { |
| 225 target_pc -= kInstrSize; | 264 target_pc -= kInstrSize; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 254 // CPU::FlushICache(pc, sizeof(target)); | 293 // CPU::FlushICache(pc, sizeof(target)); |
| 255 // However, on ARM, no instruction was actually patched by the assignment | 294 // 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 | 295 // 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 | 296 // the constant pool and is read via a data access; the instruction accessing |
| 258 // this address in the constant pool remains unchanged. | 297 // this address in the constant pool remains unchanged. |
| 259 } | 298 } |
| 260 | 299 |
| 261 } } // namespace v8::internal | 300 } } // namespace v8::internal |
| 262 | 301 |
| 263 #endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_ | 302 #endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_ |
| OLD | NEW |