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

Unified Diff: src/mips/assembler-mips.h

Issue 549079: Support for MIPS in architecture independent files.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: src/mips/assembler-mips.h
===================================================================
--- src/mips/assembler-mips.h (revision 0)
+++ src/mips/assembler-mips.h (revision 0)
@@ -0,0 +1,772 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
Søren Thygesen Gjesse 2010/01/19 22:59:12 Please use the copyright header from src/mips/asse
Alexandre 2010/01/22 23:08:42 Changed the copyright. On 2010/01/19 22:59:12, Sør
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the Ugreater copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the Ugreater
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#ifndef V8_MIPS_ASSEMBLER_MIPS_H_
+#define V8_MIPS_ASSEMBLER_MIPS_H_
+
+#include <stdio.h>
+#include "assembler.h"
+#include "constants-mips.h"
+
+using namespace assembler::mips;
+
+namespace v8 {
+namespace internal {
+
+// CPU Registers.
+//
+// 1) We would prefer to use an enum, but enum values are assignment-
+// compatible with int, which has caused code-generation bugs.
+//
+// 2) We would prefer to use a class instead of a struct but we don't like
+// the register initialization to depend on the particular initialization
+// order (which appears to be different on OS X, Linux, and Windows for the
+// installed versions of C++ we tried). Using a struct permits C-style
+// "initialization". Also, the Register objects cannot be const as this
+// forces initialization stubs in MSVC, making us dependent on initialization
+// order.
+//
+// 3) By not using an enum, we are possibly preventing the compiler from
+// doing certain constant folds, which may significantly reduce the
+// code generated for some assembly instructions (because they boil down
+// to a few constants). If this is a problem, we could change the code
+// such that we use an enum in optimized mode, and the struct in debug
+// mode. This way we get the compile-time error checking in debug mode
+// and best performance in optimized code.
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Register and CRegister
+
+// Core register
+struct Register {
+ bool is_valid() const {
+ return 0 <= code_ && code_ < 32; }
antonm 2010/01/21 13:10:45 nit: I think v8 style would be { ... } on one line
Alexandre 2010/01/22 23:08:42 Style issue fixed. On 2010/01/21 13:10:45, antonm
+ bool is(Register reg) const { return code_ == reg.code_; }
+ // The byte-register distinction of ai32 has dissapeared.
+ bool is_byte_register() const { return false; }
+ int code() const {
+ ASSERT(is_valid());
+ return code_;
+ }
+ int bit() const {
+ ASSERT(is_valid());
+ return 1 << code_;
+ }
+
+ // (unfortunately we can't make this private in a struct)
+ int code_;
+};
+
+extern const Register no_reg;
+
+extern const Register zero_reg;
+extern const Register at;
+extern const Register v0;
+extern const Register v1;
+extern const Register a0;
+extern const Register a1;
+extern const Register a2;
+extern const Register a3;
+extern const Register t0;
+extern const Register t1;
+extern const Register t2;
+extern const Register t3;
+extern const Register t4;
+extern const Register t5;
+extern const Register t6;
+extern const Register t7;
+extern const Register s0;
+extern const Register s1;
+extern const Register s2;
+extern const Register s3;
+extern const Register s4;
+extern const Register s5;
+extern const Register s6;
+extern const Register s7;
+extern const Register t8;
+extern const Register t9;
+extern const Register k0;
+extern const Register k1;
+extern const Register gp;
+extern const Register sp;
+extern const Register s8_fp;
+extern const Register ra;
+
+int ToNumber(Register reg);
+
+Register ToRegister(int num);
+
+// Coprocessor register
+struct CRegister {
+ bool is_valid() const { return 0 <= code_ && code_ < 32 ; }
+ bool is(CRegister creg) const { return code_ == creg.code_; }
+ int code() const {
+ ASSERT(is_valid());
+ return code_;
+ }
+ int bit() const {
+ ASSERT(is_valid());
+ return 1 << code_;
+ }
+
+ // (unfortunately we can't make this private in a struct)
+ int code_;
+};
+
+extern const CRegister no_creg;
+
+extern const CRegister f0;
+extern const CRegister f1;
+extern const CRegister f2;
+extern const CRegister f3;
+extern const CRegister f4;
+extern const CRegister f5;
+extern const CRegister f6;
+extern const CRegister f7;
+extern const CRegister f8;
+extern const CRegister f9;
+extern const CRegister f10;
+extern const CRegister f11;
+extern const CRegister f12; // arg
+extern const CRegister f13;
+extern const CRegister f14; // arg
+extern const CRegister f15;
+extern const CRegister f16;
+extern const CRegister f17;
+extern const CRegister f18;
+extern const CRegister f19;
+extern const CRegister f20;
+extern const CRegister f21;
+extern const CRegister f22;
+extern const CRegister f23;
+extern const CRegister f24;
+extern const CRegister f25;
+extern const CRegister f26;
+extern const CRegister f27;
+extern const CRegister f28;
+extern const CRegister f29;
+extern const CRegister f30;
+extern const CRegister f31;
+
+
+// Returns the equivalent of !cc.
+// Negation of the default no_condition (-1) results in a non-default
+// no_condition value (-2). As long as tests for no_condition check
+// for condition < 0, this will work as expected.
+inline Condition NegateCondition(Condition cc);
+
+inline Condition ReverseCondition(Condition cc) {
+ switch (cc) {
+ case Uless:
+ return Ugreater;
+ case Ugreater:
+ return Uless;
+ case Ugreater_equal:
+ return Uless_equal;
+ case Uless_equal:
+ return Ugreater_equal;
+ case less:
+ return greater;
+ case greater:
+ return less;
+ case greater_equal:
+ return less_equal;
+ case less_equal:
+ return greater_equal;
+ default:
+ return cc;
+ };
+}
+
+
+// TODO: Implement Hints or not ? Not used for arms.
+// Some kind of hints seem to exist on MIPS. See SMRL 8.5.8 (cf also p234 bot)
+enum Hint{
+ no_hint = 0
+};
+inline Hint NegateHint(Hint hint) {
+ return no_hint;
+}
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Operands
+
+// Class Operand represents a shifter operand in data processing instructions
+class Operand BASE_EMBEDDED {
+ public:
+ // immediate
+ INLINE(explicit Operand(int32_t immediate,
+ RelocInfo::Mode rmode = RelocInfo::NONE));
+ INLINE(explicit Operand(const ExternalReference& f));
+ INLINE(explicit Operand(const char* s));
+ INLINE(explicit Operand(Object** opp));
+ INLINE(explicit Operand(Context** cpp));
+ explicit Operand(Handle<Object> handle);
+ INLINE(explicit Operand(Smi* value));
+
+ // reg
+ INLINE(explicit Operand(Register rm));
+
+ // Return true if this is a register operand.
+ INLINE(bool is_reg() const);
+
+ Register rm() const { return rm_; }
+
+ private:
+ Register rm_;
+ int32_t imm32_; // valid if rm_ == no_reg
+ RelocInfo::Mode rmode_;
+
+ friend class Assembler;
+};
+
+
+// On MIPS we have only one adressing mode with base_reg + offset for every kind
+// Class MemOperand represents a memory operand in load and store instructions
antonm 2010/01/21 13:10:45 Usually all comments are terminated with a dot (he
Alexandre 2010/01/22 23:08:42 Style issue fixed. On 2010/01/21 13:10:45, antonm
+class MemOperand : public Operand {
+
+ public:
+
+ explicit MemOperand(Register rn, int16_t offset = 0);
+
+ private:
+ int16_t offset_;
+
+ friend class Assembler;
+};
+
+
+class Assembler : public Malloced {
+ public:
+ // Create an assembler. Instructions and relocation information are emitted
+ // into a buffer, with the instructions starting from the beginning and the
+ // relocation information starting from the end of the buffer. See CodeDesc
+ // for a detailed comment on the layout (globals.h).
+ //
+ // If the provided buffer is NULL, the assembler allocates and grows its own
+ // buffer, and buffer_size determines the initial buffer size. The buffer is
+ // owned by the assembler and deallocated upon destruction of the assembler.
+ //
+ // If the provided buffer is not NULL, the assembler uses the provided buffer
+ // for code generation and assumes its size to be buffer_size. If the buffer
+ // is too small, a fatal error occurs. No deallocation of the buffer is done
+ // upon destruction of the assembler.
+ Assembler(void* buffer, int buffer_size);
+ ~Assembler();
+
+ // GetCode emits any pending (non-emitted) code and fills the descriptor
+ // desc. GetCode() is idempotent; it returns the same result if no other
+ // Assembler functions are invoked in between GetCode() calls.
+ void GetCode(CodeDesc* desc);
+
+ // Label operations & relative jumps (PPUM Appendix D)
+ //
+ // Takes a branch opcode (cc) and a label (L) and generates
+ // either a backward branch or a forward branch and links it
+ // to the label fixup chain. Usage:
+ //
+ // Label L; // unbound label
+ // j(cc, &L); // forward branch to unbound label
+ // bind(&L); // bind label to the current pc
+ // j(cc, &L); // backward branch to bound label
+ // bind(&L); // illegal: a label may be bound only once
+ //
+ // Note: The same Label can be used for forward and backward branches
+ // but it may be bound only once.
+ void bind(Label* L); // binds an unbound label L to the current code position
+
+ // Returns the branch offset to the given label from the current code position
+ // Links the label to the current position if it is still unbound
+ // Manages the jump elimination optimization if the second parameter is true.
+ int32_t branch_offset(Label* L, bool jump_elimination_allowed);
+
+ // Puts a labels target address at the given position.
+ // The high 8 bits are set to zero.
+ void label_at_put(Label* L, int at_offset);
+
+ // Size of an instruction.
+ static const int kInstrSize = sizeof(Instr);
+
+ // Difference between address of current opcode and target address offset.
+ static const int kBranchPCOffset = 4;
+
+ // Read/Modify the code target address in the branch/call instruction at pc.
+ static Address target_address_at(Address pc);
+ static void set_target_address_at(Address pc, Address target);
+
+ // This sets the branch destination (which gets loaded at the call address).
+ // This is for calls and branches within generated code.
+ inline static void set_target_at(Address instruction_payload,
+ Address target) {
+ set_target_address_at(instruction_payload, target);
+ }
+
+ // This sets the branch destination (which is in the instruction on x86).
antonm 2010/01/21 13:10:45 x86?
Alexandre 2010/01/22 23:08:42 Fixed. On 2010/01/21 13:10:45, antonm wrote:
+ // This is for calls and branches to runtime code.
+ inline static void set_external_target_at(Address instruction_payload,
+ Address target) {
+ set_target_address_at(instruction_payload, target);
+ }
+
+ static const int kCallTargetSize = 3 * kPointerSize;
+ static const int kExternalTargetSize = 3 * kPointerSize;
+
+ // Distance between the instruction referring to the address of the call
+ // target and the return address
+ static const int kCallTargetAddressOffset = 4 * kInstrSize;
+
+ // Distance between start of patched return sequence and the emitted address
+ // to jump to.
+ static const int kPatchReturnSequenceAddressOffset = kInstrSize;
+
+
+ // ---------------------------------------------------------------------------
+ // Code generation
+
+
+ // Insert the smallest number of nop instructions
+ // possible to align the pc offset to a multiple
+ // of m. m must be a power of 2 (>= 4).
+ void Align(int m);
+
+ //------- Branch and jump instructions --------
+ // We don't use likely variant of instructions
+ void b (int16_t offset);
+ void b (Label* L) { b(branch_offset(L, false)>>2); }
+ void bal (int16_t offset);
+ void bal (Label* L) { bal(branch_offset(L, false)>>2); }
+
+ void beq (Register rs, Register rt, int16_t offset);
+ void beq (Register rs, Register rt, Label* L) {beq(rs,rt,branch_offset(L, false)>>2);}
+// void beql (Register rs, Register rt, int16_t offset);
antonm 2010/01/21 13:10:45 maybe those commented out lines should be just rem
Alexandre 2010/01/22 23:08:42 I removed them. These likely variants of instructi
+ void bgez (Register rs, int16_t offset);
+ void bgezal (Register rs, int16_t offset);
+// void bgezall (Register rs, int16_t offset);
+// void bgezl (Register rs, int16_t offset);
+ void bgtz (Register rs, int16_t offset);
+// void bgtzl (Register rs, int16_t offset);
+ void blez (Register rs, int16_t offset);
+// void blezl (Register rs, int16_t offset);
+ void bltz (Register rs, int16_t offset);
+ void bltzal (Register rs, int16_t offset);
+// void bltzall (Register rs, int16_t offset);
+ void bne (Register rs, Register rt, int16_t offset);
+ void bne (Register rs, Register rt, Label* L) {bne(rs,rt,branch_offset(L, false)>>2);}
+// void bnel (Register rs, Register rt, int16_t offset);
+
+// IMPORTANT NOTE: Never use the int16_t b(l)cond version with a branch offset
+// IMPORTANT NOTE: instead of using the Label* version. See Twiki for infos.
+ // Emulated conditionnal branch instructions calling the right branch instruction
+ void bcond(Condition cond, int16_t offset, Register rs = zero_reg,
+ const Operand& rt = Operand(zero_reg), Register scratch = at);
+ void bcond(Condition cond, Label* L, Register rs = zero_reg,
+ const Operand& rt = Operand(zero_reg), Register scratch = at);
+ // conditionnal branch and link
+ void blcond(Condition cond, int16_t offset, Register rs = zero_reg,
+ const Operand& rt = Operand(zero_reg), Register scratch = at);
+ void blcond(Condition cond, Label* L, Register rs = zero_reg,
+ const Operand& rt = Operand(zero_reg), Register scratch = at);
+
+ // Jump targets must be in the current 256 MB-aligned region. ie 28 bits.
+ void j (const Operand& target);
+ void jal (const Operand& target);
+ void jalr (Register rs, Register rd = ra);
+ void jalr (const Operand& rs, Register rd = ra);
+ void jalr_hb (const Operand& rs, Register rd = ra);
+ void jr (Register target);
+ void jr (const Operand& target);
+ void jr_hb(const Operand& target);
+
+// INLINE(void jalr (Register rs);)
+// INLINE(void jalr_hb (Register rs);)
+// INLINE(void jalr (Register rs) { jalr(ra, rs); })
+// INLINE(void jalr_hb (Register rs) { jalr_hb(ra, rs); })
+
+ // Automatically calls immediate or register j/jl versions.
+ void jcond(const Operand& target, Condition cond, Register rs, const Operand& rt);
+ void jalcond(const Operand& target, Condition cond, Register rs, const Operand& rt);
+
+
+ //-------Data-processing-instructions---------
+
+ // Arithmetic
+ void add(Register rd, Register rs, const Operand& rt);
+ void add(Register rd, Register rs, Register rt) {add(rd, rs, Operand(rt));}
+ void add(Register rd, const Operand& rt) { add(rd, rd, rt); }
+ void addi(Register rd, Register rs, const Operand& rt);
+ void addi(Register rd, Register rs, int32_t rt) {addi(rd, rs, Operand(rt));}
+ void addi(Register rd, const Operand& rt) { addi(rd, rd, rt); }
+ void addu(Register rd, Register rs, const Operand& rt);
+ void addu(Register rd, Register rs, Register rt) {addu(rd, rs, Operand(rt));}
+ void addu(Register rd, const Operand& rt) { addu(rd, rd, rt); }
+ void addiu(Register rd, Register rs, const Operand& rt);
+ void addiu(Register rd, Register rs, int32_t rt) {addiu(rd, rs, Operand(rt));}
+ void addiu(Register rd, const Operand& rt) { addiu(rd, rd, rt); }
+
+ void sub(Register rd, Register rs, const Operand& rt);
+ void subu(Register rd, Register rs, const Operand& rt);
+
+ void mult(Register rs, const Operand& rt);
+ void multu(Register rs, const Operand& rt);
+ void div(Register rs, const Operand& rt);
+ void divu(Register rs, const Operand& rt);
+
+ void mul(Register rd, Register rs, const Operand& rt);
+
+ // Logical
+ void and_(Register rd, Register rs, const Operand& rt);
+ void and_(Register rd, const Operand& rt) { and_(rd, rd, rt); }
+ void andi(Register rd, Register rs, const Operand& rt);
+ void andi(Register rd, const Operand& rt) { andi(rd, rd, rt); }
+ void or_(Register rd, Register rs, const Operand& rt);
+ void or_(Register rd, const Operand& rt) { or_(rd, rd, rt); }
+ void ori(Register rd, Register rs, const Operand& rt);
+ void ori(Register rd, Register rs, uint32_t rt) { ori(rd, rs, Operand(rt)); }
+ void ori(Register rd, const Operand& rt) { ori(rd, rd, rt); }
+ void xor_(Register rd, Register rs, const Operand& rt);
+ void xor_(Register rd, const Operand& rt) { xor_(rd, rd, rt); }
+ void xori(Register rd, Register rs, const Operand& rt);
+ void xori(Register rd, const Operand& rt) { xori(rd, rd, rt); }
+ void nor(Register rd, Register rs, const Operand& rt);
+ void nor(Register rd, const Operand& rt) { nor(rd, rd, rt); }
+
+ // Shifts
+ void sll(Register rd, Register rt, uint16_t sa);
+ void sllv(Register rd, Register rt, Register rs);
+ void srl(Register rd, Register rt, uint16_t sa);
+ void srlv(Register rd, Register rt, Register rs);
+ void sra(Register rt, Register rd, uint16_t sa);
+ void srav(Register rt, Register rd, Register rs);
+
+
+ //------------Memory-instructions-------------
+
+ void lb(Register rd, const MemOperand& rs);
+ void lbu(Register rd, const MemOperand& rs);
+ void lw(Register rd, const MemOperand& rs);
+ void sb(Register rd, const MemOperand& rs);
+ void sw(Register rd, const MemOperand& rs);
+ void lui(Register rd, uint16_t j);
+
+
+ //-------------Misc-instructions--------------
+
+ // Break / Trap instructions
+ void break_(uint32_t code);
+ void tge (Register rs, Register rt, uint16_t code);
+ void tgeu (Register rs, Register rt, uint16_t code);
+ void tlt (Register rs, Register rt, uint16_t code);
+ void tltu (Register rs, Register rt, uint16_t code);
+ void teq (Register rs, Register rt, uint16_t code);
+ void tne (Register rs, Register rt, uint16_t code);
+
+ // Move from HI/LO register
+ void mfhi(Register rd);
+ void mflo(Register rd);
+
+ // Set on less than
+ void slt (Register rd, Register rs, const Operand& rt);
+ void slt (Register rd, Register rs, Register rt) {slt(rd, rs, Operand(rt)); }
+ void sltu (Register rd, Register rs, const Operand& rt);
+ void sltu (Register rd, Register rs, Register rt) {sltu(rd, rs, Operand(rt));}
+ void slti (Register rd, Register rs, const Operand& rt);
+ void sltiu(Register rd, Register rs, const Operand& rt);
+
+
+ //--------Coprocessor-instructions----------------
+
+ // Load, store, and move
+ void lwc1(CRegister fd, const MemOperand& src);
+ void ldc1(CRegister fd, const MemOperand& src);
+
+ void swc1(CRegister fs, const MemOperand& dst);
+ void sdc1(CRegister fs, const MemOperand& dst);
+
+ void mtc1 (CRegister fs, Register rt);
+ void mthc1(CRegister fs, Register rt);
+ void mfc1 (CRegister fs, Register rt);
+ void mfhc1(CRegister fs, Register rt);
+
+ // Conversion
+ void cvt_w_s(CRegister fd, CRegister fs);
+ void cvt_w_d(CRegister fd, CRegister fs);
+
+ void cvt_l_s(CRegister fd, CRegister fs);
+ void cvt_l_d(CRegister fd, CRegister fs);
+
+ void cvt_s_w(CRegister fd, CRegister fs);
+ void cvt_s_l(CRegister fd, CRegister fs);
+ void cvt_s_d(CRegister fd, CRegister fs);
+
+ void cvt_d_w(CRegister fd, CRegister fs);
+ void cvt_d_l(CRegister fd, CRegister fs);
+ void cvt_d_s(CRegister fd, CRegister fs);
+
+ // Conditions and branches
+ void c(C_Condition cond, SecondaryField fmt,
+ CRegister ft, CRegister fs, uint16_t cc = 0);
+
+ void bc1f(int16_t offset, uint16_t cc = 0);
+ void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); }
+ void bc1t(int16_t offset, uint16_t cc = 0);
+ void bc1t(Label* L, uint16_t cc = 0) { bc1t(branch_offset(L, false)>>2, cc); }
+
+ //------------Pseudo-instructions-------------
+
+ void nop() { sll(zero_reg, zero_reg, 0); }
+ void mov(Register rd, Register rt) { or_(rd, rt, Operand(zero_reg)); }
+ // Move the logical ones complement of source to dest.
+ void movn(Register rd, Register rt);
+
+
+ // Push multiple registers on the stack.
+ // With multi_push, lower registers are pushed first on the stack.
+ // For example if you push t0, t1, s0, and ra you get:
+ // | |
+ // |-----------------------|
+ // | t0 | +
+ // |-----------------------| |
+ // | t1 | |
+ // |-----------------------| |
+ // | s0 | v
+ // |-----------------------| -
+ // | ra |
+ // |-----------------------|
+ // | |
+ void multi_push(RegList regs);
+ void multi_push_reversed(RegList regs);
+ void push(Register src) {
+ addiu(sp, Operand(-kPointerSize));
+ sw(src, MemOperand(sp, 0));
+ }
+
+ void push(Register src, Condition cond, Register tst1, Register tst2) {
+ // Since we don't have conditionnal execution we use a branch.
+ bcond(cond, 3, tst1, Operand(tst2));
+ nop();
+ addiu(sp, sp, Operand(-kPointerSize));
+ sw(src, MemOperand(sp, 0));
+ }
+
+ // Pops multiple values from the stack and load them in the
+ // registers specified in regs. Pop order is the opposite as in multi_push.
+ void multi_pop(RegList regs);
+ void multi_pop_reversed(RegList regs);
+ void pop(Register dst) {
+ lw(dst, MemOperand(sp, 0));
+ addiu(sp, Operand(kPointerSize));
+ }
+ void pop() {
+ add(sp, sp, Operand(kPointerSize));
+ }
+
+ // load uint32 in the rd register
+ void li(Register rd, Operand j, bool gen2instr = false);
+ void lrdi32(Register rd, Operand j) { li(rd, j); }
+
+ // Exception-generating instructions and debugging support
+ void stop(const char* msg);
+
+ // Jump unconditionally to given label.
+ // We NEED a nop in the branch delay slot, as it used by v8, for example in
+ // CodeGenerator::ProcessDeferred().
+ // Use rather b(Label) for code generation.
+ void jmp(Label* L) {
+ bcond(cc_always, L);
+ nop();
+ }
+
+
+ // Check the code size generated from label to here.
+ int InstructionsGeneratedSince(Label* l) {
+ return (pc_offset() - l->pos()) / kInstrSize;
+ }
+
+ // Debugging
+
+ // Mark address of the ExitJSFrame code.
+ void RecordJSReturn();
+
+ // Record a comment relocation entry that can be used by a disassembler.
+ // Use --debug_code to enable.
+ void RecordComment(const char* msg);
+
+ void RecordPosition(int pos);
+ void RecordStatementPosition(int pos);
+ void WriteRecordedPositions();
+
+ int32_t pc_offset() const { return pc_ - buffer_; }
+ int32_t current_position() const { return current_position_; }
+ int32_t current_statement_position() const { return current_position_; }
+
+ // Check if there is less than kGap bytes available in the buffer.
+ // If this is the case, we need to grow the buffer before emitting
+ // an instruction or relocation information.
+ inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
+
+ // Get the number of bytes available in the buffer.
+ inline int available_space() const { return reloc_info_writer.pos() - pc_; }
+
+ protected:
+ int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
+
+ // Read/patch instructions
+ static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
+ void instr_at_put(byte* pc, Instr instr) {
+ *reinterpret_cast<Instr*>(pc) = instr;
+ }
+ Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
+ void instr_at_put(int pos, Instr instr) {
+ *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
+ }
+
+ // Check if an instruction is a branch of some kind.
+ bool is_branch(Instr instr);
+
+ // Decode branch instruction at pos and return branch target pos
+ int target_at(int32_t pos);
+
+ // Patch branch instruction at pos to branch to given branch target pos
+ void target_at_put(int32_t pos, int32_t target_pos);
+
+ private:
+ // Code buffer:
+ // The buffer into which code and relocation info are generated.
+ byte* buffer_;
+ int buffer_size_;
+ // True if the assembler owns the buffer, false if buffer is external.
+ bool own_buffer_;
+
+ // Buffer size and constant pool distance are checked together at regular
+ // intervals of kBufferCheckInterval emitted bytes
+ static const int kBufferCheckInterval = 1*KB/2;
+
+ // Code generation
+ // The relocation writer's position is at least kGap bytes Uless the end of
+ // the generated instructions. This is so that multi-instruction sequences do
+ // not have to check for overflow. The same is true for writes of large
+ // relocation info entries.
+ static const int kGap = 32;
+ byte* pc_; // the program counter; moves forward
+
+ // Relocation information generation
+ // Each relocation is encoded as a variable size value
+ static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
+ RelocInfoWriter reloc_info_writer;
+
+ // The bound position, before this we cannot do instruction elimination.
+ int last_bound_pos_;
+
+ // source position information
+ int current_position_;
+ int current_statement_position_;
+ int written_position_;
+ int written_statement_position_;
+
+ // Code emission
+ inline void CheckBuffer();
+ void GrowBuffer();
+ inline void emit(Instr x);
+
+ // Instruction generation
+ // We have 3 different kind of encoding layout on MIPS.
+ // However due to many different types of objects encoded in the same fields
+ // we have quite a few aliases for each mode.
+ // Using the same structure to refer to Register and CRegister would spare a
+ // few aliases, but mixing both does not look clean to me.
+ // Anyway we could surely implement this differently.
+
+ void instrmod1(Opcode opcode,
+ Register r1,
+ Register r2,
+ Register r3,
+ uint16_t sa = 0,
+ SecondaryField func = NULLSF);
+
+ void instrmod1(Opcode opcode,
+ SecondaryField fmt,
+ CRegister ft,
+ CRegister fs,
+ CRegister fd,
+ SecondaryField func = NULLSF);
+
+ void instrmod1(Opcode opcode,
+ SecondaryField fmt,
+ Register rt,
+ CRegister fs,
+ CRegister fd,
+ SecondaryField func = NULLSF);
+
+
+ void instrmod2(Opcode opcode,
+ Register r1,
+ Register r2,
+ int16_t j);
+ void instrmod2(Opcode opcode,
+ Register r1,
+ Register r2,
+ uint16_t j);
+ void instrmod2(Opcode opcode,
+ Register r1,
+ SecondaryField SF,
+ int16_t j);
+ void instrmod2(Opcode opcode,
+ Register r1,
+ SecondaryField SF,
+ uint16_t j);
+
+ void instrmod2(Opcode opcode,
+ Register r1,
+ CRegister r2,
+ int16_t j);
+
+
+ void instrmod3(Opcode opcode,
+ Register r1,
+ uint32_t address);
+
+
+ // Labels
+ void print(Label* L);
+ void bind_to(Label* L, int pos);
+ void link_to(Label* L, Label* appendix);
+ void next(Label* L);
+
+ // Record reloc info for current pc_
+ void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
+
+ friend class RegExpMacroAssemblerARM;
+ friend class RelocInfo;
+ friend class CodePatcher;
+};
+
+} } // namespace v8::internal
+
+#endif // V8_ARM_ASSEMBLER_ARM_H_

Powered by Google App Engine
This is Rietveld 408576698