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

Side by Side Diff: src/mips/assembler-mips.cc

Issue 6709022: Re-establish mips basic infrastructure. (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Updated per comments, and rebased on r7312. Created 9 years, 9 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
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 are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // 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 22 matching lines...) Expand all
33 // Copyright 2010 the V8 project authors. All rights reserved. 33 // Copyright 2010 the V8 project authors. All rights reserved.
34 34
35 35
36 #include "v8.h" 36 #include "v8.h"
37 37
38 #if defined(V8_TARGET_ARCH_MIPS) 38 #if defined(V8_TARGET_ARCH_MIPS)
39 39
40 #include "mips/assembler-mips-inl.h" 40 #include "mips/assembler-mips-inl.h"
41 #include "serialize.h" 41 #include "serialize.h"
42 42
43
44 namespace v8 { 43 namespace v8 {
45 namespace internal { 44 namespace internal {
46 45
46 CpuFeatures::CpuFeatures()
47 : supported_(0),
48 enabled_(0),
49 found_by_runtime_probing_(0) {
50 }
47 51
52 void CpuFeatures::Probe(bool portable) {
53 // If the compiler is allowed to use fpu then we can use fpu too in our
54 // code generation.
55 #if !defined(__mips__)
56 // For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled.
57 if (FLAG_enable_fpu) {
58 supported_ |= 1u << FPU;
59 }
60 #else
61 if (portable && Serializer::enabled()) {
62 supported_ |= OS::CpuFeaturesImpliedByPlatform();
63 return; // No features if we might serialize.
64 }
48 65
49 const Register no_reg = { -1 }; 66 if (OS::MipsCpuHasFeature(FPU)) {
67 // This implementation also sets the FPU flags if
68 // runtime detection of FPU returns true.
69 supported_ |= 1u << FPU;
70 found_by_runtime_probing_ |= 1u << FPU;
71 }
50 72
51 const Register zero_reg = { 0 }; 73 if (!portable) found_by_runtime_probing_ = 0;
52 const Register at = { 1 }; 74 #endif
53 const Register v0 = { 2 }; 75 }
54 const Register v1 = { 3 };
55 const Register a0 = { 4 };
56 const Register a1 = { 5 };
57 const Register a2 = { 6 };
58 const Register a3 = { 7 };
59 const Register t0 = { 8 };
60 const Register t1 = { 9 };
61 const Register t2 = { 10 };
62 const Register t3 = { 11 };
63 const Register t4 = { 12 };
64 const Register t5 = { 13 };
65 const Register t6 = { 14 };
66 const Register t7 = { 15 };
67 const Register s0 = { 16 };
68 const Register s1 = { 17 };
69 const Register s2 = { 18 };
70 const Register s3 = { 19 };
71 const Register s4 = { 20 };
72 const Register s5 = { 21 };
73 const Register s6 = { 22 };
74 const Register s7 = { 23 };
75 const Register t8 = { 24 };
76 const Register t9 = { 25 };
77 const Register k0 = { 26 };
78 const Register k1 = { 27 };
79 const Register gp = { 28 };
80 const Register sp = { 29 };
81 const Register s8_fp = { 30 };
82 const Register ra = { 31 };
83 76
84 77
85 const FPURegister no_creg = { -1 };
86
87 const FPURegister f0 = { 0 };
88 const FPURegister f1 = { 1 };
89 const FPURegister f2 = { 2 };
90 const FPURegister f3 = { 3 };
91 const FPURegister f4 = { 4 };
92 const FPURegister f5 = { 5 };
93 const FPURegister f6 = { 6 };
94 const FPURegister f7 = { 7 };
95 const FPURegister f8 = { 8 };
96 const FPURegister f9 = { 9 };
97 const FPURegister f10 = { 10 };
98 const FPURegister f11 = { 11 };
99 const FPURegister f12 = { 12 };
100 const FPURegister f13 = { 13 };
101 const FPURegister f14 = { 14 };
102 const FPURegister f15 = { 15 };
103 const FPURegister f16 = { 16 };
104 const FPURegister f17 = { 17 };
105 const FPURegister f18 = { 18 };
106 const FPURegister f19 = { 19 };
107 const FPURegister f20 = { 20 };
108 const FPURegister f21 = { 21 };
109 const FPURegister f22 = { 22 };
110 const FPURegister f23 = { 23 };
111 const FPURegister f24 = { 24 };
112 const FPURegister f25 = { 25 };
113 const FPURegister f26 = { 26 };
114 const FPURegister f27 = { 27 };
115 const FPURegister f28 = { 28 };
116 const FPURegister f29 = { 29 };
117 const FPURegister f30 = { 30 };
118 const FPURegister f31 = { 31 };
119
120 int ToNumber(Register reg) { 78 int ToNumber(Register reg) {
121 ASSERT(reg.is_valid()); 79 ASSERT(reg.is_valid());
122 const int kNumbers[] = { 80 const int kNumbers[] = {
123 0, // zero_reg 81 0, // zero_reg
124 1, // at 82 1, // at
125 2, // v0 83 2, // v0
126 3, // v1 84 3, // v1
127 4, // a0 85 4, // a0
128 5, // a1 86 5, // a1
129 6, // a2 87 6, // a2
(...skipping 19 matching lines...) Expand all
149 26, // k0 107 26, // k0
150 27, // k1 108 27, // k1
151 28, // gp 109 28, // gp
152 29, // sp 110 29, // sp
153 30, // s8_fp 111 30, // s8_fp
154 31, // ra 112 31, // ra
155 }; 113 };
156 return kNumbers[reg.code()]; 114 return kNumbers[reg.code()];
157 } 115 }
158 116
117
159 Register ToRegister(int num) { 118 Register ToRegister(int num) {
160 ASSERT(num >= 0 && num < kNumRegisters); 119 ASSERT(num >= 0 && num < kNumRegisters);
161 const Register kRegisters[] = { 120 const Register kRegisters[] = {
162 zero_reg, 121 zero_reg,
163 at, 122 at,
164 v0, v1, 123 v0, v1,
165 a0, a1, a2, a3, 124 a0, a1, a2, a3,
166 t0, t1, t2, t3, t4, t5, t6, t7, 125 t0, t1, t2, t3, t4, t5, t6, t7,
167 s0, s1, s2, s3, s4, s5, s6, s7, 126 s0, s1, s2, s3, s4, s5, s6, s7,
168 t8, t9, 127 t8, t9,
169 k0, k1, 128 k0, k1,
170 gp, 129 gp,
171 sp, 130 sp,
172 s8_fp, 131 s8_fp,
173 ra 132 ra
174 }; 133 };
175 return kRegisters[num]; 134 return kRegisters[num];
176 } 135 }
177 136
178 137
179 // ----------------------------------------------------------------------------- 138 // -----------------------------------------------------------------------------
180 // Implementation of RelocInfo. 139 // Implementation of RelocInfo.
181 140
182 const int RelocInfo::kApplyMask = 0; 141 const int RelocInfo::kApplyMask = 0;
183 142
143
144 bool RelocInfo::IsCodedSpecially() {
145 // The deserializer needs to know whether a pointer is specially coded. Being
146 // specially coded on MIPS means that it is a lui/ori instruction, and that is
147 // always the case inside code objects.
148 return true;
149 }
150
151
184 // Patch the code at the current address with the supplied instructions. 152 // Patch the code at the current address with the supplied instructions.
185 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { 153 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
186 Instr* pc = reinterpret_cast<Instr*>(pc_); 154 Instr* pc = reinterpret_cast<Instr*>(pc_);
187 Instr* instr = reinterpret_cast<Instr*>(instructions); 155 Instr* instr = reinterpret_cast<Instr*>(instructions);
188 for (int i = 0; i < instruction_count; i++) { 156 for (int i = 0; i < instruction_count; i++) {
189 *(pc + i) = *(instr + i); 157 *(pc + i) = *(instr + i);
190 } 158 }
191 159
192 // Indicate that code has changed. 160 // Indicate that code has changed.
193 CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize); 161 CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
194 } 162 }
195 163
196 164
197 // Patch the code at the current PC with a call to the target address. 165 // Patch the code at the current PC with a call to the target address.
198 // Additional guard instructions can be added if required. 166 // Additional guard instructions can be added if required.
199 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 167 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
200 // Patch the code at the current address with a call to the target. 168 // Patch the code at the current address with a call to the target.
201 UNIMPLEMENTED_MIPS(); 169 UNIMPLEMENTED_MIPS();
202 } 170 }
203 171
204 172
205 // ----------------------------------------------------------------------------- 173 // -----------------------------------------------------------------------------
206 // Implementation of Operand and MemOperand. 174 // Implementation of Operand and MemOperand.
207 // See assembler-mips-inl.h for inlined constructors. 175 // See assembler-mips-inl.h for inlined constructors.
208 176
209 Operand::Operand(Handle<Object> handle) { 177 Operand::Operand(Handle<Object> handle) {
210 rm_ = no_reg; 178 rm_ = no_reg;
211 // Verify all Objects referred by code are NOT in new space. 179 // Verify all Objects referred by code are NOT in new space.
212 Object* obj = *handle; 180 Object* obj = *handle;
213 ASSERT(!Heap::InNewSpace(obj)); 181 ASSERT(!HEAP->InNewSpace(obj));
214 if (obj->IsHeapObject()) { 182 if (obj->IsHeapObject()) {
215 imm32_ = reinterpret_cast<intptr_t>(handle.location()); 183 imm32_ = reinterpret_cast<intptr_t>(handle.location());
216 rmode_ = RelocInfo::EMBEDDED_OBJECT; 184 rmode_ = RelocInfo::EMBEDDED_OBJECT;
217 } else { 185 } else {
218 // No relocation needed. 186 // No relocation needed.
219 imm32_ = reinterpret_cast<intptr_t>(obj); 187 imm32_ = reinterpret_cast<intptr_t>(obj);
220 rmode_ = RelocInfo::NONE; 188 rmode_ = RelocInfo::NONE;
221 } 189 }
222 } 190 }
223 191
224 MemOperand::MemOperand(Register rm, int16_t offset) : Operand(rm) { 192
193 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) {
225 offset_ = offset; 194 offset_ = offset;
226 } 195 }
227 196
228 197
229 // ----------------------------------------------------------------------------- 198 // -----------------------------------------------------------------------------
230 // Implementation of Assembler. 199 // Specific instructions, constants, and masks.
231 200
201 static const int kNegOffset = 0x00008000;
202 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
203 // operations as post-increment of sp.
204 const Instr kPopInstruction = ADDIU | (sp.code() << kRsShift)
205 | (sp.code() << kRtShift) | (kPointerSize & kImm16Mask);
206 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
207 const Instr kPushInstruction = ADDIU | (sp.code() << kRsShift)
208 | (sp.code() << kRtShift) | (-kPointerSize & kImm16Mask);
209 // sw(r, MemOperand(sp, 0))
210 const Instr kPushRegPattern = SW | (sp.code() << kRsShift)
211 | (0 & kImm16Mask);
212 // lw(r, MemOperand(sp, 0))
213 const Instr kPopRegPattern = LW | (sp.code() << kRsShift)
214 | (0 & kImm16Mask);
215
216 const Instr kLwRegFpOffsetPattern = LW | (s8_fp.code() << kRsShift)
217 | (0 & kImm16Mask);
218
219 const Instr kSwRegFpOffsetPattern = SW | (s8_fp.code() << kRsShift)
220 | (0 & kImm16Mask);
221
222 const Instr kLwRegFpNegOffsetPattern = LW | (s8_fp.code() << kRsShift)
223 | (kNegOffset & kImm16Mask);
224
225 const Instr kSwRegFpNegOffsetPattern = SW | (s8_fp.code() << kRsShift)
226 | (kNegOffset & kImm16Mask);
227 // A mask for the Rt register for push, pop, lw, sw instructions.
228 const Instr kRtMask = kRtFieldMask;
229 const Instr kLwSwInstrTypeMask = 0xffe00000;
230 const Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask;
231 const Instr kLwSwOffsetMask = kImm16Mask;
232
233
234 // Spare buffer.
232 static const int kMinimalBufferSize = 4*KB; 235 static const int kMinimalBufferSize = 4*KB;
Søren Thygesen Gjesse 2011/03/23 23:38:42 Spaces around binary operations.
Paul Lind 2011/03/26 18:39:17 Done.
233 static byte* spare_buffer_ = NULL;
234 236
235 Assembler::Assembler(void* buffer, int buffer_size) { 237
238 Assembler::Assembler(void* buffer, int buffer_size)
239 : AssemblerBase(Isolate::Current()),
240 positions_recorder_(this),
241 allow_peephole_optimization_(false) {
242 // BUG(3245989): disable peephole optimization if crankshaft is enabled.
243 allow_peephole_optimization_ = FLAG_peephole_optimization;
236 if (buffer == NULL) { 244 if (buffer == NULL) {
237 // Do our own buffer management. 245 // Do our own buffer management.
238 if (buffer_size <= kMinimalBufferSize) { 246 if (buffer_size <= kMinimalBufferSize) {
239 buffer_size = kMinimalBufferSize; 247 buffer_size = kMinimalBufferSize;
240 248
241 if (spare_buffer_ != NULL) { 249 if (isolate()->assembler_spare_buffer() != NULL) {
242 buffer = spare_buffer_; 250 buffer = isolate()->assembler_spare_buffer();
243 spare_buffer_ = NULL; 251 isolate()->set_assembler_spare_buffer(NULL);
244 } 252 }
245 } 253 }
246 if (buffer == NULL) { 254 if (buffer == NULL) {
247 buffer_ = NewArray<byte>(buffer_size); 255 buffer_ = NewArray<byte>(buffer_size);
248 } else { 256 } else {
249 buffer_ = static_cast<byte*>(buffer); 257 buffer_ = static_cast<byte*>(buffer);
250 } 258 }
251 buffer_size_ = buffer_size; 259 buffer_size_ = buffer_size;
252 own_buffer_ = true; 260 own_buffer_ = true;
253 261
254 } else { 262 } else {
255 // Use externally provided buffer instead. 263 // Use externally provided buffer instead.
256 ASSERT(buffer_size > 0); 264 ASSERT(buffer_size > 0);
257 buffer_ = static_cast<byte*>(buffer); 265 buffer_ = static_cast<byte*>(buffer);
258 buffer_size_ = buffer_size; 266 buffer_size_ = buffer_size;
259 own_buffer_ = false; 267 own_buffer_ = false;
260 } 268 }
261 269
262 // Setup buffer pointers. 270 // Setup buffer pointers.
263 ASSERT(buffer_ != NULL); 271 ASSERT(buffer_ != NULL);
264 pc_ = buffer_; 272 pc_ = buffer_;
265 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 273 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
266 current_statement_position_ = RelocInfo::kNoPosition; 274
267 current_position_ = RelocInfo::kNoPosition; 275 last_trampoline_pool_end_ = 0;
268 written_statement_position_ = current_statement_position_; 276 no_trampoline_pool_before_ = 0;
269 written_position_ = current_position_; 277 trampoline_pool_blocked_nesting_ = 0;
278 next_buffer_check_ = kMaxBranchOffset - kTrampolineSize;
270 } 279 }
271 280
272 281
273 Assembler::~Assembler() { 282 Assembler::~Assembler() {
274 if (own_buffer_) { 283 if (own_buffer_) {
275 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { 284 if (isolate()->assembler_spare_buffer() == NULL &&
276 spare_buffer_ = buffer_; 285 buffer_size_ == kMinimalBufferSize) {
286 isolate()->set_assembler_spare_buffer(buffer_);
277 } else { 287 } else {
278 DeleteArray(buffer_); 288 DeleteArray(buffer_);
279 } 289 }
280 } 290 }
281 } 291 }
282 292
283 293
284 void Assembler::GetCode(CodeDesc* desc) { 294 void Assembler::GetCode(CodeDesc* desc) {
285 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap 295 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap
286 // Setup code descriptor. 296 // Setup code descriptor.
287 desc->buffer = buffer_; 297 desc->buffer = buffer_;
288 desc->buffer_size = buffer_size_; 298 desc->buffer_size = buffer_size_;
289 desc->instr_size = pc_offset(); 299 desc->instr_size = pc_offset();
290 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 300 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
291 } 301 }
292 302
293 303
304 void Assembler::Align(int m) {
305 ASSERT(m >= 4 && IsPowerOf2(m));
306 while ((pc_offset() & (m - 1)) != 0) {
307 nop();
308 }
309 }
310
311
312 void Assembler::CodeTargetAlign() {
313 // No advantage to aligning branch/call targets to more than
314 // single instruction, that I am aware of.
315 Align(4);
316 }
317
318
319 Register Assembler::GetRt(Instr instr) {
320 Register rt;
321 rt.code_ = (instr & kRtMask) >> kRtShift;
322 return rt;
323 }
324
325
326 bool Assembler::IsPop(Instr instr) {
327 return (instr & ~kRtMask) == kPopRegPattern;
328 }
329
330
331 bool Assembler::IsPush(Instr instr) {
332 return (instr & ~kRtMask) == kPushRegPattern;
333 }
334
335
336 bool Assembler::IsSwRegFpOffset(Instr instr) {
337 return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
338 }
339
340
341 bool Assembler::IsLwRegFpOffset(Instr instr) {
342 return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
343 }
344
345
346 bool Assembler::IsSwRegFpNegOffset(Instr instr) {
347 return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
348 kSwRegFpNegOffsetPattern);
349 }
350
351
352 bool Assembler::IsLwRegFpNegOffset(Instr instr) {
353 return ((instr & (kLwSwInstrTypeMask | kNegOffset)) ==
354 kLwRegFpNegOffsetPattern);
355 }
356
357
294 // Labels refer to positions in the (to be) generated code. 358 // Labels refer to positions in the (to be) generated code.
295 // There are bound, linked, and unused labels. 359 // There are bound, linked, and unused labels.
296 // 360 //
297 // Bound labels refer to known positions in the already 361 // Bound labels refer to known positions in the already
298 // generated code. pos() is the position the label refers to. 362 // generated code. pos() is the position the label refers to.
299 // 363 //
300 // Linked labels refer to unknown positions in the code 364 // Linked labels refer to unknown positions in the code
301 // to be generated; pos() is the position of the last 365 // to be generated; pos() is the position of the last
302 // instruction using the label. 366 // instruction using the label.
303 367
368 // The link chain is terminated by a value in the instruction of -1,
369 // which is an otherwise illegal value (branch -1 is inf loop).
370 // The instruction 16-bit offset field addresses 32-bit words, but in
371 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
304 372
305 // The link chain is terminated by a negative code position (must be aligned).
306 const int kEndOfChain = -4; 373 const int kEndOfChain = -4;
307 374
308 bool Assembler::is_branch(Instr instr) { 375
376 bool Assembler::IsBranch(Instr instr) {
309 uint32_t opcode = ((instr & kOpcodeMask)); 377 uint32_t opcode = ((instr & kOpcodeMask));
310 uint32_t rt_field = ((instr & kRtFieldMask)); 378 uint32_t rt_field = ((instr & kRtFieldMask));
311 uint32_t rs_field = ((instr & kRsFieldMask)); 379 uint32_t rs_field = ((instr & kRsFieldMask));
380 uint32_t label_constant = (instr & ~kImm16Mask);
312 // Checks if the instruction is a branch. 381 // Checks if the instruction is a branch.
313 return opcode == BEQ || 382 return opcode == BEQ ||
314 opcode == BNE || 383 opcode == BNE ||
315 opcode == BLEZ || 384 opcode == BLEZ ||
316 opcode == BGTZ || 385 opcode == BGTZ ||
317 opcode == BEQL || 386 opcode == BEQL ||
318 opcode == BNEL || 387 opcode == BNEL ||
319 opcode == BLEZL || 388 opcode == BLEZL ||
320 opcode == BGTZL|| 389 opcode == BGTZL||
321 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || 390 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
322 rt_field == BLTZAL || rt_field == BGEZAL)) || 391 rt_field == BLTZAL || rt_field == BGEZAL)) ||
323 (opcode == COP1 && rs_field == BC1); // Coprocessor branch. 392 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
393 label_constant == 0; // Emitted label const in reg-exp engine.
324 } 394 }
325 395
326 396
397 bool Assembler::IsNop(Instr instr, unsigned int type) {
398 // See Assembler::nop(type).
399 ASSERT(type < 32);
400 uint32_t opcode = ((instr & kOpcodeMask));
401 uint32_t rt = ((instr & kRtFieldMask) >> kRtShift);
402 uint32_t rs = ((instr & kRsFieldMask) >> kRsShift);
403 uint32_t sa = ((instr & kSaFieldMask) >> kSaShift);
404
405 // nop(type) == sll(zero_reg, zero_reg, type);
406 // Technically all these values will be 0 but
407 // this makes more sense to the reader.
408
409 bool ret = (opcode == SLL &&
Søren Thygesen Gjesse 2011/03/23 23:38:42 Indention off - indent to parentesis.
Paul Lind 2011/03/26 18:39:17 Done.
410 rt == static_cast<uint32_t>(ToNumber(zero_reg)) &&
411 rs == static_cast<uint32_t>(ToNumber(zero_reg)) &&
412 sa == type);
413
414 return ret;
415 }
416
417
418 int32_t Assembler::GetBranchOffset(Instr instr) {
419 ASSERT(IsBranch(instr));
420 return ((int16_t)(instr & kImm16Mask)) << 2;
421 }
422
423
424 bool Assembler::IsLw(Instr instr) {
425 return ((instr & kOpcodeMask) == LW);
426 }
427
428
429 int16_t Assembler::GetLwOffset(Instr instr) {
430 ASSERT(IsLw(instr));
431 return ((instr & kImm16Mask));
432 }
433
434
435 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
436 ASSERT(IsLw(instr));
437
438 // We actually create a new lw instruction based on the original one.
Søren Thygesen Gjesse 2011/03/23 23:38:42 Format this Instr temp_instr = LW |
Paul Lind 2011/03/26 18:39:17 Done.
439 Instr temp_instr = LW |
440 (instr & kRsFieldMask) |
441 (instr & kRtFieldMask) |
442 (offset & kImm16Mask);
443
444 return temp_instr;
445 }
446
447
448 bool Assembler::IsSw(Instr instr) {
449 return ((instr & kOpcodeMask) == SW);
450 }
451
452
453 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
454 ASSERT(IsSw(instr));
455 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
456 }
457
458
459 bool Assembler::IsAddImmediate(Instr instr) {
460 return ((instr & kOpcodeMask) == ADDIU);
461 }
462
463
464 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
465 ASSERT(IsAddImmediate(instr));
466 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
467 }
468
469
327 int Assembler::target_at(int32_t pos) { 470 int Assembler::target_at(int32_t pos) {
328 Instr instr = instr_at(pos); 471 Instr instr = instr_at(pos);
329 if ((instr & ~kImm16Mask) == 0) { 472 if ((instr & ~kImm16Mask) == 0) {
330 // Emitted label constant, not part of a branch. 473 // Emitted label constant, not part of a branch.
331 return instr - (Code::kHeaderSize - kHeapObjectTag); 474 if (instr == 0) {
475 return kEndOfChain;
476 } else {
477 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
478 return (imm18 + pos);
479 }
332 } 480 }
333 // Check we have a branch instruction. 481 // Check we have a branch instruction.
334 ASSERT(is_branch(instr)); 482 ASSERT(IsBranch(instr));
335 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 483 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
336 // the compiler uses arithmectic shifts for signed integers. 484 // the compiler uses arithmectic shifts for signed integers.
337 int32_t imm18 = ((instr & 485 int32_t imm18 = ((instr &
338 static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 486 static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
339 487
340 return pos + kBranchPCOffset + imm18; 488 if (imm18 == kEndOfChain) {
489 // EndOfChain sentinel is returned directly, not relative to pc or pos.
490 return kEndOfChain;
491 } else {
492 return pos + kBranchPCOffset + imm18;
493 }
341 } 494 }
342 495
343 496
344 void Assembler::target_at_put(int32_t pos, int32_t target_pos) { 497 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
345 Instr instr = instr_at(pos); 498 Instr instr = instr_at(pos);
346 if ((instr & ~kImm16Mask) == 0) { 499 if ((instr & ~kImm16Mask) == 0) {
347 ASSERT(target_pos == kEndOfChain || target_pos >= 0); 500 ASSERT(target_pos == kEndOfChain || target_pos >= 0);
348 // Emitted label constant, not part of a branch. 501 // Emitted label constant, not part of a branch.
349 // Make label relative to Code* of generated Code object. 502 // Make label relative to Code* of generated Code object.
350 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 503 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
351 return; 504 return;
352 } 505 }
353 506
354 ASSERT(is_branch(instr)); 507 ASSERT(IsBranch(instr));
355 int32_t imm18 = target_pos - (pos + kBranchPCOffset); 508 int32_t imm18 = target_pos - (pos + kBranchPCOffset);
356 ASSERT((imm18 & 3) == 0); 509 ASSERT((imm18 & 3) == 0);
357 510
358 instr &= ~kImm16Mask; 511 instr &= ~kImm16Mask;
359 int32_t imm16 = imm18 >> 2; 512 int32_t imm16 = imm18 >> 2;
360 ASSERT(is_int16(imm16)); 513 ASSERT(is_int16(imm16));
361 514
362 instr_at_put(pos, instr | (imm16 & kImm16Mask)); 515 instr_at_put(pos, instr | (imm16 & kImm16Mask));
363 } 516 }
364 517
(...skipping 16 matching lines...) Expand all
381 } 534 }
382 next(&l); 535 next(&l);
383 } 536 }
384 } else { 537 } else {
385 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 538 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
386 } 539 }
387 } 540 }
388 541
389 542
390 void Assembler::bind_to(Label* L, int pos) { 543 void Assembler::bind_to(Label* L, int pos) {
391 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position 544 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
Søren Thygesen Gjesse 2011/03/23 23:38:42 Case + full stop in comment.
Paul Lind 2011/03/26 18:39:17 Fixed this one, and all the others in the file. So
392 while (L->is_linked()) { 545 while (L->is_linked()) {
393 int32_t fixup_pos = L->pos(); 546 int32_t fixup_pos = L->pos();
547 int32_t dist = pos - fixup_pos;
394 next(L); // call next before overwriting link with target at fixup_pos 548 next(L); // call next before overwriting link with target at fixup_pos
549 if (dist > kMaxBranchOffset) {
550 do {
551 int32_t trampoline_pos = get_trampoline_entry(fixup_pos);
552 ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
553 target_at_put(fixup_pos, trampoline_pos);
554 fixup_pos = trampoline_pos;
555 dist = pos - fixup_pos;
556 } while (dist > kMaxBranchOffset);
557 } else if (dist < -kMaxBranchOffset) {
558 do {
559 int32_t trampoline_pos = get_trampoline_entry(fixup_pos, false);
560 ASSERT((trampoline_pos - fixup_pos) >= -kMaxBranchOffset);
561 target_at_put(fixup_pos, trampoline_pos);
562 fixup_pos = trampoline_pos;
563 dist = pos - fixup_pos;
564 } while (dist < -kMaxBranchOffset);
565 };
395 target_at_put(fixup_pos, pos); 566 target_at_put(fixup_pos, pos);
396 } 567 }
397 L->bind_to(pos); 568 L->bind_to(pos);
398 569
399 // Keep track of the last bound label so we don't eliminate any instructions 570 // Keep track of the last bound label so we don't eliminate any instructions
400 // before a bound label. 571 // before a bound label.
401 if (pos > last_bound_pos_) 572 if (pos > last_bound_pos_)
402 last_bound_pos_ = pos; 573 last_bound_pos_ = pos;
403 } 574 }
404 575
(...skipping 21 matching lines...) Expand all
426 597
427 void Assembler::bind(Label* L) { 598 void Assembler::bind(Label* L) {
428 ASSERT(!L->is_bound()); // label can only be bound once 599 ASSERT(!L->is_bound()); // label can only be bound once
429 bind_to(L, pc_offset()); 600 bind_to(L, pc_offset());
430 } 601 }
431 602
432 603
433 void Assembler::next(Label* L) { 604 void Assembler::next(Label* L) {
434 ASSERT(L->is_linked()); 605 ASSERT(L->is_linked());
435 int link = target_at(L->pos()); 606 int link = target_at(L->pos());
436 if (link > 0) { 607 ASSERT(link > 0 || link == kEndOfChain);
608 if (link == kEndOfChain) {
609 L->Unuse();
610 } else if (link > 0) {
437 L->link_to(link); 611 L->link_to(link);
438 } else {
439 ASSERT(link == kEndOfChain);
440 L->Unuse();
441 } 612 }
442 } 613 }
443 614
444 615
445 // We have to use a temporary register for things that can be relocated even 616 // We have to use a temporary register for things that can be relocated even
446 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction 617 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
447 // space. There is no guarantee that the relocated location can be similarly 618 // space. There is no guarantee that the relocated location can be similarly
448 // encoded. 619 // encoded.
449 bool Assembler::MustUseAt(RelocInfo::Mode rmode) { 620 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
450 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 621 return rmode != RelocInfo::NONE;
451 return Serializer::enabled();
452 } else if (rmode == RelocInfo::NONE) {
453 return false;
454 }
455 return true;
456 } 622 }
457 623
458 624
459 void Assembler::GenInstrRegister(Opcode opcode, 625 void Assembler::GenInstrRegister(Opcode opcode,
460 Register rs, 626 Register rs,
461 Register rt, 627 Register rt,
462 Register rd, 628 Register rd,
463 uint16_t sa, 629 uint16_t sa,
464 SecondaryField func) { 630 SecondaryField func) {
465 ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa)); 631 ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
466 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 632 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
467 | (rd.code() << kRdShift) | (sa << kSaShift) | func; 633 | (rd.code() << kRdShift) | (sa << kSaShift) | func;
468 emit(instr); 634 emit(instr);
469 } 635 }
470 636
471 637
472 void Assembler::GenInstrRegister(Opcode opcode, 638 void Assembler::GenInstrRegister(Opcode opcode,
639 Register rs,
640 Register rt,
641 uint16_t msb,
642 uint16_t lsb,
643 SecondaryField func) {
644 ASSERT(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
645 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
646 | (msb << kRdShift) | (lsb << kSaShift) | func;
647 emit(instr);
648 }
649
650
651 void Assembler::GenInstrRegister(Opcode opcode,
473 SecondaryField fmt, 652 SecondaryField fmt,
474 FPURegister ft, 653 FPURegister ft,
475 FPURegister fs, 654 FPURegister fs,
476 FPURegister fd, 655 FPURegister fd,
477 SecondaryField func) { 656 SecondaryField func) {
478 ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid()); 657 ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
Søren Thygesen Gjesse 2011/03/24 22:11:19 Shouldn't this and all other FPU instructions star
Paul Lind 2011/03/26 18:39:17 Yes. Done.
479 Instr instr = opcode | fmt | (ft.code() << 16) | (fs.code() << kFsShift) 658 Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
480 | (fd.code() << 6) | func; 659 | (fd.code() << kFdShift) | func;
481 emit(instr); 660 emit(instr);
482 } 661 }
483 662
484 663
485 void Assembler::GenInstrRegister(Opcode opcode, 664 void Assembler::GenInstrRegister(Opcode opcode,
486 SecondaryField fmt, 665 SecondaryField fmt,
487 Register rt, 666 Register rt,
488 FPURegister fs, 667 FPURegister fs,
489 FPURegister fd, 668 FPURegister fd,
490 SecondaryField func) { 669 SecondaryField func) {
491 ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid()); 670 ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
492 Instr instr = opcode | fmt | (rt.code() << kRtShift) 671 Instr instr = opcode | fmt | (rt.code() << kRtShift)
493 | (fs.code() << kFsShift) | (fd.code() << 6) | func; 672 | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
494 emit(instr); 673 emit(instr);
495 } 674 }
496 675
676
677 void Assembler::GenInstrRegister(Opcode opcode,
678 SecondaryField fmt,
679 Register rt,
680 FPUControlRegister fs,
681 SecondaryField func) {
682 ASSERT(fs.is_valid() && rt.is_valid());
683 Instr instr = opcode | fmt | (rt.code() << kRtShift)
684 | (fs.code() << kFsShift) | func;
685 emit(instr);
686 }
687
497 688
498 // Instructions with immediate value. 689 // Instructions with immediate value.
499 // Registers are in the order of the instruction encoding, from left to right. 690 // Registers are in the order of the instruction encoding, from left to right.
500 void Assembler::GenInstrImmediate(Opcode opcode, 691 void Assembler::GenInstrImmediate(Opcode opcode,
501 Register rs, 692 Register rs,
502 Register rt, 693 Register rt,
503 int32_t j) { 694 int32_t j) {
504 ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); 695 ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
505 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 696 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
506 | (j & kImm16Mask); 697 | (j & kImm16Mask);
(...skipping 18 matching lines...) Expand all
525 ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); 716 ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
526 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) 717 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
527 | (j & kImm16Mask); 718 | (j & kImm16Mask);
528 emit(instr); 719 emit(instr);
529 } 720 }
530 721
531 722
532 // Registers are in the order of the instruction encoding, from left to right. 723 // Registers are in the order of the instruction encoding, from left to right.
533 void Assembler::GenInstrJump(Opcode opcode, 724 void Assembler::GenInstrJump(Opcode opcode,
534 uint32_t address) { 725 uint32_t address) {
726 BlockTrampolinePoolScope block_trampoline_pool(this);
535 ASSERT(is_uint26(address)); 727 ASSERT(is_uint26(address));
536 Instr instr = opcode | address; 728 Instr instr = opcode | address;
537 emit(instr); 729 emit(instr);
730 BlockTrampolinePoolFor(1);
731 }
732
733
734 // Returns the next free label entry from the next trampoline pool.
735 int32_t Assembler::get_label_entry(int32_t pos, bool next_pool) {
736 int trampoline_count = trampolines_.length();
737 int32_t label_entry = 0;
738 ASSERT(trampoline_count > 0);
739
740 if (next_pool) {
741 for (int i = 0; i < trampoline_count; i++) {
742 if (trampolines_[i].start() > pos) {
743 label_entry = trampolines_[i].take_label();
744 break;
745 }
746 }
747 } else { // Caller needs a label entry from the previous pool.
748 for (int i = trampoline_count-1; i >= 0; i--) {
749 if (trampolines_[i].end() < pos) {
750 label_entry = trampolines_[i].take_label();
751 break;
752 }
753 }
754 }
755 return label_entry;
756 }
757
758
759 // Returns the next free trampoline entry from the next trampoline pool.
760 int32_t Assembler::get_trampoline_entry(int32_t pos, bool next_pool) {
761 int trampoline_count = trampolines_.length();
762 int32_t trampoline_entry = 0;
763 ASSERT(trampoline_count > 0);
764
765 if (next_pool) {
766 for (int i = 0; i < trampoline_count; i++) {
767 if (trampolines_[i].start() > pos) {
768 trampoline_entry = trampolines_[i].take_slot();
769 break;
770 }
771 }
772 } else { // Caller needs a trampoline entry from the previous pool.
773 for (int i = trampoline_count-1; i >= 0; i--) {
774 if (trampolines_[i].end() < pos) {
775 trampoline_entry = trampolines_[i].take_slot();
776 break;
777 }
778 }
779 }
780 return trampoline_entry;
538 } 781 }
539 782
540 783
541 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 784 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
542 int32_t target_pos; 785 int32_t target_pos;
786 int32_t pc_offset_v = pc_offset();
787
543 if (L->is_bound()) { 788 if (L->is_bound()) {
544 target_pos = L->pos(); 789 target_pos = L->pos();
790 int32_t dist = pc_offset_v - target_pos;
791 if (dist > kMaxBranchOffset) {
792 do {
793 int32_t trampoline_pos = get_trampoline_entry(target_pos);
794 ASSERT((trampoline_pos - target_pos) > 0);
795 ASSERT((trampoline_pos - target_pos) <= kMaxBranchOffset);
796 target_at_put(trampoline_pos, target_pos);
797 target_pos = trampoline_pos;
798 dist = pc_offset_v - target_pos;
799 } while (dist > kMaxBranchOffset);
800 } else if (dist < -kMaxBranchOffset) {
801 do {
802 int32_t trampoline_pos = get_trampoline_entry(target_pos, false);
803 ASSERT((target_pos - trampoline_pos) > 0);
804 ASSERT((target_pos - trampoline_pos) <= kMaxBranchOffset);
805 target_at_put(trampoline_pos, target_pos);
806 target_pos = trampoline_pos;
807 dist = pc_offset_v - target_pos;
808 } while (dist < -kMaxBranchOffset);
809 }
545 } else { 810 } else {
546 if (L->is_linked()) { 811 if (L->is_linked()) {
547 target_pos = L->pos(); // L's link 812 target_pos = L->pos(); // L's link
813 int32_t dist = pc_offset_v - target_pos;
814 if (dist > kMaxBranchOffset) {
815 do {
816 int32_t label_pos = get_label_entry(target_pos);
817 ASSERT((label_pos - target_pos) < kMaxBranchOffset);
818 label_at_put(L, label_pos);
819 target_pos = label_pos;
820 dist = pc_offset_v - target_pos;
821 } while (dist > kMaxBranchOffset);
822 } else if (dist < -kMaxBranchOffset) {
823 do {
824 int32_t label_pos = get_label_entry(target_pos, false);
825 ASSERT((label_pos - target_pos) > -kMaxBranchOffset);
826 label_at_put(L, label_pos);
827 target_pos = label_pos;
828 dist = pc_offset_v - target_pos;
829 } while (dist < -kMaxBranchOffset);
830 }
831 L->link_to(pc_offset());
548 } else { 832 } else {
549 target_pos = kEndOfChain; 833 L->link_to(pc_offset());
834 return kEndOfChain;
550 } 835 }
551 L->link_to(pc_offset());
552 } 836 }
553 837
554 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); 838 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
839 ASSERT((offset & 3) == 0);
840 ASSERT(is_int16(offset >> 2));
841
555 return offset; 842 return offset;
556 } 843 }
557 844
558 845
559 void Assembler::label_at_put(Label* L, int at_offset) { 846 void Assembler::label_at_put(Label* L, int at_offset) {
560 int target_pos; 847 int target_pos;
561 if (L->is_bound()) { 848 if (L->is_bound()) {
562 target_pos = L->pos(); 849 target_pos = L->pos();
850 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
563 } else { 851 } else {
564 if (L->is_linked()) { 852 if (L->is_linked()) {
565 target_pos = L->pos(); // L's link 853 target_pos = L->pos(); // L's link
854 int32_t imm18 = target_pos - at_offset;
855 ASSERT((imm18 & 3) == 0);
856 int32_t imm16 = imm18 >> 2;
857 ASSERT(is_int16(imm16));
858 instr_at_put(at_offset, (imm16 & kImm16Mask));
566 } else { 859 } else {
567 target_pos = kEndOfChain; 860 target_pos = kEndOfChain;
861 instr_at_put(at_offset, 0);
568 } 862 }
569 L->link_to(at_offset); 863 L->link_to(at_offset);
570 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
571 } 864 }
572 } 865 }
573 866
574 867
575 //------- Branch and jump instructions -------- 868 //------- Branch and jump instructions --------
576 869
577 void Assembler::b(int16_t offset) { 870 void Assembler::b(int16_t offset) {
578 beq(zero_reg, zero_reg, offset); 871 beq(zero_reg, zero_reg, offset);
579 } 872 }
580 873
581 874
582 void Assembler::bal(int16_t offset) { 875 void Assembler::bal(int16_t offset) {
876 positions_recorder()->WriteRecordedPositions();
583 bgezal(zero_reg, offset); 877 bgezal(zero_reg, offset);
584 } 878 }
585 879
586 880
587 void Assembler::beq(Register rs, Register rt, int16_t offset) { 881 void Assembler::beq(Register rs, Register rt, int16_t offset) {
882 BlockTrampolinePoolScope block_trampoline_pool(this);
588 GenInstrImmediate(BEQ, rs, rt, offset); 883 GenInstrImmediate(BEQ, rs, rt, offset);
884 BlockTrampolinePoolFor(1);
Søren Thygesen Gjesse 2011/03/23 23:38:42 This additional blocking for one instruction is th
Paul Lind 2011/03/26 18:39:17 Yes, it is for the delay slot. In this file, that
589 } 885 }
590 886
591 887
592 void Assembler::bgez(Register rs, int16_t offset) { 888 void Assembler::bgez(Register rs, int16_t offset) {
889 BlockTrampolinePoolScope block_trampoline_pool(this);
593 GenInstrImmediate(REGIMM, rs, BGEZ, offset); 890 GenInstrImmediate(REGIMM, rs, BGEZ, offset);
891 BlockTrampolinePoolFor(1);
594 } 892 }
595 893
596 894
597 void Assembler::bgezal(Register rs, int16_t offset) { 895 void Assembler::bgezal(Register rs, int16_t offset) {
896 BlockTrampolinePoolScope block_trampoline_pool(this);
897 positions_recorder()->WriteRecordedPositions();
598 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); 898 GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
899 BlockTrampolinePoolFor(1);
599 } 900 }
600 901
601 902
602 void Assembler::bgtz(Register rs, int16_t offset) { 903 void Assembler::bgtz(Register rs, int16_t offset) {
904 BlockTrampolinePoolScope block_trampoline_pool(this);
603 GenInstrImmediate(BGTZ, rs, zero_reg, offset); 905 GenInstrImmediate(BGTZ, rs, zero_reg, offset);
906 BlockTrampolinePoolFor(1);
604 } 907 }
605 908
606 909
607 void Assembler::blez(Register rs, int16_t offset) { 910 void Assembler::blez(Register rs, int16_t offset) {
911 BlockTrampolinePoolScope block_trampoline_pool(this);
608 GenInstrImmediate(BLEZ, rs, zero_reg, offset); 912 GenInstrImmediate(BLEZ, rs, zero_reg, offset);
913 BlockTrampolinePoolFor(1);
609 } 914 }
610 915
611 916
612 void Assembler::bltz(Register rs, int16_t offset) { 917 void Assembler::bltz(Register rs, int16_t offset) {
918 BlockTrampolinePoolScope block_trampoline_pool(this);
613 GenInstrImmediate(REGIMM, rs, BLTZ, offset); 919 GenInstrImmediate(REGIMM, rs, BLTZ, offset);
920 BlockTrampolinePoolFor(1);
614 } 921 }
615 922
616 923
617 void Assembler::bltzal(Register rs, int16_t offset) { 924 void Assembler::bltzal(Register rs, int16_t offset) {
925 BlockTrampolinePoolScope block_trampoline_pool(this);
926 positions_recorder()->WriteRecordedPositions();
618 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); 927 GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
928 BlockTrampolinePoolFor(1);
619 } 929 }
620 930
621 931
622 void Assembler::bne(Register rs, Register rt, int16_t offset) { 932 void Assembler::bne(Register rs, Register rt, int16_t offset) {
933 BlockTrampolinePoolScope block_trampoline_pool(this);
623 GenInstrImmediate(BNE, rs, rt, offset); 934 GenInstrImmediate(BNE, rs, rt, offset);
935 BlockTrampolinePoolFor(1);
624 } 936 }
625 937
626 938
627 void Assembler::j(int32_t target) { 939 void Assembler::j(int32_t target) {
628 ASSERT(is_uint28(target) && ((target & 3) == 0)); 940 ASSERT(is_uint28(target) && ((target & 3) == 0));
629 GenInstrJump(J, target >> 2); 941 GenInstrJump(J, target >> 2);
630 } 942 }
631 943
632 944
633 void Assembler::jr(Register rs) { 945 void Assembler::jr(Register rs) {
946 BlockTrampolinePoolScope block_trampoline_pool(this);
947 if (rs.is(ra)) {
948 positions_recorder()->WriteRecordedPositions();
949 }
634 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); 950 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
951 BlockTrampolinePoolFor(1);
635 } 952 }
636 953
637 954
638 void Assembler::jal(int32_t target) { 955 void Assembler::jal(int32_t target) {
956 positions_recorder()->WriteRecordedPositions();
639 ASSERT(is_uint28(target) && ((target & 3) == 0)); 957 ASSERT(is_uint28(target) && ((target & 3) == 0));
640 GenInstrJump(JAL, target >> 2); 958 GenInstrJump(JAL, target >> 2);
641 } 959 }
642 960
643 961
644 void Assembler::jalr(Register rs, Register rd) { 962 void Assembler::jalr(Register rs, Register rd) {
963 BlockTrampolinePoolScope block_trampoline_pool(this);
964 positions_recorder()->WriteRecordedPositions();
645 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); 965 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
966 BlockTrampolinePoolFor(1);
646 } 967 }
647 968
648 969
649 //-------Data-processing-instructions--------- 970 //-------Data-processing-instructions---------
650 971
651 // Arithmetic. 972 // Arithmetic.
652 973
653 void Assembler::add(Register rd, Register rs, Register rt) {
654 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADD);
655 }
656
657
658 void Assembler::addu(Register rd, Register rs, Register rt) { 974 void Assembler::addu(Register rd, Register rs, Register rt) {
659 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 975 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
660 } 976 }
661 977
662 978
663 void Assembler::addi(Register rd, Register rs, int32_t j) { 979 void Assembler::addiu(Register rd, Register rs, int32_t j) {
664 GenInstrImmediate(ADDI, rs, rd, j); 980 GenInstrImmediate(ADDIU, rs, rd, j);
981
982 // Eliminate pattern: push(r), pop()
983 // addiu(sp, sp, Operand(-kPointerSize));
984 // sw(src, MemOperand(sp, 0);
985 // addiu(sp, sp, Operand(kPointerSize));
986 // Both instructions can be eliminated.
987 if (can_peephole_optimize(3) &&
988 // Pattern.
989 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
990 (instr_at(pc_ - 2 * kInstrSize) & ~kRtMask) == kPushRegPattern &&
991 (instr_at(pc_ - 3 * kInstrSize)) == kPushInstruction) {
992 pc_ -= 3 * kInstrSize;
993 if (FLAG_print_peephole_optimization) {
994 PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
995 }
996 }
997
998 // Eliminate pattern: push(ry), pop(rx)
999 // addiu(sp, sp, -kPointerSize)
1000 // sw(ry, MemOperand(sp, 0)
1001 // lw(rx, MemOperand(sp, 0)
1002 // addiu(sp, sp, kPointerSize);
1003 // Both instructions can be eliminated if ry = rx.
1004 // If ry != rx, a register copy from ry to rx is inserted
1005 // after eliminating the push and the pop instructions.
1006 if (can_peephole_optimize(4)) {
1007 Instr pre_push_sp_set = instr_at(pc_ - 4 * kInstrSize);
1008 Instr push_instr = instr_at(pc_ - 3 * kInstrSize);
1009 Instr pop_instr = instr_at(pc_ - 2 * kInstrSize);
1010 Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize);
1011
1012 if (IsPush(push_instr) &&
1013 IsPop(pop_instr) && pre_push_sp_set == kPushInstruction &&
1014 post_pop_sp_set == kPopInstruction) {
1015 if ((pop_instr & kRtMask) != (push_instr & kRtMask)) {
1016 // For consecutive push and pop on different registers,
1017 // we delete both the push & pop and insert a register move.
1018 // push ry, pop rx --> mov rx, ry
1019 Register reg_pushed, reg_popped;
1020 reg_pushed = GetRt(push_instr);
1021 reg_popped = GetRt(pop_instr);
1022 pc_ -= 4 * kInstrSize;
1023 // Insert a mov instruction, which is better than a pair of push & pop
1024 or_(reg_popped, reg_pushed, zero_reg);
1025 if (FLAG_print_peephole_optimization) {
1026 PrintF("%x push/pop (diff reg) replaced by a reg move\n",
1027 pc_offset());
1028 }
1029 } else {
1030 // For consecutive push and pop on the same register,
1031 // both the push and the pop can be deleted.
1032 pc_ -= 4 * kInstrSize;
1033 if (FLAG_print_peephole_optimization) {
1034 PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
1035 }
1036 }
1037 }
1038 }
1039
1040 if (can_peephole_optimize(5)) {
1041 Instr pre_push_sp_set = instr_at(pc_ - 5 * kInstrSize);
1042 Instr mem_write_instr = instr_at(pc_ - 4 * kInstrSize);
1043 Instr lw_instr = instr_at(pc_ - 3 * kInstrSize);
1044 Instr mem_read_instr = instr_at(pc_ - 2 * kInstrSize);
1045 Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize);
1046
1047 if (IsPush(mem_write_instr) &&
1048 pre_push_sp_set == kPushInstruction &&
1049 IsPop(mem_read_instr) &&
1050 post_pop_sp_set == kPopInstruction) {
1051 if ((IsLwRegFpOffset(lw_instr) ||
1052 IsLwRegFpNegOffset(lw_instr))) {
1053 if ((mem_write_instr & kRtMask) ==
1054 (mem_read_instr & kRtMask)) {
1055 // Pattern: push & pop from/to same register,
1056 // with a fp+offset lw in between
1057 //
1058 // The following:
1059 // addiu sp, sp, -4
1060 // sw rx, [sp, #0]!
1061 // lw rz, [fp, #-24]
1062 // lw rx, [sp, 0],
1063 // addiu sp, sp, 4
1064 //
1065 // Becomes:
1066 // if(rx == rz)
1067 // delete all
1068 // else
1069 // lw rz, [fp, #-24]
1070
1071 if ((mem_write_instr & kRtMask) == (lw_instr & kRtMask)) {
1072 pc_ -= 5 * kInstrSize;
1073 } else {
1074 pc_ -= 5 * kInstrSize;
1075 // Reinsert back the lw rz.
1076 emit(lw_instr);
1077 }
1078 if (FLAG_print_peephole_optimization) {
1079 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset());
1080 }
1081 } else {
1082 // Pattern: push & pop from/to different registers
1083 // with a fp+offset lw in between
1084 //
1085 // The following:
1086 // addiu sp, sp ,-4
1087 // sw rx, [sp, 0]
1088 // lw rz, [fp, #-24]
1089 // lw ry, [sp, 0]
1090 // addiu sp, sp, 4
1091 //
1092 // Becomes:
1093 // if(ry == rz)
1094 // mov ry, rx;
1095 // else if(rx != rz)
1096 // lw rz, [fp, #-24]
1097 // mov ry, rx
1098 // else if((ry != rz) || (rx == rz)) becomes:
1099 // mov ry, rx
1100 // lw rz, [fp, #-24]
1101
1102 Register reg_pushed, reg_popped;
1103 if ((mem_read_instr & kRtMask) == (lw_instr & kRtMask)) {
1104 reg_pushed = GetRt(mem_write_instr);
1105 reg_popped = GetRt(mem_read_instr);
1106 pc_ -= 5 * kInstrSize;
1107 or_(reg_popped, reg_pushed, zero_reg); // move instruction;
1108 } else if ((mem_write_instr & kRtMask)
1109 != (lw_instr & kRtMask)) {
1110 reg_pushed = GetRt(mem_write_instr);
1111 reg_popped = GetRt(mem_read_instr);
1112 pc_ -= 5 * kInstrSize;
1113 emit(lw_instr);
1114 or_(reg_popped, reg_pushed, zero_reg); // move instruction
1115 } else if (((mem_read_instr & kRtMask)
1116 != (lw_instr & kRtMask)) ||
1117 ((mem_write_instr & kRtMask)
1118 == (lw_instr & kRtMask)) ) {
1119 reg_pushed = GetRt(mem_write_instr);
1120 reg_popped = GetRt(mem_read_instr);
1121 pc_ -= 5 * kInstrSize;
1122 or_(reg_popped, reg_pushed, zero_reg); // move instruction
1123 emit(lw_instr);
1124 }
1125 if (FLAG_print_peephole_optimization) {
1126 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset());
1127 }
1128 }
1129 }
1130 }
1131 }
665 } 1132 }
666 1133
667 1134
668 void Assembler::addiu(Register rd, Register rs, int32_t j) {
669 GenInstrImmediate(ADDIU, rs, rd, j);
670 }
671
672
673 void Assembler::sub(Register rd, Register rs, Register rt) {
674 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUB);
675 }
676
677
678 void Assembler::subu(Register rd, Register rs, Register rt) { 1135 void Assembler::subu(Register rd, Register rs, Register rt) {
679 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); 1136 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
680 } 1137 }
681 1138
682 1139
683 void Assembler::mul(Register rd, Register rs, Register rt) { 1140 void Assembler::mul(Register rd, Register rs, Register rt) {
684 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); 1141 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
685 } 1142 }
686 1143
687 1144
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 GenInstrImmediate(XORI, rs, rt, j); 1193 GenInstrImmediate(XORI, rs, rt, j);
737 } 1194 }
738 1195
739 1196
740 void Assembler::nor(Register rd, Register rs, Register rt) { 1197 void Assembler::nor(Register rd, Register rs, Register rt) {
741 GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR); 1198 GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
742 } 1199 }
743 1200
744 1201
745 // Shifts. 1202 // Shifts.
746 void Assembler::sll(Register rd, Register rt, uint16_t sa) { 1203 void Assembler::sll(Register rd,
1204 Register rt,
1205 uint16_t sa,
1206 bool coming_from_nop) {
1207 // Don't allow nop instructions in the form sll zero_reg, zero_reg to be
1208 // generated using the sll instruction. They must be generated using
1209 // nop(int/NopMarkerTypes) or MarkCode(int/NopMarkerTypes) pseudo
1210 // instructions.
1211 ASSERT(coming_from_nop || !(rd.is(zero_reg) && rt.is(zero_reg)));
747 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL); 1212 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
748 } 1213 }
749 1214
750 1215
751 void Assembler::sllv(Register rd, Register rt, Register rs) { 1216 void Assembler::sllv(Register rd, Register rt, Register rs) {
752 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV); 1217 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
753 } 1218 }
754 1219
755 1220
756 void Assembler::srl(Register rd, Register rt, uint16_t sa) { 1221 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
757 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL); 1222 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
758 } 1223 }
759 1224
760 1225
761 void Assembler::srlv(Register rd, Register rt, Register rs) { 1226 void Assembler::srlv(Register rd, Register rt, Register rs) {
762 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV); 1227 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
763 } 1228 }
764 1229
765 1230
766 void Assembler::sra(Register rd, Register rt, uint16_t sa) { 1231 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
767 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA); 1232 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
768 } 1233 }
769 1234
770 1235
771 void Assembler::srav(Register rd, Register rt, Register rs) { 1236 void Assembler::srav(Register rd, Register rt, Register rs) {
772 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); 1237 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
773 } 1238 }
774 1239
775 1240
1241 void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
1242 ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa));
Søren Thygesen Gjesse 2011/03/23 23:38:42 Please change pattern if (mips32r2) { ... somet
Paul Lind 2011/03/26 18:39:17 Done.
1243 if (mips32r2) {
1244 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift)
1245 | (rd.code() << kRdShift) | (sa << kSaShift) | SRL;
1246 emit(instr);
1247 } else {
1248 // You should use this through MacroAssembler::Ror.
1249 ASSERT(mips32r2);
1250 }
1251 }
1252
1253
1254 void Assembler::rotrv(Register rd, Register rt, Register rs) {
1255 ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() );
1256 if (mips32r2) {
1257 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift)
1258 | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV;
1259 emit(instr);
1260 } else {
1261 // You should use this through MacroAssembler::Ror.
1262 ASSERT(mips32r2);
1263 }
1264 }
1265
1266
776 //------------Memory-instructions------------- 1267 //------------Memory-instructions-------------
777 1268
778 void Assembler::lb(Register rd, const MemOperand& rs) { 1269 void Assembler::lb(Register rd, const MemOperand& rs) {
779 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_); 1270 if (is_int16(rs.offset_)) {
1271 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
1272 } else { // Offset > 16 bits, use multiple instructions to load.
Søren Thygesen Gjesse 2011/03/23 23:38:42 Consider refactoring ASSERT(!rs.rm().is(at)); lui
Paul Lind 2011/03/26 18:39:17 Added helper function LoadRegPlusOffsetToAt()
1273 ASSERT(!rs.rm().is(at));
1274 lui(at, rs.offset_ >> 16);
Søren Thygesen Gjesse 2011/03/23 23:38:42 Constants for 16 and 0xffff?
Paul Lind 2011/03/26 18:39:17 Added (and corrected existing) constants in consta
1275 ori(at, at, rs.offset_ & 0xffff);
1276 addu(at, at, rs.rm());
1277 GenInstrImmediate(LB, at, rd, 0); // Equiv to lb(rd, MemOperand(at, 0));
1278 }
780 } 1279 }
781 1280
782 1281
783 void Assembler::lbu(Register rd, const MemOperand& rs) { 1282 void Assembler::lbu(Register rd, const MemOperand& rs) {
784 GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_); 1283 if (is_int16(rs.offset_)) {
1284 GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
1285 } else { // Offset > 16 bits, use multiple instructions to load.
1286 ASSERT(!rs.rm().is(at));
1287 lui(at, rs.offset_ >> 16);
1288 ori(at, at, rs.offset_ & 0xffff);
1289 addu(at, at, rs.rm());
1290 GenInstrImmediate(LBU, at, rd, 0); // Equiv to lbu(rd, MemOperand(at, 0));
1291 }
1292 }
1293
1294
1295 void Assembler::lh(Register rd, const MemOperand& rs) {
1296 if (is_int16(rs.offset_)) {
1297 GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
1298 } else { // Offset > 16 bits, use multiple instructions to load.
1299 ASSERT(!rs.rm().is(at));
1300 lui(at, rs.offset_ >> 16);
1301 ori(at, at, rs.offset_ & 0xffff);
1302 addu(at, at, rs.rm());
1303 GenInstrImmediate(LH, at, rd, 0); // Equiv to lh(rd, MemOperand(at, 0));
1304 }
1305 }
1306
1307
1308 void Assembler::lhu(Register rd, const MemOperand& rs) {
1309 if (is_int16(rs.offset_)) {
1310 GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
1311 } else { // Offset > 16 bits, use multiple instructions to load.
1312 ASSERT(!rs.rm().is(at));
1313 lui(at, rs.offset_ >> 16);
1314 ori(at, at, rs.offset_ & 0xffff);
1315 addu(at, at, rs.rm());
1316 GenInstrImmediate(LHU, at, rd, 0); // Equiv to lhu(rd, MemOperand(at, 0));
1317 }
785 } 1318 }
786 1319
787 1320
788 void Assembler::lw(Register rd, const MemOperand& rs) { 1321 void Assembler::lw(Register rd, const MemOperand& rs) {
789 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); 1322 if (is_int16(rs.offset_)) {
1323 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
1324 } else { // Offset > 16 bits, use multiple instructions to load.
1325 ASSERT(!rs.rm().is(at));
1326 lui(at, rs.offset_ >> 16);
1327 ori(at, at, rs.offset_ & 0xffff);
1328 addu(at, at, rs.rm());
1329 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0));
1330 }
1331
1332 if (can_peephole_optimize(2)) {
1333 Instr sw_instr = instr_at(pc_ - 2 * kInstrSize);
1334 Instr lw_instr = instr_at(pc_ - 1 * kInstrSize);
1335
1336 if ((IsSwRegFpOffset(sw_instr) &&
1337 IsLwRegFpOffset(lw_instr)) ||
1338 (IsSwRegFpNegOffset(sw_instr) &&
1339 IsLwRegFpNegOffset(lw_instr))) {
1340 if ((lw_instr & kLwSwInstrArgumentMask) ==
1341 (sw_instr & kLwSwInstrArgumentMask)) {
1342 // Pattern: Lw/sw same fp+offset, same register.
1343 //
1344 // The following:
1345 // sw rx, [fp, #-12]
1346 // lw rx, [fp, #-12]
1347 //
1348 // Becomes:
1349 // sw rx, [fp, #-12]
1350
1351 pc_ -= 1 * kInstrSize;
1352 if (FLAG_print_peephole_optimization) {
1353 PrintF("%x sw/lw (fp + same offset), same reg\n", pc_offset());
1354 }
1355 } else if ((lw_instr & kLwSwOffsetMask) ==
1356 (sw_instr & kLwSwOffsetMask)) {
1357 // Pattern: Lw/sw same fp+offset, different register.
1358 //
1359 // The following:
1360 // sw rx, [fp, #-12]
1361 // lw ry, [fp, #-12]
1362 //
1363 // Becomes:
1364 // sw rx, [fp, #-12]
1365 // mov ry, rx
1366
1367 Register reg_stored, reg_loaded;
1368 reg_stored = GetRt(sw_instr);
1369 reg_loaded = GetRt(lw_instr);
1370 pc_ -= 1 * kInstrSize;
1371 // Insert a mov instruction, which is better than lw.
1372 or_(reg_loaded, reg_stored, zero_reg); // move instruction.
1373 if (FLAG_print_peephole_optimization) {
1374 PrintF("%x sw/lw (fp + same offset), diff reg \n", pc_offset());
1375 }
1376 }
1377 }
1378 }
1379 }
1380
1381
1382 void Assembler::lwl(Register rd, const MemOperand& rs) {
1383 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
1384 }
1385
1386
1387 void Assembler::lwr(Register rd, const MemOperand& rs) {
1388 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
790 } 1389 }
791 1390
792 1391
793 void Assembler::sb(Register rd, const MemOperand& rs) { 1392 void Assembler::sb(Register rd, const MemOperand& rs) {
794 GenInstrImmediate(SB, rs.rm(), rd, rs.offset_); 1393 if (is_int16(rs.offset_)) {
1394 GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
1395 } else { // Offset > 16 bits, use multiple instructions to store.
1396 ASSERT(!rs.rm().is(at));
1397 lui(at, rs.offset_ >> 16);
1398 ori(at, at, rs.offset_ & 0xffff);
1399 addu(at, at, rs.rm());
1400 GenInstrImmediate(SB, at, rd, 0); // Equiv to sb(rd, MemOperand(at, 0));
1401 }
1402 }
1403
1404
1405 void Assembler::sh(Register rd, const MemOperand& rs) {
1406 if (is_int16(rs.offset_)) {
1407 GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
1408 } else { // Offset > 16 bits, use multiple instructions to store.
1409 ASSERT(!rs.rm().is(at));
1410 lui(at, rs.offset_ >> 16);
1411 ori(at, at, rs.offset_ & 0xffff);
1412 addu(at, at, rs.rm());
1413 GenInstrImmediate(SH, at, rd, 0); // Equiv to sh(rd, MemOperand(at, 0));
1414 }
795 } 1415 }
796 1416
797 1417
798 void Assembler::sw(Register rd, const MemOperand& rs) { 1418 void Assembler::sw(Register rd, const MemOperand& rs) {
799 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); 1419 if (is_int16(rs.offset_)) {
800 } 1420 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
801 1421 } else { // Offset > 16 bits, use multiple instructions to store.
802 1422 ASSERT(!rs.rm().is(at));
1423 lui(at, rs.offset_ >> 16);
1424 ori(at, at, rs.offset_ & 0xffff);
1425 addu(at, at, rs.rm());
1426 GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0));
1427 }
1428
1429 // Eliminate pattern: pop(), push(r)
1430 // addiu sp, sp, Operand(kPointerSize);
1431 // addiu sp, sp, Operand(-kPointerSize);
1432 // -> sw r, MemOpernad(sp, 0);
1433 if (can_peephole_optimize(3) &&
1434 // Pattern.
1435 instr_at(pc_ - 1 * kInstrSize) ==
1436 (kPushRegPattern | (rd.code() << kRtShift)) &&
1437 instr_at(pc_ - 2 * kInstrSize) == kPushInstruction &&
1438 instr_at(pc_ - 3 * kInstrSize) == kPopInstruction) {
1439 pc_ -= 3 * kInstrSize;
1440 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
1441 if (FLAG_print_peephole_optimization) {
1442 PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
1443 }
1444 }
1445 }
1446
1447
1448 void Assembler::swl(Register rd, const MemOperand& rs) {
1449 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
1450 }
1451
1452
1453 void Assembler::swr(Register rd, const MemOperand& rs) {
1454 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
1455 }
1456
1457
803 void Assembler::lui(Register rd, int32_t j) { 1458 void Assembler::lui(Register rd, int32_t j) {
804 GenInstrImmediate(LUI, zero_reg, rd, j); 1459 GenInstrImmediate(LUI, zero_reg, rd, j);
805 } 1460 }
806 1461
807 1462
808 //-------------Misc-instructions-------------- 1463 //-------------Misc-instructions--------------
809 1464
810 // Break / Trap instructions. 1465 // Break / Trap instructions.
811 void Assembler::break_(uint32_t code) { 1466 void Assembler::break_(uint32_t code) {
812 ASSERT((code & ~0xfffff) == 0); 1467 ASSERT((code & ~0xfffff) == 0);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 void Assembler::slti(Register rt, Register rs, int32_t j) { 1544 void Assembler::slti(Register rt, Register rs, int32_t j) {
890 GenInstrImmediate(SLTI, rs, rt, j); 1545 GenInstrImmediate(SLTI, rs, rt, j);
891 } 1546 }
892 1547
893 1548
894 void Assembler::sltiu(Register rt, Register rs, int32_t j) { 1549 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
895 GenInstrImmediate(SLTIU, rs, rt, j); 1550 GenInstrImmediate(SLTIU, rs, rt, j);
896 } 1551 }
897 1552
898 1553
1554 // Conditional move.
1555 void Assembler::movz(Register rd, Register rs, Register rt) {
1556 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
1557 }
1558
1559
1560 void Assembler::movn(Register rd, Register rs, Register rt) {
1561 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
1562 }
1563
1564
1565 void Assembler::movt(Register rd, Register rs, uint16_t cc) {
1566 Register rt;
1567 rt.code_ = (cc & 0x0003)<<2 | 1;
Søren Thygesen Gjesse 2011/03/23 23:38:42 Spaces around << (more below).
Paul Lind 2011/03/26 18:39:17 Done.
1568 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
1569 }
1570
1571
1572 void Assembler::movf(Register rd, Register rs, uint16_t cc) {
1573 Register rt;
1574 rt.code_ = (cc & 0x0003)<<2 | 0;
1575 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
1576 }
1577
1578
1579 // Bit twiddling.
1580 void Assembler::clz(Register rd, Register rs) {
1581 // Clz instr requires same GPR number in 'rd' and 'rt' fields.
1582 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
1583 }
1584
1585
1586 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
1587 if (mips32r2) {
1588 // Ins instr has 'rt' field as dest, and two uint5: msb, lsb
Søren Thygesen Gjesse 2011/03/23 23:38:42 End comment with full stop.
Paul Lind 2011/03/26 18:39:17 Done.
1589 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
1590 } else {
1591 // This instruction should be called through MacroAssembler::Ins.
1592 ASSERT(mips32r2);
1593 }
1594 }
1595
1596
1597 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
1598 if (mips32r2) {
1599 // Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
1600 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
1601 } else {
1602 // This instruction should be called through MacroAssembler::Ext.
1603 ASSERT(mips32r2);
1604 }
1605 }
1606
1607
899 //--------Coprocessor-instructions---------------- 1608 //--------Coprocessor-instructions----------------
900 1609
901 // Load, store, move. 1610 // Load, store, move.
902 void Assembler::lwc1(FPURegister fd, const MemOperand& src) { 1611 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
903 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); 1612 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
904 } 1613 }
905 1614
906 1615
907 void Assembler::ldc1(FPURegister fd, const MemOperand& src) { 1616 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
908 GenInstrImmediate(LDC1, src.rm(), fd, src.offset_); 1617 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
1618 // load to two 32-bit loads.
1619 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
1620 FPURegister nextfpreg;
1621 nextfpreg.setcode(fd.code() + 1);
1622 GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + 4);
909 } 1623 }
910 1624
911 1625
912 void Assembler::swc1(FPURegister fd, const MemOperand& src) { 1626 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
913 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); 1627 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
914 } 1628 }
915 1629
916 1630
917 void Assembler::sdc1(FPURegister fd, const MemOperand& src) { 1631 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
918 GenInstrImmediate(SDC1, src.rm(), fd, src.offset_); 1632 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
1633 // store to two 32-bit stores.
1634 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
1635 FPURegister nextfpreg;
1636 nextfpreg.setcode(fd.code() + 1);
1637 GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + 4);
919 } 1638 }
920 1639
921 1640
922 void Assembler::mtc1(FPURegister fs, Register rt) { 1641 void Assembler::mtc1(Register rt, FPURegister fs) {
923 GenInstrRegister(COP1, MTC1, rt, fs, f0); 1642 GenInstrRegister(COP1, MTC1, rt, fs, f0);
924 } 1643 }
925 1644
926 1645
927 void Assembler::mthc1(FPURegister fs, Register rt) { 1646 void Assembler::mfc1(Register rt, FPURegister fs) {
928 GenInstrRegister(COP1, MTHC1, rt, fs, f0);
929 }
930
931
932 void Assembler::mfc1(FPURegister fs, Register rt) {
933 GenInstrRegister(COP1, MFC1, rt, fs, f0); 1647 GenInstrRegister(COP1, MFC1, rt, fs, f0);
934 } 1648 }
935 1649
936 1650
937 void Assembler::mfhc1(FPURegister fs, Register rt) { 1651 void Assembler::ctc1(Register rt, FPUControlRegister fs) {
938 GenInstrRegister(COP1, MFHC1, rt, fs, f0); 1652 GenInstrRegister(COP1, CTC1, rt, fs);
939 } 1653 }
940 1654
941 1655
1656 void Assembler::cfc1(Register rt, FPUControlRegister fs) {
1657 GenInstrRegister(COP1, CFC1, rt, fs);
1658 }
1659
1660
1661 // Arithmetic.
1662
1663 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1664 GenInstrRegister(COP1, D, ft, fs, fd, ADD_D);
1665 }
1666
1667
1668 void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1669 GenInstrRegister(COP1, D, ft, fs, fd, SUB_D);
1670 }
1671
1672
1673 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1674 GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
1675 }
1676
1677
1678 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
1679 GenInstrRegister(COP1, D, ft, fs, fd, DIV_D);
1680 }
1681
1682
1683 void Assembler::abs_d(FPURegister fd, FPURegister fs) {
1684 GenInstrRegister(COP1, D, f0, fs, fd, ABS_D);
1685 }
1686
1687
1688 void Assembler::mov_d(FPURegister fd, FPURegister fs) {
1689 GenInstrRegister(COP1, D, f0, fs, fd, MOV_D);
1690 }
1691
1692
1693 void Assembler::neg_d(FPURegister fd, FPURegister fs) {
1694 GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
1695 }
1696
1697
1698 void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
1699 GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D);
1700 }
1701
1702
942 // Conversions. 1703 // Conversions.
943 1704
944 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) { 1705 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
945 GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S); 1706 GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
946 } 1707 }
947 1708
948 1709
949 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) { 1710 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
950 GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D); 1711 GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
951 } 1712 }
952 1713
953 1714
1715 void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
1716 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
1717 }
1718
1719
1720 void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
1721 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D);
1722 }
1723
1724
1725 void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
1726 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
1727 }
1728
1729
1730 void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
1731 GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D);
1732 }
1733
1734
1735 void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
1736 GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
1737 }
1738
1739
1740 void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
1741 GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D);
1742 }
1743
1744
1745 void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
1746 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
1747 }
1748
1749
1750 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
1751 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D);
1752 }
1753
1754
954 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { 1755 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
955 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); 1756 if (mips32r2) {
1757 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
1758 } else {
1759 ASSERT(mips32r2);
1760 }
956 } 1761 }
957 1762
958 1763
959 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { 1764 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
960 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); 1765 if (mips32r2) {
1766 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
1767 } else {
1768 ASSERT(mips32r2);
1769 }
961 } 1770 }
962 1771
963 1772
1773 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
1774 if (mips32r2) {
1775 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
1776 } else {
1777 ASSERT(mips32r2);
1778 }
1779 }
1780
1781
1782 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
1783 if (mips32r2) {
1784 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D);
1785 } else {
1786 ASSERT(mips32r2);
1787 }
1788 }
1789
1790
1791 void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
1792 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
1793 }
1794
1795
1796 void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
1797 GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D);
1798 }
1799
1800
1801 void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
1802 GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
1803 }
1804
1805
1806 void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
1807 GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D);
1808 }
1809
1810
1811 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
1812 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
1813 }
1814
1815
1816 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
1817 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D);
1818 }
1819
1820
964 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { 1821 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
965 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); 1822 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
966 } 1823 }
967 1824
968 1825
969 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { 1826 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
970 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); 1827 if (mips32r2) {
1828 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
1829 } else {
1830 ASSERT(mips32r2);
1831 }
971 } 1832 }
972 1833
973 1834
974 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { 1835 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
975 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); 1836 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
976 } 1837 }
977 1838
978 1839
979 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { 1840 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
980 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); 1841 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
981 } 1842 }
982 1843
983 1844
984 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { 1845 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
985 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); 1846 if (mips32r2) {
1847 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
1848 } else {
1849 ASSERT(mips32r2);
1850 }
986 } 1851 }
987 1852
988 1853
989 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { 1854 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
990 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); 1855 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
991 } 1856 }
992 1857
993 1858
994 // Conditions. 1859 // Conditions.
995 void Assembler::c(FPUCondition cond, SecondaryField fmt, 1860 void Assembler::c(FPUCondition cond, SecondaryField fmt,
996 FPURegister ft, FPURegister fs, uint16_t cc) { 1861 FPURegister fs, FPURegister ft, uint16_t cc) {
997 ASSERT(is_uint3(cc)); 1862 ASSERT(is_uint3(cc));
998 ASSERT((fmt & ~(31 << kRsShift)) == 0); 1863 ASSERT((fmt & ~(31 << kRsShift)) == 0);
999 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift 1864 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
1000 | cc << 8 | 3 << 4 | cond; 1865 | cc << 8 | 3 << 4 | cond;
1001 emit(instr); 1866 emit(instr);
1002 } 1867 }
1003 1868
1004 1869
1870 void Assembler::fcmp(FPURegister src1, const double src2,
1871 FPUCondition cond) {
1872 ASSERT(isolate()->cpu_features()->IsSupported(FPU));
1873 ASSERT(src2 == 0.0);
1874 mtc1(zero_reg, f14);
1875 cvt_d_w(f14, f14);
1876 c(cond, D, src1, f14, 0);
1877 }
1878
1879
1005 void Assembler::bc1f(int16_t offset, uint16_t cc) { 1880 void Assembler::bc1f(int16_t offset, uint16_t cc) {
1006 ASSERT(is_uint3(cc)); 1881 ASSERT(is_uint3(cc));
1007 Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask); 1882 Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
1008 emit(instr); 1883 emit(instr);
1009 } 1884 }
1010 1885
1011 1886
1012 void Assembler::bc1t(int16_t offset, uint16_t cc) { 1887 void Assembler::bc1t(int16_t offset, uint16_t cc) {
1013 ASSERT(is_uint3(cc)); 1888 ASSERT(is_uint3(cc));
1014 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 1889 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
1015 emit(instr); 1890 emit(instr);
1016 } 1891 }
1017 1892
1018 1893
1019 // Debugging. 1894 // Debugging.
1020 void Assembler::RecordJSReturn() { 1895 void Assembler::RecordJSReturn() {
1021 WriteRecordedPositions(); 1896 positions_recorder()->WriteRecordedPositions();
1022 CheckBuffer(); 1897 CheckBuffer();
1023 RecordRelocInfo(RelocInfo::JS_RETURN); 1898 RecordRelocInfo(RelocInfo::JS_RETURN);
1024 } 1899 }
1025 1900
1026 1901
1902 void Assembler::RecordDebugBreakSlot() {
1903 positions_recorder()->WriteRecordedPositions();
1904 CheckBuffer();
1905 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
1906 }
1907
1908
1027 void Assembler::RecordComment(const char* msg) { 1909 void Assembler::RecordComment(const char* msg) {
1028 if (FLAG_debug_code) { 1910 if (FLAG_code_comments) {
1029 CheckBuffer(); 1911 CheckBuffer();
1030 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 1912 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1031 } 1913 }
1032 } 1914 }
1033 1915
1034 1916
1035 void Assembler::RecordPosition(int pos) {
1036 if (pos == RelocInfo::kNoPosition) return;
1037 ASSERT(pos >= 0);
1038 current_position_ = pos;
1039 }
1040
1041
1042 void Assembler::RecordStatementPosition(int pos) {
1043 if (pos == RelocInfo::kNoPosition) return;
1044 ASSERT(pos >= 0);
1045 current_statement_position_ = pos;
1046 }
1047
1048
1049 bool Assembler::WriteRecordedPositions() {
1050 bool written = false;
1051
1052 // Write the statement position if it is different from what was written last
1053 // time.
1054 if (current_statement_position_ != written_statement_position_) {
1055 CheckBuffer();
1056 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
1057 written_statement_position_ = current_statement_position_;
1058 written = true;
1059 }
1060
1061 // Write the position if it is different from what was written last time and
1062 // also different from the written statement position.
1063 if (current_position_ != written_position_ &&
1064 current_position_ != written_statement_position_) {
1065 CheckBuffer();
1066 RecordRelocInfo(RelocInfo::POSITION, current_position_);
1067 written_position_ = current_position_;
1068 written = true;
1069 }
1070
1071 // Return whether something was written.
1072 return written;
1073 }
1074
1075
1076 void Assembler::GrowBuffer() { 1917 void Assembler::GrowBuffer() {
1077 if (!own_buffer_) FATAL("external code buffer is too small"); 1918 if (!own_buffer_) FATAL("external code buffer is too small");
1078 1919
1079 // Compute new buffer size. 1920 // Compute new buffer size.
1080 CodeDesc desc; // the new buffer 1921 CodeDesc desc; // the new buffer
1081 if (buffer_size_ < 4*KB) { 1922 if (buffer_size_ < 4*KB) {
1082 desc.buffer_size = 4*KB; 1923 desc.buffer_size = 4*KB;
1083 } else if (buffer_size_ < 1*MB) { 1924 } else if (buffer_size_ < 1*MB) {
1084 desc.buffer_size = 2*buffer_size_; 1925 desc.buffer_size = 2*buffer_size_;
1085 } else { 1926 } else {
(...skipping 24 matching lines...) Expand all
1110 1951
1111 1952
1112 // On ia32 and ARM pc relative addressing is used, and we thus need to apply a 1953 // On ia32 and ARM pc relative addressing is used, and we thus need to apply a
1113 // shift by pc_delta. But on MIPS the target address it directly loaded, so 1954 // shift by pc_delta. But on MIPS the target address it directly loaded, so
1114 // we do not need to relocate here. 1955 // we do not need to relocate here.
1115 1956
1116 ASSERT(!overflow()); 1957 ASSERT(!overflow());
1117 } 1958 }
1118 1959
1119 1960
1961 void Assembler::db(uint8_t data) {
1962 CheckBuffer();
1963 *reinterpret_cast<uint8_t*>(pc_) = data;
1964 pc_ += sizeof(uint8_t);
1965 }
1966
1967
1968 void Assembler::dd(uint32_t data) {
1969 CheckBuffer();
1970 *reinterpret_cast<uint32_t*>(pc_) = data;
1971 pc_ += sizeof(uint32_t);
1972 }
1973
1974
1120 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 1975 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
1121 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants 1976 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants
1122 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { 1977 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
1123 // Adjust code for new modes. 1978 // Adjust code for new modes.
1124 ASSERT(RelocInfo::IsJSReturn(rmode) 1979 ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
1980 || RelocInfo::IsJSReturn(rmode)
1125 || RelocInfo::IsComment(rmode) 1981 || RelocInfo::IsComment(rmode)
1126 || RelocInfo::IsPosition(rmode)); 1982 || RelocInfo::IsPosition(rmode));
1127 // These modes do not need an entry in the constant pool. 1983 // These modes do not need an entry in the constant pool.
1128 } 1984 }
1129 if (rinfo.rmode() != RelocInfo::NONE) { 1985 if (rinfo.rmode() != RelocInfo::NONE) {
1130 // Don't record external references unless the heap will be serialized. 1986 // Don't record external references unless the heap will be serialized.
1131 if (rmode == RelocInfo::EXTERNAL_REFERENCE && 1987 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
1132 !Serializer::enabled() && 1988 !Serializer::enabled() &&
1133 !FLAG_debug_code) { 1989 !FLAG_debug_code) {
1134 return; 1990 return;
1135 } 1991 }
1136 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 1992 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
1137 reloc_info_writer.Write(&rinfo); 1993 reloc_info_writer.Write(&rinfo);
1138 } 1994 }
1139 } 1995 }
1140 1996
1141 1997
1998 void Assembler::BlockTrampolinePoolFor(int instructions) {
1999 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
2000 }
2001
2002
2003 void Assembler::CheckTrampolinePool(bool force_emit) {
2004 // Calculate the offset of the next check.
2005 next_buffer_check_ = pc_offset() + kCheckConstInterval;
2006
2007 int dist = pc_offset() - last_trampoline_pool_end_;
2008
2009 if (dist <= kMaxDistBetweenPools && !force_emit) {
2010 return;
2011 }
2012
2013 // Some small sequences of instructions must not be broken up by the
2014 // insertion of a trampoline pool; such sequences are protected by setting
2015 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
2016 // which are both checked here. Also, recursive calls to CheckTrampolinePool
2017 // are blocked by trampoline_pool_blocked_nesting_.
2018 if ((trampoline_pool_blocked_nesting_ > 0) ||
2019 (pc_offset() < no_trampoline_pool_before_)) {
2020 // Emission is currently blocked; make sure we try again as soon as
2021 // possible.
2022 if (trampoline_pool_blocked_nesting_ > 0) {
2023 next_buffer_check_ = pc_offset() + kInstrSize;
2024 } else {
2025 next_buffer_check_ = no_trampoline_pool_before_;
2026 }
2027 return;
2028 }
2029
2030 // First we emit jump (2 instructions), then we emit trampoline pool.
2031 { BlockTrampolinePoolScope block_trampoline_pool(this);
2032 Label after_pool;
2033 b(&after_pool);
2034 nop();
2035
2036 int pool_start = pc_offset();
2037 for (int i = 0; i < kSlotsPerTrampoline; i++) {
2038 b(&after_pool);
2039 nop();
2040 }
2041 for (int i = 0; i < kLabelsPerTrampoline; i++) {
2042 emit(0);
2043 }
2044 last_trampoline_pool_end_ = pc_offset() - kInstrSize;
2045 bind(&after_pool);
2046 trampolines_.Add(Trampoline(pool_start,
2047 kSlotsPerTrampoline,
2048 kLabelsPerTrampoline));
2049
2050 // Since a trampoline pool was just emitted,
2051 // move the check offset forward by the standard interval.
2052 next_buffer_check_ = last_trampoline_pool_end_ + kMaxDistBetweenPools;
2053 }
2054 return;
2055 }
2056
2057
1142 Address Assembler::target_address_at(Address pc) { 2058 Address Assembler::target_address_at(Address pc) {
1143 Instr instr1 = instr_at(pc); 2059 Instr instr1 = instr_at(pc);
1144 Instr instr2 = instr_at(pc + kInstrSize); 2060 Instr instr2 = instr_at(pc + kInstrSize);
1145 // Check we have 2 instructions generated by li. 2061 // Check we have 2 instructions generated by li.
1146 ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) || 2062 ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
1147 ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI || 2063 ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI ||
1148 (instr2 & kOpcodeMask) == ORI || 2064 (instr2 & kOpcodeMask) == ORI ||
1149 (instr2 & kOpcodeMask) == LUI))); 2065 (instr2 & kOpcodeMask) == LUI)));
1150 // Interpret these 2 instructions. 2066 // Interpret these 2 instructions.
1151 if (instr1 == nopInstr) { 2067 if (instr1 == nopInstr) {
(...skipping 17 matching lines...) Expand all
1169 2085
1170 2086
1171 void Assembler::set_target_address_at(Address pc, Address target) { 2087 void Assembler::set_target_address_at(Address pc, Address target) {
1172 // On MIPS we need to patch the code to generate. 2088 // On MIPS we need to patch the code to generate.
1173 2089
1174 // First check we have a li. 2090 // First check we have a li.
1175 Instr instr2 = instr_at(pc + kInstrSize); 2091 Instr instr2 = instr_at(pc + kInstrSize);
1176 #ifdef DEBUG 2092 #ifdef DEBUG
1177 Instr instr1 = instr_at(pc); 2093 Instr instr1 = instr_at(pc);
1178 2094
1179 // Check we have indeed the result from a li with MustUseAt true. 2095 // Check we have indeed the result from a li with MustUseReg true.
1180 CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) || 2096 CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
1181 ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU || 2097 ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU ||
1182 (instr2 & kOpcodeMask)== ORI || 2098 (instr2 & kOpcodeMask)== ORI ||
1183 (instr2 & kOpcodeMask)== LUI))); 2099 (instr2 & kOpcodeMask)== LUI)));
1184 #endif 2100 #endif
1185 2101
1186 2102
1187 uint32_t rt_code = (instr2 & kRtFieldMask); 2103 uint32_t rt_code = (instr2 & kRtFieldMask);
1188 uint32_t* p = reinterpret_cast<uint32_t*>(pc); 2104 uint32_t* p = reinterpret_cast<uint32_t*>(pc);
1189 uint32_t itarget = reinterpret_cast<uint32_t>(target); 2105 uint32_t itarget = reinterpret_cast<uint32_t>(target);
1190 2106
1191 if (is_int16(itarget)) { 2107 if (is_int16(itarget)) {
1192 // nop 2108 // nop.
1193 // addiu rt zero_reg j 2109 // addiu rt zero_reg j.
1194 *p = nopInstr; 2110 *p = nopInstr;
1195 *(p+1) = ADDIU | rt_code | (itarget & LOMask); 2111 *(p+1) = ADDIU | rt_code | (itarget & LOMask);
1196 } else if (!(itarget & HIMask)) { 2112 } else if (!(itarget & HIMask)) {
1197 // nop 2113 // nop.
1198 // ori rt zero_reg j 2114 // ori rt zero_reg j.
1199 *p = nopInstr; 2115 *p = nopInstr;
1200 *(p+1) = ORI | rt_code | (itarget & LOMask); 2116 *(p+1) = ORI | rt_code | (itarget & LOMask);
1201 } else if (!(itarget & LOMask)) { 2117 } else if (!(itarget & LOMask)) {
1202 // nop 2118 // nop.
1203 // lui rt (HIMask & itarget)>>16 2119 // lui rt (HIMask & itarget)>>16.
1204 *p = nopInstr; 2120 *p = nopInstr;
1205 *(p+1) = LUI | rt_code | ((itarget & HIMask)>>16); 2121 *(p+1) = LUI | rt_code | ((itarget & HIMask)>>16);
1206 } else { 2122 } else {
1207 // lui rt (HIMask & itarget)>>16 2123 // lui rt (HIMask & itarget)>>16.
1208 // ori rt rt, (LOMask & itarget) 2124 // ori rt rt, (LOMask & itarget).
1209 *p = LUI | rt_code | ((itarget & HIMask)>>16); 2125 *p = LUI | rt_code | ((itarget & HIMask)>>16);
1210 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & LOMask); 2126 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & LOMask);
1211 } 2127 }
1212 2128
1213 CPU::FlushICache(pc, 2 * sizeof(int32_t)); 2129 CPU::FlushICache(pc, 2 * sizeof(int32_t));
1214 } 2130 }
1215 2131
1216 2132
1217 } } // namespace v8::internal 2133 } } // namespace v8::internal
1218 2134
1219 #endif // V8_TARGET_ARCH_MIPS 2135 #endif // V8_TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698