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

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

Powered by Google App Engine
This is Rietveld 408576698