Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: src/arm/assembler-thumb2-inl.h

Issue 601028: Forking disassembler and simulator for Thumb2 support;... Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-thumb2.h ('k') | src/arm/debug-thumb2.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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_
OLDNEW
« no previous file with comments | « src/arm/assembler-thumb2.h ('k') | src/arm/debug-thumb2.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698