• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2010 the V8 project authors. All rights reserved.
34 
35 
36 #include "v8.h"
37 #include "mips/assembler-mips-inl.h"
38 #include "serialize.h"
39 
40 
41 namespace v8 {
42 namespace internal {
43 
44 
45 
46 const Register no_reg = { -1 };
47 
48 const Register zero_reg = { 0 };
49 const Register at = { 1 };
50 const Register v0 = { 2 };
51 const Register v1 = { 3 };
52 const Register a0 = { 4 };
53 const Register a1 = { 5 };
54 const Register a2 = { 6 };
55 const Register a3 = { 7 };
56 const Register t0 = { 8 };
57 const Register t1 = { 9 };
58 const Register t2 = { 10 };
59 const Register t3 = { 11 };
60 const Register t4 = { 12 };
61 const Register t5 = { 13 };
62 const Register t6 = { 14 };
63 const Register t7 = { 15 };
64 const Register s0 = { 16 };
65 const Register s1 = { 17 };
66 const Register s2 = { 18 };
67 const Register s3 = { 19 };
68 const Register s4 = { 20 };
69 const Register s5 = { 21 };
70 const Register s6 = { 22 };
71 const Register s7 = { 23 };
72 const Register t8 = { 24 };
73 const Register t9 = { 25 };
74 const Register k0 = { 26 };
75 const Register k1 = { 27 };
76 const Register gp = { 28 };
77 const Register sp = { 29 };
78 const Register s8_fp = { 30 };
79 const Register ra = { 31 };
80 
81 
82 const FPURegister no_creg = { -1 };
83 
84 const FPURegister f0 = { 0 };
85 const FPURegister f1 = { 1 };
86 const FPURegister f2 = { 2 };
87 const FPURegister f3 = { 3 };
88 const FPURegister f4 = { 4 };
89 const FPURegister f5 = { 5 };
90 const FPURegister f6 = { 6 };
91 const FPURegister f7 = { 7 };
92 const FPURegister f8 = { 8 };
93 const FPURegister f9 = { 9 };
94 const FPURegister f10 = { 10 };
95 const FPURegister f11 = { 11 };
96 const FPURegister f12 = { 12 };
97 const FPURegister f13 = { 13 };
98 const FPURegister f14 = { 14 };
99 const FPURegister f15 = { 15 };
100 const FPURegister f16 = { 16 };
101 const FPURegister f17 = { 17 };
102 const FPURegister f18 = { 18 };
103 const FPURegister f19 = { 19 };
104 const FPURegister f20 = { 20 };
105 const FPURegister f21 = { 21 };
106 const FPURegister f22 = { 22 };
107 const FPURegister f23 = { 23 };
108 const FPURegister f24 = { 24 };
109 const FPURegister f25 = { 25 };
110 const FPURegister f26 = { 26 };
111 const FPURegister f27 = { 27 };
112 const FPURegister f28 = { 28 };
113 const FPURegister f29 = { 29 };
114 const FPURegister f30 = { 30 };
115 const FPURegister f31 = { 31 };
116 
ToNumber(Register reg)117 int ToNumber(Register reg) {
118   ASSERT(reg.is_valid());
119   const int kNumbers[] = {
120     0,    // zero_reg
121     1,    // at
122     2,    // v0
123     3,    // v1
124     4,    // a0
125     5,    // a1
126     6,    // a2
127     7,    // a3
128     8,    // t0
129     9,    // t1
130     10,   // t2
131     11,   // t3
132     12,   // t4
133     13,   // t5
134     14,   // t6
135     15,   // t7
136     16,   // s0
137     17,   // s1
138     18,   // s2
139     19,   // s3
140     20,   // s4
141     21,   // s5
142     22,   // s6
143     23,   // s7
144     24,   // t8
145     25,   // t9
146     26,   // k0
147     27,   // k1
148     28,   // gp
149     29,   // sp
150     30,   // s8_fp
151     31,   // ra
152   };
153   return kNumbers[reg.code()];
154 }
155 
ToRegister(int num)156 Register ToRegister(int num) {
157   ASSERT(num >= 0 && num < kNumRegisters);
158   const Register kRegisters[] = {
159     zero_reg,
160     at,
161     v0, v1,
162     a0, a1, a2, a3,
163     t0, t1, t2, t3, t4, t5, t6, t7,
164     s0, s1, s2, s3, s4, s5, s6, s7,
165     t8, t9,
166     k0, k1,
167     gp,
168     sp,
169     s8_fp,
170     ra
171   };
172   return kRegisters[num];
173 }
174 
175 
176 // -----------------------------------------------------------------------------
177 // Implementation of RelocInfo.
178 
179 const int RelocInfo::kApplyMask = 0;
180 
181 // Patch the code at the current address with the supplied instructions.
PatchCode(byte * instructions,int instruction_count)182 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
183   Instr* pc = reinterpret_cast<Instr*>(pc_);
184   Instr* instr = reinterpret_cast<Instr*>(instructions);
185   for (int i = 0; i < instruction_count; i++) {
186     *(pc + i) = *(instr + i);
187   }
188 
189   // Indicate that code has changed.
190   CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
191 }
192 
193 
194 // Patch the code at the current PC with a call to the target address.
195 // Additional guard instructions can be added if required.
PatchCodeWithCall(Address target,int guard_bytes)196 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
197   // Patch the code at the current address with a call to the target.
198   UNIMPLEMENTED_MIPS();
199 }
200 
201 
202 // -----------------------------------------------------------------------------
203 // Implementation of Operand and MemOperand.
204 // See assembler-mips-inl.h for inlined constructors.
205 
Operand(Handle<Object> handle)206 Operand::Operand(Handle<Object> handle) {
207   rm_ = no_reg;
208   // Verify all Objects referred by code are NOT in new space.
209   Object* obj = *handle;
210   ASSERT(!Heap::InNewSpace(obj));
211   if (obj->IsHeapObject()) {
212     imm32_ = reinterpret_cast<intptr_t>(handle.location());
213     rmode_ = RelocInfo::EMBEDDED_OBJECT;
214   } else {
215     // No relocation needed.
216     imm32_ = reinterpret_cast<intptr_t>(obj);
217     rmode_ = RelocInfo::NONE;
218   }
219 }
220 
MemOperand(Register rm,int16_t offset)221 MemOperand::MemOperand(Register rm, int16_t offset) : Operand(rm) {
222   offset_ = offset;
223 }
224 
225 
226 // -----------------------------------------------------------------------------
227 // Implementation of Assembler.
228 
229 static const int kMinimalBufferSize = 4*KB;
230 static byte* spare_buffer_ = NULL;
231 
Assembler(void * buffer,int buffer_size)232 Assembler::Assembler(void* buffer, int buffer_size) {
233   if (buffer == NULL) {
234     // Do our own buffer management.
235     if (buffer_size <= kMinimalBufferSize) {
236       buffer_size = kMinimalBufferSize;
237 
238       if (spare_buffer_ != NULL) {
239         buffer = spare_buffer_;
240         spare_buffer_ = NULL;
241       }
242     }
243     if (buffer == NULL) {
244       buffer_ = NewArray<byte>(buffer_size);
245     } else {
246       buffer_ = static_cast<byte*>(buffer);
247     }
248     buffer_size_ = buffer_size;
249     own_buffer_ = true;
250 
251   } else {
252     // Use externally provided buffer instead.
253     ASSERT(buffer_size > 0);
254     buffer_ = static_cast<byte*>(buffer);
255     buffer_size_ = buffer_size;
256     own_buffer_ = false;
257   }
258 
259   // Setup buffer pointers.
260   ASSERT(buffer_ != NULL);
261   pc_ = buffer_;
262   reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
263   current_statement_position_ = RelocInfo::kNoPosition;
264   current_position_ = RelocInfo::kNoPosition;
265   written_statement_position_ = current_statement_position_;
266   written_position_ = current_position_;
267 }
268 
269 
~Assembler()270 Assembler::~Assembler() {
271   if (own_buffer_) {
272     if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
273       spare_buffer_ = buffer_;
274     } else {
275       DeleteArray(buffer_);
276     }
277   }
278 }
279 
280 
GetCode(CodeDesc * desc)281 void Assembler::GetCode(CodeDesc* desc) {
282   ASSERT(pc_ <= reloc_info_writer.pos());  // no overlap
283   // Setup code descriptor.
284   desc->buffer = buffer_;
285   desc->buffer_size = buffer_size_;
286   desc->instr_size = pc_offset();
287   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
288 }
289 
290 
291 // Labels refer to positions in the (to be) generated code.
292 // There are bound, linked, and unused labels.
293 //
294 // Bound labels refer to known positions in the already
295 // generated code. pos() is the position the label refers to.
296 //
297 // Linked labels refer to unknown positions in the code
298 // to be generated; pos() is the position of the last
299 // instruction using the label.
300 
301 
302 // The link chain is terminated by a negative code position (must be aligned).
303 const int kEndOfChain = -4;
304 
is_branch(Instr instr)305 bool Assembler::is_branch(Instr instr) {
306   uint32_t opcode   = ((instr & kOpcodeMask));
307   uint32_t rt_field = ((instr & kRtFieldMask));
308   uint32_t rs_field = ((instr & kRsFieldMask));
309   // Checks if the instruction is a branch.
310   return opcode == BEQ ||
311       opcode == BNE ||
312       opcode == BLEZ ||
313       opcode == BGTZ ||
314       opcode == BEQL ||
315       opcode == BNEL ||
316       opcode == BLEZL ||
317       opcode == BGTZL||
318       (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
319                             rt_field == BLTZAL || rt_field == BGEZAL)) ||
320       (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
321 }
322 
323 
target_at(int32_t pos)324 int Assembler::target_at(int32_t pos) {
325   Instr instr = instr_at(pos);
326   if ((instr & ~kImm16Mask) == 0) {
327     // Emitted label constant, not part of a branch.
328     return instr - (Code::kHeaderSize - kHeapObjectTag);
329   }
330   // Check we have a branch instruction.
331   ASSERT(is_branch(instr));
332   // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
333   // the compiler uses arithmectic shifts for signed integers.
334   int32_t imm18 = ((instr &
335                     static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
336 
337   return pos + kBranchPCOffset + imm18;
338 }
339 
340 
target_at_put(int32_t pos,int32_t target_pos)341 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
342   Instr instr = instr_at(pos);
343   if ((instr & ~kImm16Mask) == 0) {
344     ASSERT(target_pos == kEndOfChain || target_pos >= 0);
345     // Emitted label constant, not part of a branch.
346     // Make label relative to Code* of generated Code object.
347     instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
348     return;
349   }
350 
351   ASSERT(is_branch(instr));
352   int32_t imm18 = target_pos - (pos + kBranchPCOffset);
353   ASSERT((imm18 & 3) == 0);
354 
355   instr &= ~kImm16Mask;
356   int32_t imm16 = imm18 >> 2;
357   ASSERT(is_int16(imm16));
358 
359   instr_at_put(pos, instr | (imm16 & kImm16Mask));
360 }
361 
362 
print(Label * L)363 void Assembler::print(Label* L) {
364   if (L->is_unused()) {
365     PrintF("unused label\n");
366   } else if (L->is_bound()) {
367     PrintF("bound label to %d\n", L->pos());
368   } else if (L->is_linked()) {
369     Label l = *L;
370     PrintF("unbound label");
371     while (l.is_linked()) {
372       PrintF("@ %d ", l.pos());
373       Instr instr = instr_at(l.pos());
374       if ((instr & ~kImm16Mask) == 0) {
375         PrintF("value\n");
376       } else {
377         PrintF("%d\n", instr);
378       }
379       next(&l);
380     }
381   } else {
382     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
383   }
384 }
385 
386 
bind_to(Label * L,int pos)387 void Assembler::bind_to(Label* L, int pos) {
388   ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
389   while (L->is_linked()) {
390     int32_t fixup_pos = L->pos();
391     next(L);  // call next before overwriting link with target at fixup_pos
392     target_at_put(fixup_pos, pos);
393   }
394   L->bind_to(pos);
395 
396   // Keep track of the last bound label so we don't eliminate any instructions
397   // before a bound label.
398   if (pos > last_bound_pos_)
399     last_bound_pos_ = pos;
400 }
401 
402 
link_to(Label * L,Label * appendix)403 void Assembler::link_to(Label* L, Label* appendix) {
404   if (appendix->is_linked()) {
405     if (L->is_linked()) {
406       // Append appendix to L's list.
407       int fixup_pos;
408       int link = L->pos();
409       do {
410         fixup_pos = link;
411         link = target_at(fixup_pos);
412       } while (link > 0);
413       ASSERT(link == kEndOfChain);
414       target_at_put(fixup_pos, appendix->pos());
415     } else {
416       // L is empty, simply use appendix
417       *L = *appendix;
418     }
419   }
420   appendix->Unuse();  // appendix should not be used anymore
421 }
422 
423 
bind(Label * L)424 void Assembler::bind(Label* L) {
425   ASSERT(!L->is_bound());  // label can only be bound once
426   bind_to(L, pc_offset());
427 }
428 
429 
next(Label * L)430 void Assembler::next(Label* L) {
431   ASSERT(L->is_linked());
432   int link = target_at(L->pos());
433   if (link > 0) {
434     L->link_to(link);
435   } else {
436     ASSERT(link == kEndOfChain);
437     L->Unuse();
438   }
439 }
440 
441 
442 // We have to use a temporary register for things that can be relocated even
443 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
444 // space.  There is no guarantee that the relocated location can be similarly
445 // encoded.
MustUseAt(RelocInfo::Mode rmode)446 bool Assembler::MustUseAt(RelocInfo::Mode rmode) {
447   if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
448     return Serializer::enabled();
449   } else if (rmode == RelocInfo::NONE) {
450     return false;
451   }
452   return true;
453 }
454 
455 
GenInstrRegister(Opcode opcode,Register rs,Register rt,Register rd,uint16_t sa,SecondaryField func)456 void Assembler::GenInstrRegister(Opcode opcode,
457                                  Register rs,
458                                  Register rt,
459                                  Register rd,
460                                  uint16_t sa,
461                                  SecondaryField func) {
462   ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
463   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
464       | (rd.code() << kRdShift) | (sa << kSaShift) | func;
465   emit(instr);
466 }
467 
468 
GenInstrRegister(Opcode opcode,SecondaryField fmt,FPURegister ft,FPURegister fs,FPURegister fd,SecondaryField func)469 void Assembler::GenInstrRegister(Opcode opcode,
470                                  SecondaryField fmt,
471                                  FPURegister ft,
472                                  FPURegister fs,
473                                  FPURegister fd,
474                                  SecondaryField func) {
475   ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
476   Instr instr = opcode | fmt | (ft.code() << 16) | (fs.code() << kFsShift)
477       | (fd.code() << 6) | func;
478   emit(instr);
479 }
480 
481 
GenInstrRegister(Opcode opcode,SecondaryField fmt,Register rt,FPURegister fs,FPURegister fd,SecondaryField func)482 void Assembler::GenInstrRegister(Opcode opcode,
483                                  SecondaryField fmt,
484                                  Register rt,
485                                  FPURegister fs,
486                                  FPURegister fd,
487                                  SecondaryField func) {
488   ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
489   Instr instr = opcode | fmt | (rt.code() << kRtShift)
490       | (fs.code() << kFsShift) | (fd.code() << 6) | func;
491   emit(instr);
492 }
493 
494 
495 // Instructions with immediate value.
496 // Registers are in the order of the instruction encoding, from left to right.
GenInstrImmediate(Opcode opcode,Register rs,Register rt,int32_t j)497 void Assembler::GenInstrImmediate(Opcode opcode,
498                                   Register rs,
499                                   Register rt,
500                                   int32_t j) {
501   ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
502   Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
503       | (j & kImm16Mask);
504   emit(instr);
505 }
506 
507 
GenInstrImmediate(Opcode opcode,Register rs,SecondaryField SF,int32_t j)508 void Assembler::GenInstrImmediate(Opcode opcode,
509                                   Register rs,
510                                   SecondaryField SF,
511                                   int32_t j) {
512   ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j)));
513   Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
514   emit(instr);
515 }
516 
517 
GenInstrImmediate(Opcode opcode,Register rs,FPURegister ft,int32_t j)518 void Assembler::GenInstrImmediate(Opcode opcode,
519                                   Register rs,
520                                   FPURegister ft,
521                                   int32_t j) {
522   ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
523   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
524       | (j & kImm16Mask);
525   emit(instr);
526 }
527 
528 
529 // Registers are in the order of the instruction encoding, from left to right.
GenInstrJump(Opcode opcode,uint32_t address)530 void Assembler::GenInstrJump(Opcode opcode,
531                               uint32_t address) {
532   ASSERT(is_uint26(address));
533   Instr instr = opcode | address;
534   emit(instr);
535 }
536 
537 
branch_offset(Label * L,bool jump_elimination_allowed)538 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
539   int32_t target_pos;
540   if (L->is_bound()) {
541     target_pos = L->pos();
542   } else {
543     if (L->is_linked()) {
544       target_pos = L->pos();  // L's link
545     } else {
546       target_pos = kEndOfChain;
547     }
548     L->link_to(pc_offset());
549   }
550 
551   int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
552   return offset;
553 }
554 
555 
label_at_put(Label * L,int at_offset)556 void Assembler::label_at_put(Label* L, int at_offset) {
557   int target_pos;
558   if (L->is_bound()) {
559     target_pos = L->pos();
560   } else {
561     if (L->is_linked()) {
562       target_pos = L->pos();  // L's link
563     } else {
564       target_pos = kEndOfChain;
565     }
566     L->link_to(at_offset);
567     instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
568   }
569 }
570 
571 
572 //------- Branch and jump instructions --------
573 
b(int16_t offset)574 void Assembler::b(int16_t offset) {
575   beq(zero_reg, zero_reg, offset);
576 }
577 
578 
bal(int16_t offset)579 void Assembler::bal(int16_t offset) {
580   bgezal(zero_reg, offset);
581 }
582 
583 
beq(Register rs,Register rt,int16_t offset)584 void Assembler::beq(Register rs, Register rt, int16_t offset) {
585   GenInstrImmediate(BEQ, rs, rt, offset);
586 }
587 
588 
bgez(Register rs,int16_t offset)589 void Assembler::bgez(Register rs, int16_t offset) {
590   GenInstrImmediate(REGIMM, rs, BGEZ, offset);
591 }
592 
593 
bgezal(Register rs,int16_t offset)594 void Assembler::bgezal(Register rs, int16_t offset) {
595   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
596 }
597 
598 
bgtz(Register rs,int16_t offset)599 void Assembler::bgtz(Register rs, int16_t offset) {
600   GenInstrImmediate(BGTZ, rs, zero_reg, offset);
601 }
602 
603 
blez(Register rs,int16_t offset)604 void Assembler::blez(Register rs, int16_t offset) {
605   GenInstrImmediate(BLEZ, rs, zero_reg, offset);
606 }
607 
608 
bltz(Register rs,int16_t offset)609 void Assembler::bltz(Register rs, int16_t offset) {
610   GenInstrImmediate(REGIMM, rs, BLTZ, offset);
611 }
612 
613 
bltzal(Register rs,int16_t offset)614 void Assembler::bltzal(Register rs, int16_t offset) {
615   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
616 }
617 
618 
bne(Register rs,Register rt,int16_t offset)619 void Assembler::bne(Register rs, Register rt, int16_t offset) {
620   GenInstrImmediate(BNE, rs, rt, offset);
621 }
622 
623 
j(int32_t target)624 void Assembler::j(int32_t target) {
625   ASSERT(is_uint28(target) && ((target & 3) == 0));
626   GenInstrJump(J, target >> 2);
627 }
628 
629 
jr(Register rs)630 void Assembler::jr(Register rs) {
631   GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
632 }
633 
634 
jal(int32_t target)635 void Assembler::jal(int32_t target) {
636   ASSERT(is_uint28(target) && ((target & 3) == 0));
637   GenInstrJump(JAL, target >> 2);
638 }
639 
640 
jalr(Register rs,Register rd)641 void Assembler::jalr(Register rs, Register rd) {
642   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
643 }
644 
645 
646 //-------Data-processing-instructions---------
647 
648 // Arithmetic.
649 
add(Register rd,Register rs,Register rt)650 void Assembler::add(Register rd, Register rs, Register rt) {
651   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADD);
652 }
653 
654 
addu(Register rd,Register rs,Register rt)655 void Assembler::addu(Register rd, Register rs, Register rt) {
656   GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
657 }
658 
659 
addi(Register rd,Register rs,int32_t j)660 void Assembler::addi(Register rd, Register rs, int32_t j) {
661   GenInstrImmediate(ADDI, rs, rd, j);
662 }
663 
664 
addiu(Register rd,Register rs,int32_t j)665 void Assembler::addiu(Register rd, Register rs, int32_t j) {
666   GenInstrImmediate(ADDIU, rs, rd, j);
667 }
668 
669 
sub(Register rd,Register rs,Register rt)670 void Assembler::sub(Register rd, Register rs, Register rt) {
671   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUB);
672 }
673 
674 
subu(Register rd,Register rs,Register rt)675 void Assembler::subu(Register rd, Register rs, Register rt) {
676   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
677 }
678 
679 
mul(Register rd,Register rs,Register rt)680 void Assembler::mul(Register rd, Register rs, Register rt) {
681   GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
682 }
683 
684 
mult(Register rs,Register rt)685 void Assembler::mult(Register rs, Register rt) {
686   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
687 }
688 
689 
multu(Register rs,Register rt)690 void Assembler::multu(Register rs, Register rt) {
691   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
692 }
693 
694 
div(Register rs,Register rt)695 void Assembler::div(Register rs, Register rt) {
696   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
697 }
698 
699 
divu(Register rs,Register rt)700 void Assembler::divu(Register rs, Register rt) {
701   GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
702 }
703 
704 
705 // Logical.
706 
and_(Register rd,Register rs,Register rt)707 void Assembler::and_(Register rd, Register rs, Register rt) {
708   GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
709 }
710 
711 
andi(Register rt,Register rs,int32_t j)712 void Assembler::andi(Register rt, Register rs, int32_t j) {
713   GenInstrImmediate(ANDI, rs, rt, j);
714 }
715 
716 
or_(Register rd,Register rs,Register rt)717 void Assembler::or_(Register rd, Register rs, Register rt) {
718   GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
719 }
720 
721 
ori(Register rt,Register rs,int32_t j)722 void Assembler::ori(Register rt, Register rs, int32_t j) {
723   GenInstrImmediate(ORI, rs, rt, j);
724 }
725 
726 
xor_(Register rd,Register rs,Register rt)727 void Assembler::xor_(Register rd, Register rs, Register rt) {
728   GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
729 }
730 
731 
xori(Register rt,Register rs,int32_t j)732 void Assembler::xori(Register rt, Register rs, int32_t j) {
733   GenInstrImmediate(XORI, rs, rt, j);
734 }
735 
736 
nor(Register rd,Register rs,Register rt)737 void Assembler::nor(Register rd, Register rs, Register rt) {
738   GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
739 }
740 
741 
742 // Shifts.
sll(Register rd,Register rt,uint16_t sa)743 void Assembler::sll(Register rd, Register rt, uint16_t sa) {
744   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
745 }
746 
747 
sllv(Register rd,Register rt,Register rs)748 void Assembler::sllv(Register rd, Register rt, Register rs) {
749   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
750 }
751 
752 
srl(Register rd,Register rt,uint16_t sa)753 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
754   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
755 }
756 
757 
srlv(Register rd,Register rt,Register rs)758 void Assembler::srlv(Register rd, Register rt, Register rs) {
759   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
760 }
761 
762 
sra(Register rd,Register rt,uint16_t sa)763 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
764   GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
765 }
766 
767 
srav(Register rd,Register rt,Register rs)768 void Assembler::srav(Register rd, Register rt, Register rs) {
769   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
770 }
771 
772 
773 //------------Memory-instructions-------------
774 
lb(Register rd,const MemOperand & rs)775 void Assembler::lb(Register rd, const MemOperand& rs) {
776   GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
777 }
778 
779 
lbu(Register rd,const MemOperand & rs)780 void Assembler::lbu(Register rd, const MemOperand& rs) {
781   GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
782 }
783 
784 
lw(Register rd,const MemOperand & rs)785 void Assembler::lw(Register rd, const MemOperand& rs) {
786   GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
787 }
788 
789 
sb(Register rd,const MemOperand & rs)790 void Assembler::sb(Register rd, const MemOperand& rs) {
791   GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
792 }
793 
794 
sw(Register rd,const MemOperand & rs)795 void Assembler::sw(Register rd, const MemOperand& rs) {
796   GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
797 }
798 
799 
lui(Register rd,int32_t j)800 void Assembler::lui(Register rd, int32_t j) {
801   GenInstrImmediate(LUI, zero_reg, rd, j);
802 }
803 
804 
805 //-------------Misc-instructions--------------
806 
807 // Break / Trap instructions.
break_(uint32_t code)808 void Assembler::break_(uint32_t code) {
809   ASSERT((code & ~0xfffff) == 0);
810   Instr break_instr = SPECIAL | BREAK | (code << 6);
811   emit(break_instr);
812 }
813 
814 
tge(Register rs,Register rt,uint16_t code)815 void Assembler::tge(Register rs, Register rt, uint16_t code) {
816   ASSERT(is_uint10(code));
817   Instr instr = SPECIAL | TGE | rs.code() << kRsShift
818       | rt.code() << kRtShift | code << 6;
819   emit(instr);
820 }
821 
822 
tgeu(Register rs,Register rt,uint16_t code)823 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
824   ASSERT(is_uint10(code));
825   Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
826       | rt.code() << kRtShift | code << 6;
827   emit(instr);
828 }
829 
830 
tlt(Register rs,Register rt,uint16_t code)831 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
832   ASSERT(is_uint10(code));
833   Instr instr =
834       SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
835   emit(instr);
836 }
837 
838 
tltu(Register rs,Register rt,uint16_t code)839 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
840   ASSERT(is_uint10(code));
841   Instr instr = SPECIAL | TLTU | rs.code() << kRsShift
842       | rt.code() << kRtShift | code << 6;
843   emit(instr);
844 }
845 
846 
teq(Register rs,Register rt,uint16_t code)847 void Assembler::teq(Register rs, Register rt, uint16_t code) {
848   ASSERT(is_uint10(code));
849   Instr instr =
850       SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
851   emit(instr);
852 }
853 
854 
tne(Register rs,Register rt,uint16_t code)855 void Assembler::tne(Register rs, Register rt, uint16_t code) {
856   ASSERT(is_uint10(code));
857   Instr instr =
858       SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
859   emit(instr);
860 }
861 
862 
863 // Move from HI/LO register.
864 
mfhi(Register rd)865 void Assembler::mfhi(Register rd) {
866   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
867 }
868 
869 
mflo(Register rd)870 void Assembler::mflo(Register rd) {
871   GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
872 }
873 
874 
875 // Set on less than instructions.
slt(Register rd,Register rs,Register rt)876 void Assembler::slt(Register rd, Register rs, Register rt) {
877   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
878 }
879 
880 
sltu(Register rd,Register rs,Register rt)881 void Assembler::sltu(Register rd, Register rs, Register rt) {
882   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
883 }
884 
885 
slti(Register rt,Register rs,int32_t j)886 void Assembler::slti(Register rt, Register rs, int32_t j) {
887   GenInstrImmediate(SLTI, rs, rt, j);
888 }
889 
890 
sltiu(Register rt,Register rs,int32_t j)891 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
892   GenInstrImmediate(SLTIU, rs, rt, j);
893 }
894 
895 
896 //--------Coprocessor-instructions----------------
897 
898 // Load, store, move.
lwc1(FPURegister fd,const MemOperand & src)899 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
900   GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
901 }
902 
903 
ldc1(FPURegister fd,const MemOperand & src)904 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
905   GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
906 }
907 
908 
swc1(FPURegister fd,const MemOperand & src)909 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
910   GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
911 }
912 
913 
sdc1(FPURegister fd,const MemOperand & src)914 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
915   GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
916 }
917 
918 
mtc1(FPURegister fs,Register rt)919 void Assembler::mtc1(FPURegister fs, Register rt) {
920   GenInstrRegister(COP1, MTC1, rt, fs, f0);
921 }
922 
923 
mthc1(FPURegister fs,Register rt)924 void Assembler::mthc1(FPURegister fs, Register rt) {
925   GenInstrRegister(COP1, MTHC1, rt, fs, f0);
926 }
927 
928 
mfc1(FPURegister fs,Register rt)929 void Assembler::mfc1(FPURegister fs, Register rt) {
930   GenInstrRegister(COP1, MFC1, rt, fs, f0);
931 }
932 
933 
mfhc1(FPURegister fs,Register rt)934 void Assembler::mfhc1(FPURegister fs, Register rt) {
935   GenInstrRegister(COP1, MFHC1, rt, fs, f0);
936 }
937 
938 
939 // Conversions.
940 
cvt_w_s(FPURegister fd,FPURegister fs)941 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
942   GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
943 }
944 
945 
cvt_w_d(FPURegister fd,FPURegister fs)946 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
947   GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
948 }
949 
950 
cvt_l_s(FPURegister fd,FPURegister fs)951 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
952   GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
953 }
954 
955 
cvt_l_d(FPURegister fd,FPURegister fs)956 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
957   GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
958 }
959 
960 
cvt_s_w(FPURegister fd,FPURegister fs)961 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
962   GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
963 }
964 
965 
cvt_s_l(FPURegister fd,FPURegister fs)966 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
967   GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
968 }
969 
970 
cvt_s_d(FPURegister fd,FPURegister fs)971 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
972   GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
973 }
974 
975 
cvt_d_w(FPURegister fd,FPURegister fs)976 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
977   GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
978 }
979 
980 
cvt_d_l(FPURegister fd,FPURegister fs)981 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
982   GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
983 }
984 
985 
cvt_d_s(FPURegister fd,FPURegister fs)986 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
987   GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
988 }
989 
990 
991 // Conditions.
c(FPUCondition cond,SecondaryField fmt,FPURegister ft,FPURegister fs,uint16_t cc)992 void Assembler::c(FPUCondition cond, SecondaryField fmt,
993     FPURegister ft, FPURegister fs, uint16_t cc) {
994   ASSERT(is_uint3(cc));
995   ASSERT((fmt & ~(31 << kRsShift)) == 0);
996   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
997       | cc << 8 | 3 << 4 | cond;
998   emit(instr);
999 }
1000 
1001 
bc1f(int16_t offset,uint16_t cc)1002 void Assembler::bc1f(int16_t offset, uint16_t cc) {
1003   ASSERT(is_uint3(cc));
1004   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
1005   emit(instr);
1006 }
1007 
1008 
bc1t(int16_t offset,uint16_t cc)1009 void Assembler::bc1t(int16_t offset, uint16_t cc) {
1010   ASSERT(is_uint3(cc));
1011   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
1012   emit(instr);
1013 }
1014 
1015 
1016 // Debugging.
RecordJSReturn()1017 void Assembler::RecordJSReturn() {
1018   WriteRecordedPositions();
1019   CheckBuffer();
1020   RecordRelocInfo(RelocInfo::JS_RETURN);
1021 }
1022 
1023 
RecordComment(const char * msg)1024 void Assembler::RecordComment(const char* msg) {
1025   if (FLAG_debug_code) {
1026     CheckBuffer();
1027     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1028   }
1029 }
1030 
1031 
RecordPosition(int pos)1032 void Assembler::RecordPosition(int pos) {
1033   if (pos == RelocInfo::kNoPosition) return;
1034   ASSERT(pos >= 0);
1035   current_position_ = pos;
1036 }
1037 
1038 
RecordStatementPosition(int pos)1039 void Assembler::RecordStatementPosition(int pos) {
1040   if (pos == RelocInfo::kNoPosition) return;
1041   ASSERT(pos >= 0);
1042   current_statement_position_ = pos;
1043 }
1044 
1045 
WriteRecordedPositions()1046 void Assembler::WriteRecordedPositions() {
1047   // Write the statement position if it is different from what was written last
1048   // time.
1049   if (current_statement_position_ != written_statement_position_) {
1050     CheckBuffer();
1051     RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
1052     written_statement_position_ = current_statement_position_;
1053   }
1054 
1055   // Write the position if it is different from what was written last time and
1056   // also different from the written statement position.
1057   if (current_position_ != written_position_ &&
1058       current_position_ != written_statement_position_) {
1059     CheckBuffer();
1060     RecordRelocInfo(RelocInfo::POSITION, current_position_);
1061     written_position_ = current_position_;
1062   }
1063 }
1064 
1065 
GrowBuffer()1066 void Assembler::GrowBuffer() {
1067   if (!own_buffer_) FATAL("external code buffer is too small");
1068 
1069   // Compute new buffer size.
1070   CodeDesc desc;  // the new buffer
1071   if (buffer_size_ < 4*KB) {
1072     desc.buffer_size = 4*KB;
1073   } else if (buffer_size_ < 1*MB) {
1074     desc.buffer_size = 2*buffer_size_;
1075   } else {
1076     desc.buffer_size = buffer_size_ + 1*MB;
1077   }
1078   CHECK_GT(desc.buffer_size, 0);  // no overflow
1079 
1080   // Setup new buffer.
1081   desc.buffer = NewArray<byte>(desc.buffer_size);
1082 
1083   desc.instr_size = pc_offset();
1084   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
1085 
1086   // Copy the data.
1087   int pc_delta = desc.buffer - buffer_;
1088   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
1089   memmove(desc.buffer, buffer_, desc.instr_size);
1090   memmove(reloc_info_writer.pos() + rc_delta,
1091           reloc_info_writer.pos(), desc.reloc_size);
1092 
1093   // Switch buffers.
1094   DeleteArray(buffer_);
1095   buffer_ = desc.buffer;
1096   buffer_size_ = desc.buffer_size;
1097   pc_ += pc_delta;
1098   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
1099                                reloc_info_writer.last_pc() + pc_delta);
1100 
1101 
1102   // On ia32 and ARM pc relative addressing is used, and we thus need to apply a
1103   // shift by pc_delta. But on MIPS the target address it directly loaded, so
1104   // we do not need to relocate here.
1105 
1106   ASSERT(!overflow());
1107 }
1108 
1109 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)1110 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
1111   RelocInfo rinfo(pc_, rmode, data);  // we do not try to reuse pool constants
1112   if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
1113     // Adjust code for new modes.
1114     ASSERT(RelocInfo::IsJSReturn(rmode)
1115            || RelocInfo::IsComment(rmode)
1116            || RelocInfo::IsPosition(rmode));
1117     // These modes do not need an entry in the constant pool.
1118   }
1119   if (rinfo.rmode() != RelocInfo::NONE) {
1120     // Don't record external references unless the heap will be serialized.
1121     if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
1122         !Serializer::enabled() &&
1123         !FLAG_debug_code) {
1124       return;
1125     }
1126     ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
1127     reloc_info_writer.Write(&rinfo);
1128   }
1129 }
1130 
1131 
target_address_at(Address pc)1132 Address Assembler::target_address_at(Address pc) {
1133   Instr instr1 = instr_at(pc);
1134   Instr instr2 = instr_at(pc + kInstrSize);
1135   // Check we have 2 instructions generated by li.
1136   ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
1137          ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI ||
1138                             (instr2 & kOpcodeMask) == ORI ||
1139                             (instr2 & kOpcodeMask) == LUI)));
1140   // Interpret these 2 instructions.
1141   if (instr1 == nopInstr) {
1142     if ((instr2 & kOpcodeMask) == ADDI) {
1143       return reinterpret_cast<Address>(((instr2 & kImm16Mask) << 16) >> 16);
1144     } else if ((instr2 & kOpcodeMask) == ORI) {
1145       return reinterpret_cast<Address>(instr2 & kImm16Mask);
1146     } else if ((instr2 & kOpcodeMask) == LUI) {
1147       return reinterpret_cast<Address>((instr2 & kImm16Mask) << 16);
1148     }
1149   } else if ((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) {
1150     // 32 bits value.
1151     return reinterpret_cast<Address>(
1152         (instr1 & kImm16Mask) << 16 | (instr2 & kImm16Mask));
1153   }
1154 
1155   // We should never get here.
1156   UNREACHABLE();
1157   return (Address)0x0;
1158 }
1159 
1160 
set_target_address_at(Address pc,Address target)1161 void Assembler::set_target_address_at(Address pc, Address target) {
1162   // On MIPS we need to patch the code to generate.
1163 
1164   // First check we have a li.
1165   Instr instr2 = instr_at(pc + kInstrSize);
1166 #ifdef DEBUG
1167   Instr instr1 = instr_at(pc);
1168 
1169   // Check we have indeed the result from a li with MustUseAt true.
1170   CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
1171         ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU ||
1172                            (instr2 & kOpcodeMask)== ORI ||
1173                            (instr2 & kOpcodeMask)== LUI)));
1174 #endif
1175 
1176 
1177   uint32_t rt_code = (instr2 & kRtFieldMask);
1178   uint32_t* p = reinterpret_cast<uint32_t*>(pc);
1179   uint32_t itarget = reinterpret_cast<uint32_t>(target);
1180 
1181   if (is_int16(itarget)) {
1182     // nop
1183     // addiu rt zero_reg j
1184     *p = nopInstr;
1185     *(p+1) = ADDIU | rt_code | (itarget & LOMask);
1186   } else if (!(itarget & HIMask)) {
1187     // nop
1188     // ori rt zero_reg j
1189     *p = nopInstr;
1190     *(p+1) = ORI | rt_code | (itarget & LOMask);
1191   } else if (!(itarget & LOMask)) {
1192     // nop
1193     // lui rt (HIMask & itarget)>>16
1194     *p = nopInstr;
1195     *(p+1) = LUI | rt_code | ((itarget & HIMask)>>16);
1196   } else {
1197     // lui rt (HIMask & itarget)>>16
1198     // ori rt rt, (LOMask & itarget)
1199     *p = LUI | rt_code | ((itarget & HIMask)>>16);
1200     *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & LOMask);
1201   }
1202 
1203   CPU::FlushICache(pc, 2 * sizeof(int32_t));
1204 }
1205 
1206 
1207 } }  // namespace v8::internal
1208 
1209