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

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

Issue 543161: Added support for MIPS in architecture independent files.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 2006-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
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
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.
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.
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
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
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
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
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
281 void Assembler::GetCode(CodeDesc* desc) {
282 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap
283 // setup desc
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
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
319 || rt_field == BGEZ
320 || rt_field == BLTZAL
321 || rt_field == BGEZAL))
322 || (opcode == COP1 && rs_field == BC1); // Coprocessor branch
323 }
324
325
326 int Assembler::target_at(int32_t pos) {
327 Instr instr = instr_at(pos);
328 if ((instr & ~kImm16Mask) == 0) {
329 // Emitted label constant, not part of a branch.
330 return instr - (Code::kHeaderSize - kHeapObjectTag);
331 }
332 // Check we have a branch instruction.
333 ASSERT(is_branch(instr));
334 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
335 // the compiler uses arithmectic shifts for signed integers.
336 int32_t imm18 = (((int32_t)instr & (int32_t)kImm16Mask) << 16) >> 14;
337
338 return pos + kBranchPCOffset + imm18;
339 }
340
341
342 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
343 Instr instr = instr_at(pos);
344 if ((instr & ~kImm16Mask) == 0) {
345 ASSERT(target_pos == kEndOfChain || target_pos >= 0);
346 // Emitted label constant, not part of a branch.
347 // Make label relative to Code* of generated Code object.
348 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
349 return;
350 }
351
352 ASSERT(is_branch(instr));
353 int32_t imm18 = target_pos - (pos + kBranchPCOffset);
354 ASSERT((imm18 & 3) == 0);
355
356 instr &= ~kImm16Mask;
357 int32_t imm16 = imm18 >> 2;
358 ASSERT(is_int16(imm16));
359
360 instr_at_put(pos, instr | (imm16 & kImm16Mask));
361 }
362
363
364 void Assembler::print(Label* L) {
365 if (L->is_unused()) {
366 PrintF("unused label\n");
367 } else if (L->is_bound()) {
368 PrintF("bound label to %d\n", L->pos());
369 } else if (L->is_linked()) {
370 Label l = *L;
371 PrintF("unbound label");
372 while (l.is_linked()) {
373 PrintF("@ %d ", l.pos());
374 Instr instr = instr_at(l.pos());
375 if ((instr & ~kImm16Mask) == 0) {
376 PrintF("value\n");
377 } else {
378 PrintF("%d\n", instr);
379 }
380 next(&l);
381 }
382 } else {
383 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
384 }
385 }
386
387
388 void Assembler::bind_to(Label* L, int pos) {
389 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
390 while (L->is_linked()) {
391 int32_t fixup_pos = L->pos();
392 next(L); // call next before overwriting link with target at fixup_pos
393 target_at_put(fixup_pos, pos);
394 }
395 L->bind_to(pos);
396
397 // Keep track of the last bound label so we don't eliminate any instructions
398 // before a bound label.
399 if (pos > last_bound_pos_)
400 last_bound_pos_ = pos;
401 }
402
403
404 void Assembler::link_to(Label* L, Label* appendix) {
405 if (appendix->is_linked()) {
406 if (L->is_linked()) {
407 // append appendix to L's list
408 int fixup_pos;
409 int link = L->pos();
410 do {
411 fixup_pos = link;
412 link = target_at(fixup_pos);
413 } while (link > 0);
414 ASSERT(link == kEndOfChain);
415 target_at_put(fixup_pos, appendix->pos());
416 } else {
417 // L is empty, simply use appendix
418 *L = *appendix;
419 }
420 }
421 appendix->Unuse(); // appendix should not be used anymore
422 }
423
424
425 void Assembler::bind(Label* L) {
426 ASSERT(!L->is_bound()); // label can only be bound once
427 bind_to(L, pc_offset());
428 }
429
430
431 void Assembler::next(Label* L) {
432 ASSERT(L->is_linked());
433 int link = target_at(L->pos());
434 if (link > 0) {
435 L->link_to(link);
436 } else {
437 ASSERT(link == kEndOfChain);
438 L->Unuse();
439 }
440 }
441
442
443 // We have to use a temporary register for things that can be relocated even
444 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
445 // space. There is no guarantee that the relocated location can be similarly
446 // encoded.
447 bool Assembler::MustUseAt(RelocInfo::Mode rmode) {
448 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
449 return Serializer::enabled();
450 } else if (rmode == RelocInfo::NONE) {
451 return false;
452 }
453 return true;
454 }
455
456
457 void Assembler::GenInstrRegister(Opcode opcode,
458 Register rs,
459 Register rt,
460 Register rd,
461 uint16_t sa,
462 SecondaryField func) {
463 ASSERT(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
464 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
465 | (rd.code() << kRdShift) | (sa << kSaShift) | func;
466 emit(instr);
467 }
468
469
470 void Assembler::GenInstrRegister(Opcode opcode,
471 SecondaryField fmt,
472 FPURegister ft,
473 FPURegister fs,
474 FPURegister fd,
475 SecondaryField func) {
476 ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
477 Instr instr = opcode | fmt | (ft.code() << 16) | (fs.code() << kFsShift)
478 | (fd.code() << 6) | func;
479 emit(instr);
480 }
481
482
483 void Assembler::GenInstrRegister(Opcode opcode,
484 SecondaryField fmt,
485 Register rt,
486 FPURegister fs,
487 FPURegister fd,
488 SecondaryField func) {
489 ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
490 Instr instr = opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift)
491 | (fd.code() << 6) | func;
492 emit(instr);
493 }
494
495
496 // Instructions with immediate value
497 // Registers are in the order of the instruction encoding, from left to right.
498 void Assembler::GenInstrImmediate(Opcode opcode,
499 Register rs,
500 Register rt,
501 int32_t j) {
502 ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
503 Instr instr = opcode | (rs.code() << kRsShift)
504 | (rt.code() << kRtShift) | (j & kImm16Mask);
505 emit(instr);
506 }
507
508
509 void Assembler::GenInstrImmediate(Opcode opcode,
510 Register rs,
511 SecondaryField SF,
512 int32_t j) {
513 ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j)));
514 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
515 emit(instr);
516 }
517
518
519 void Assembler::GenInstrImmediate(Opcode opcode,
520 Register rs,
521 FPURegister ft,
522 int32_t j) {
523 ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
524 Instr instr = opcode | (rs.code() << kRsShift)
525 | (ft.code() << kFtShift) | (j & kImm16Mask);
526 emit(instr);
527 }
528
529
530 // Registers are in the order of the instruction encoding, from left to right.
531 void Assembler::GenInstrJump(Opcode opcode,
532 uint32_t address) {
533 ASSERT(is_uint26(address));
534 Instr instr = opcode | address;
535 emit(instr);
536 }
537
538
539 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
540 int32_t target_pos;
541 if (L->is_bound()) {
542 target_pos = L->pos();
543 } else {
544 if (L->is_linked()) {
545 target_pos = L->pos(); // L's link
546 } else {
547 target_pos = kEndOfChain;
548 }
549 L->link_to(pc_offset());
550 }
551
552 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
553 return offset;
554 }
555
556
557 void Assembler::label_at_put(Label* L, int at_offset) {
558 int target_pos;
559 if (L->is_bound()) {
560 target_pos = L->pos();
561 } else {
562 if (L->is_linked()) {
563 target_pos = L->pos(); // L's link
564 } else {
565 target_pos = kEndOfChain;
566 }
567 L->link_to(at_offset);
568 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
569 }
570 }
571
572
573 //------- Branch and jump instructions --------
574
575 void Assembler::b(int16_t offset) {
576 beq(zero_reg, zero_reg, offset);
577 }
578
579
580 void Assembler::bal(int16_t offset) {
581 bgezal(zero_reg, offset);
582 }
583
584
585 void Assembler::beq(Register rs, Register rt, int16_t offset) {
586 GenInstrImmediate(BEQ, rs, rt, offset);
587 }
588
589
590 void Assembler::bgez(Register rs, int16_t offset) {
591 GenInstrImmediate(REGIMM, rs, BGEZ, offset);
592 }
593
594
595 void Assembler::bgezal(Register rs, int16_t offset) {
596 GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
597 }
598
599
600 void Assembler::bgtz(Register rs, int16_t offset) {
601 GenInstrImmediate(BGTZ, rs, zero_reg, offset);
602 }
603
604
605 void Assembler::blez(Register rs, int16_t offset) {
606 GenInstrImmediate(BLEZ, rs, zero_reg, offset);
607 }
608
609
610 void Assembler::bltz(Register rs, int16_t offset) {
611 GenInstrImmediate(REGIMM, rs, BLTZ, offset);
612 }
613
614
615 void Assembler::bltzal(Register rs, int16_t offset) {
616 GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
617 }
618
619
620 void Assembler::bne(Register rs, Register rt, int16_t offset) {
621 GenInstrImmediate(BNE, rs, rt, offset);
622 }
623
624
625 void Assembler::j(int32_t target) {
626 ASSERT(is_uint28(target) && ((target & 3) == 0));
627 GenInstrJump(J, target >> 2);
628 }
629
630
631 void Assembler::jr(Register rs) {
632 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
633 }
634
635
636 void Assembler::jal(int32_t target) {
637 ASSERT(is_uint28(target) && ((target & 3) == 0));
638 GenInstrJump(JAL, target >> 2);
639 }
640
641
642 void Assembler::jalr(Register rs, Register rd) {
643 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
644 }
645
646
647 //-------Data-processing-instructions---------
648
649 // Arithmetic
650
651 void Assembler::add(Register rd, Register rs, Register rt) {
652 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADD);
653 }
654
655
656 void Assembler::addu(Register rd, Register rs, Register rt) {
657 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
658 }
659
660
661 void Assembler::addi(Register rd, Register rs, int32_t j) {
662 GenInstrImmediate(ADDI, rs, rd, j);
663 }
664
665
666 void Assembler::addiu(Register rd, Register rs, int32_t j) {
667 GenInstrImmediate(ADDIU, rs, rd, j);
668 }
669
670
671 void Assembler::sub(Register rd, Register rs, Register rt) {
672 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUB);
673 }
674
675
676 void Assembler::subu(Register rd, Register rs, Register rt) {
677 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
678 }
679
680
681 void Assembler::mul(Register rd, Register rs, Register rt) {
682 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
683 }
684
685
686 void Assembler::mult(Register rs, Register rt) {
687 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
688 }
689
690
691 void Assembler::multu(Register rs, Register rt) {
692 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
693 }
694
695
696 void Assembler::div(Register rs, Register rt) {
697 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
698 }
699
700
701 void Assembler::divu(Register rs, Register rt) {
702 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
703 }
704
705
706 // Logical
707
708 void Assembler::and_(Register rd, Register rs, Register rt) {
709 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
710 }
711
712
713 void Assembler::andi(Register rt, Register rs, int32_t j) {
714 GenInstrImmediate(ANDI, rs, rt, j);
715 }
716
717
718 void Assembler::or_(Register rd, Register rs, Register rt) {
719 GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
720 }
721
722
723 void Assembler::ori(Register rt, Register rs, int32_t j) {
724 GenInstrImmediate(ORI, rs, rt, j);
725 }
726
727
728 void Assembler::xor_(Register rd, Register rs, Register rt) {
729 GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
730 }
731
732
733 void Assembler::xori(Register rt, Register rs, int32_t j) {
734 GenInstrImmediate(XORI, rs, rt, j);
735 }
736
737
738 void Assembler::nor(Register rd, Register rs, Register rt) {
739 GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
740 }
741
742
743 // Shifts
744 void Assembler::sll(Register rd, Register rt, uint16_t sa) {
745 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SLL);
746 }
747
748
749 void Assembler::sllv(Register rd, Register rt, Register rs) {
750 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
751 }
752
753
754 void Assembler::srl(Register rd, Register rt, uint16_t sa) {
755 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRL);
756 }
757
758
759 void Assembler::srlv(Register rd, Register rt, Register rs) {
760 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
761 }
762
763
764 void Assembler::sra(Register rd, Register rt, uint16_t sa) {
765 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, SRA);
766 }
767
768
769 void Assembler::srav(Register rd, Register rt, Register rs) {
770 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
771 }
772
773
774 //------------Memory-instructions-------------
775
776 void Assembler::lb(Register rd, const MemOperand& rs) {
777 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
778 }
779
780
781 void Assembler::lbu(Register rd, const MemOperand& rs) {
782 GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
783 }
784
785
786 void Assembler::lw(Register rd, const MemOperand& rs) {
787 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
788 }
789
790
791 void Assembler::sb(Register rd, const MemOperand& rs) {
792 GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
793 }
794
795
796 void Assembler::sw(Register rd, const MemOperand& rs) {
797 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
798 }
799
800
801 void Assembler::lui(Register rd, int32_t j) {
802 GenInstrImmediate(LUI, zero_reg, rd, j);
803 }
804
805
806 //-------------Misc-instructions--------------
807
808 // Break / Trap instructions
809 void Assembler::break_(uint32_t code) {
810 ASSERT((code & ~0xfffff) == 0);
811 Instr break_instr = SPECIAL | BREAK | (code << 6);
812 emit(break_instr);
813 }
814
815
816 void Assembler::tge(Register rs, Register rt, uint16_t code) {
817 ASSERT(is_uint10(code));
818 Instr instr = SPECIAL | TGE | rs.code() << kRsShift
819 | rt.code() << kRtShift | code << 6;
820 emit(instr);
821 }
822
823
824 void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
825 ASSERT(is_uint10(code));
826 Instr instr = SPECIAL | TGEU | rs.code() << kRsShift
827 | rt.code() << kRtShift | code << 6;
828 emit(instr);
829 }
830
831
832 void Assembler::tlt(Register rs, Register rt, uint16_t code) {
833 ASSERT(is_uint10(code));
834 Instr instr =
835 SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
836 emit(instr);
837 }
838
839
840 void Assembler::tltu(Register rs, Register rt, uint16_t code) {
841 ASSERT(is_uint10(code));
842 Instr instr = SPECIAL | TLTU | rs.code() << kRsShift |
843 rt.code() << kRtShift | code << 6;
844 emit(instr);
845 }
846
847
848 void Assembler::teq(Register rs, Register rt, uint16_t code) {
849 ASSERT(is_uint10(code));
850 Instr instr =
851 SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
852 emit(instr);
853 }
854
855
856 void Assembler::tne(Register rs, Register rt, uint16_t code) {
857 ASSERT(is_uint10(code));
858 Instr instr =
859 SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6;
860 emit(instr);
861 }
862
863
864 // Move from HI/LO register
865
866 void Assembler::mfhi(Register rd) {
867 GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
868 }
869
870
871 void Assembler::mflo(Register rd) {
872 GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
873 }
874
875
876 // Set on less than instructions
877 void Assembler::slt(Register rd, Register rs, Register rt) {
878 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
879 }
880
881
882 void Assembler::sltu(Register rd, Register rs, Register rt) {
883 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
884 }
885
886
887 void Assembler::slti(Register rt, Register rs, int32_t j) {
888 GenInstrImmediate(SLTI, rs, rt, j);
889 }
890
891
892 void Assembler::sltiu(Register rt, Register rs, int32_t j) {
893 GenInstrImmediate(SLTIU, rs, rt, j);
894 }
895
896
897 //--------Coprocessor-instructions----------------
898
899 // Load, store, move
900 void Assembler::lwc1(FPURegister fd, const MemOperand& src) {
901 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
902 }
903
904
905 void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
906 GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
907 }
908
909
910 void Assembler::swc1(FPURegister fd, const MemOperand& src) {
911 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
912 }
913
914
915 void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
916 GenInstrImmediate(SDC1, src.rm(), fd, src.offset_);
917 }
918
919
920 void Assembler::mtc1(FPURegister fs, Register rt) {
921 GenInstrRegister(COP1, MTC1, rt, fs, f0);
922 }
923
924
925 void Assembler::mthc1(FPURegister fs, Register rt) {
926 GenInstrRegister(COP1, MTHC1, rt, fs, f0);
927 }
928
929
930 void Assembler::mfc1(FPURegister fs, Register rt) {
931 GenInstrRegister(COP1, MFC1, rt, fs, f0);
932 }
933
934
935 void Assembler::mfhc1(FPURegister fs, Register rt) {
936 GenInstrRegister(COP1, MFHC1, rt, fs, f0);
937 }
938
939
940 // Conversions
941
942 void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
943 GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
944 }
945
946
947 void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
948 GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D);
949 }
950
951
952 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
953 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
954 }
955
956
957 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
958 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D);
959 }
960
961
962 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
963 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
964 }
965
966
967 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
968 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
969 }
970
971
972 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
973 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D);
974 }
975
976
977 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
978 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
979 }
980
981
982 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
983 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
984 }
985
986
987 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
988 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
989 }
990
991
992 // Conditions
993 void Assembler::c(FPUCondition cond, SecondaryField fmt,
994 FPURegister ft, FPURegister fs, uint16_t cc) {
995 ASSERT(is_uint3(cc));
996 ASSERT((fmt & ~(31 << kRsShift)) == 0);
997 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift |
998 cc << 8 | 3 << 4 | cond;
999 emit(instr);
1000 }
1001
1002
1003 void Assembler::bc1f(int16_t offset, uint16_t cc) {
1004 ASSERT(is_uint3(cc));
1005 Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
1006 emit(instr);
1007 }
1008
1009
1010 void Assembler::bc1t(int16_t offset, uint16_t cc) {
1011 ASSERT(is_uint3(cc));
1012 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
1013 emit(instr);
1014 }
1015
1016
1017 // Debugging
1018 void Assembler::RecordJSReturn() {
1019 WriteRecordedPositions();
1020 CheckBuffer();
1021 RecordRelocInfo(RelocInfo::JS_RETURN);
1022 }
1023
1024
1025 void Assembler::RecordComment(const char* msg) {
1026 if (FLAG_debug_code) {
1027 CheckBuffer();
1028 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1029 }
1030 }
1031
1032
1033 void Assembler::RecordPosition(int pos) {
1034 if (pos == RelocInfo::kNoPosition) return;
1035 ASSERT(pos >= 0);
1036 current_position_ = pos;
1037 }
1038
1039
1040 void Assembler::RecordStatementPosition(int pos) {
1041 if (pos == RelocInfo::kNoPosition) return;
1042 ASSERT(pos >= 0);
1043 current_statement_position_ = pos;
1044 }
1045
1046
1047 void Assembler::WriteRecordedPositions() {
1048 // Write the statement position if it is different from what was written last
1049 // time.
1050 if (current_statement_position_ != written_statement_position_) {
1051 CheckBuffer();
1052 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
1053 written_statement_position_ = current_statement_position_;
1054 }
1055
1056 // Write the position if it is different from what was written last time and
1057 // also different from the written statement position.
1058 if (current_position_ != written_position_ &&
1059 current_position_ != written_statement_position_) {
1060 CheckBuffer();
1061 RecordRelocInfo(RelocInfo::POSITION, current_position_);
1062 written_position_ = current_position_;
1063 }
1064 }
1065
1066
1067 void Assembler::GrowBuffer() {
1068 if (!own_buffer_) FATAL("external code buffer is too small");
1069
1070 // compute new buffer size
1071 CodeDesc desc; // the new buffer
1072 if (buffer_size_ < 4*KB) {
1073 desc.buffer_size = 4*KB;
1074 } else if (buffer_size_ < 1*MB) {
1075 desc.buffer_size = 2*buffer_size_;
1076 } else {
1077 desc.buffer_size = buffer_size_ + 1*MB;
1078 }
1079 CHECK_GT(desc.buffer_size, 0); // no overflow
1080
1081 // setup new buffer
1082 desc.buffer = NewArray<byte>(desc.buffer_size);
1083
1084 desc.instr_size = pc_offset();
1085 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
1086
1087 // copy the data
1088 int pc_delta = desc.buffer - buffer_;
1089 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
1090 memmove(desc.buffer, buffer_, desc.instr_size);
1091 memmove(reloc_info_writer.pos() + rc_delta,
1092 reloc_info_writer.pos(), desc.reloc_size);
1093
1094 // switch buffers
1095 DeleteArray(buffer_);
1096 buffer_ = desc.buffer;
1097 buffer_size_ = desc.buffer_size;
1098 pc_ += pc_delta;
1099 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
1100 reloc_info_writer.last_pc() + pc_delta);
1101
1102
1103 // On ia32 or ARM pc relative addressing is used, and we thus need to apply a
1104 // shift by pc_delta. But on MIPS the target address it directly loaded, so
1105 // we do not need to relocate here.
1106
1107 ASSERT(!overflow());
1108 }
1109
1110
1111 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
1112 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants
1113 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) {
1114 // Adjust code for new modes
1115 ASSERT(RelocInfo::IsJSReturn(rmode)
1116 || RelocInfo::IsComment(rmode)
1117 || RelocInfo::IsPosition(rmode));
1118 // these modes do not need an entry in the constant pool
1119 }
1120 if (rinfo.rmode() != RelocInfo::NONE) {
1121 // Don't record external references unless the heap will be serialized.
1122 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
1123 !Serializer::enabled() &&
1124 !FLAG_debug_code) {
1125 return;
1126 }
1127 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
1128 reloc_info_writer.Write(&rinfo);
1129 }
1130 }
1131
1132
1133 Address Assembler::target_address_at(Address pc) {
1134 Instr instr1 = instr_at(pc);
1135 Instr instr2 = instr_at(pc + kInstrSize);
1136 // Check we have 2 instructions generated by li.
1137 ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
1138 ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI ||
1139 (instr2 & kOpcodeMask) == ORI ||
1140 (instr2 & kOpcodeMask) == LUI)));
1141 // Interpret these 2 instructions.
1142 if (instr1 == nopInstr) {
1143 if ((instr2 & kOpcodeMask) == ADDI) {
1144 return reinterpret_cast<Address>(((instr2 & kImm16Mask) << 16) >> 16);
1145 } else if ((instr2 & kOpcodeMask) == ORI) {
1146 return reinterpret_cast<Address>(instr2 & kImm16Mask);
1147 } else if ((instr2 & kOpcodeMask) == LUI) {
1148 return reinterpret_cast<Address>((instr2 & kImm16Mask) << 16);
1149 }
1150 } else if ((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) {
1151 // 32 bits value.
1152 return reinterpret_cast<Address>(
1153 (instr1 & kImm16Mask) << 16 | (instr2 & kImm16Mask));
1154 }
1155
1156 // We should never get here.
1157 UNREACHABLE();
1158 return (Address)0x0;
1159 }
1160
1161
1162 void Assembler::set_target_address_at(Address pc, Address target) {
1163 // On MIPS we need to patch the code to generate.
1164
1165 // First check we have a li
1166 Instr instr2 = instr_at(pc + kInstrSize);
1167 #ifdef DEBUG
1168 Instr instr1 = instr_at(pc);
1169
1170 // Check we have indeed the result from a li with MustUseAt true.
1171 CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) ||
1172 ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU ||
1173 (instr2 & kOpcodeMask)== ORI ||
1174 (instr2 & kOpcodeMask)== LUI)));
1175 #endif
1176
1177
1178 uint32_t rt_code = (instr2 & kRtFieldMask);
1179 uint32_t* p = reinterpret_cast<uint32_t*>(pc);
1180 uint32_t itarget = reinterpret_cast<uint32_t>(target);
1181
1182 if (is_int16(itarget)) {
1183 // nop
1184 // addiu rt zero_reg j
1185 *p = nopInstr;
1186 *(p+1) = ADDIU | rt_code | (itarget & LOMask);
1187 } else if (!(itarget & HIMask)) {
1188 // nop
1189 // ori rt zero_reg j
1190 *p = nopInstr;
1191 *(p+1) = ORI | rt_code | (itarget & LOMask);
1192 } else if (!(itarget & LOMask)) {
1193 // nop
1194 // lui rt (HIMask & itarget)>>16
1195 *p = nopInstr;
1196 *(p+1) = LUI | rt_code | ((itarget & HIMask)>>16);
1197 } else {
1198 // lui rt (HIMask & itarget)>>16
1199 // ori rt rt, (LOMask & itarget)
1200 *p = LUI | rt_code | ((itarget & HIMask)>>16);
1201 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & LOMask);
1202 }
1203
1204 CPU::FlushICache(pc, 2* sizeof(int32_t));
1205
1206 #undef instr1
1207 #undef instr2
1208 }
1209
1210
1211 } } // namespace v8::internal
1212
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698