| Index: runtime/vm/assembler_arm.h
|
| ===================================================================
|
| --- runtime/vm/assembler_arm.h (revision 17773)
|
| +++ runtime/vm/assembler_arm.h (working copy)
|
| @@ -10,55 +10,11 @@
|
| #endif
|
|
|
| #include "platform/assert.h"
|
| +#include "platform/utils.h"
|
| #include "vm/constants_arm.h"
|
|
|
| namespace dart {
|
|
|
| -class Operand : public ValueObject {
|
| - public:
|
| - Operand(const Operand& other) : ValueObject() {
|
| - UNIMPLEMENTED();
|
| - }
|
| -
|
| - Operand& operator=(const Operand& other) {
|
| - UNIMPLEMENTED();
|
| - return *this;
|
| - }
|
| -
|
| - protected:
|
| - Operand() { } // Needed by subclass Address.
|
| -};
|
| -
|
| -
|
| -class Address : public Operand {
|
| - public:
|
| - Address(Register base, int32_t disp) {
|
| - UNIMPLEMENTED();
|
| - }
|
| -
|
| - Address(const Address& other) : Operand(other) { }
|
| -
|
| - Address& operator=(const Address& other) {
|
| - Operand::operator=(other);
|
| - return *this;
|
| - }
|
| -};
|
| -
|
| -
|
| -class FieldAddress : public Address {
|
| - public:
|
| - FieldAddress(Register base, int32_t disp)
|
| - : Address(base, disp - kHeapObjectTag) { }
|
| -
|
| - FieldAddress(const FieldAddress& other) : Address(other) { }
|
| -
|
| - FieldAddress& operator=(const FieldAddress& other) {
|
| - Address::operator=(other);
|
| - return *this;
|
| - }
|
| -};
|
| -
|
| -
|
| class Label : public ValueObject {
|
| public:
|
| Label() : position_(0) { }
|
| @@ -113,38 +69,219 @@
|
| };
|
|
|
|
|
| -class Assembler : public ValueObject {
|
| +// Encodes Addressing Mode 1 - Data-processing operands.
|
| +class ShifterOperand : public ValueObject {
|
| public:
|
| - Assembler() { UNIMPLEMENTED(); }
|
| - ~Assembler() { }
|
| + // Data-processing operands - Uninitialized.
|
| + ShifterOperand() : type_(-1) { }
|
|
|
| - void PopRegister(Register r) {
|
| - UNIMPLEMENTED();
|
| + // Data-processing operands - Copy constructor.
|
| + ShifterOperand(const ShifterOperand& other)
|
| + : ValueObject(), type_(other.type_), encoding_(other.encoding_) { }
|
| +
|
| + // Data-processing operands - Assignment operator.
|
| + ShifterOperand& operator=(const ShifterOperand& other) {
|
| + type_ = other.type_;
|
| + encoding_ = other.encoding_;
|
| + return *this;
|
| }
|
|
|
| - void Bind(Label* label) {
|
| - UNIMPLEMENTED();
|
| + // Data-processing operands - Immediate.
|
| + explicit ShifterOperand(uint32_t immediate) {
|
| + ASSERT(immediate < (1 << kImmed8Bits));
|
| + type_ = 1;
|
| + encoding_ = immediate;
|
| }
|
|
|
| - // Misc. functionality
|
| - int CodeSize() const {
|
| - UNIMPLEMENTED();
|
| - return 0;
|
| + // Data-processing operands - Rotated immediate.
|
| + ShifterOperand(uint32_t rotate, uint32_t immed8) {
|
| + ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
|
| + type_ = 1;
|
| + encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
|
| }
|
| - int prologue_offset() const {
|
| - UNIMPLEMENTED();
|
| - return 0;
|
| +
|
| + // Data-processing operands - Register.
|
| + explicit ShifterOperand(Register rm) {
|
| + type_ = 0;
|
| + encoding_ = static_cast<uint32_t>(rm);
|
| }
|
| +
|
| + // Data-processing operands - Logical shift/rotate by immediate.
|
| + ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) {
|
| + ASSERT(shift_imm < (1 << kShiftImmBits));
|
| + type_ = 0;
|
| + encoding_ = shift_imm << kShiftImmShift |
|
| + static_cast<uint32_t>(shift) << kShiftShift |
|
| + static_cast<uint32_t>(rm);
|
| + }
|
| +
|
| + // Data-processing operands - Logical shift/rotate by register.
|
| + ShifterOperand(Register rm, Shift shift, Register rs) {
|
| + type_ = 0;
|
| + encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift |
|
| + static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) |
|
| + static_cast<uint32_t>(rm);
|
| + }
|
| +
|
| + static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) {
|
| + // Avoid the more expensive test for frequent small immediate values.
|
| + if (immediate < (1 << kImmed8Bits)) {
|
| + shifter_op->type_ = 1;
|
| + shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift);
|
| + return true;
|
| + }
|
| + // Note that immediate must be unsigned for the test to work correctly.
|
| + for (int rot = 0; rot < 16; rot++) {
|
| + uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot));
|
| + if (imm8 < (1 << kImmed8Bits)) {
|
| + shifter_op->type_ = 1;
|
| + shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + private:
|
| + bool is_valid() const { return (type_ == 0) || (type_ == 1); }
|
| +
|
| + uint32_t type() const {
|
| + ASSERT(is_valid());
|
| + return type_;
|
| + }
|
| +
|
| + uint32_t encoding() const {
|
| + ASSERT(is_valid());
|
| + return encoding_;
|
| + }
|
| +
|
| + uint32_t type_; // Encodes the type field (bits 27-25) in the instruction.
|
| + uint32_t encoding_;
|
| +
|
| + friend class Assembler;
|
| +};
|
| +
|
| +
|
| +enum LoadOperandType {
|
| + kLoadSignedByte,
|
| + kLoadUnsignedByte,
|
| + kLoadSignedHalfword,
|
| + kLoadUnsignedHalfword,
|
| + kLoadWord,
|
| + kLoadWordPair,
|
| + kLoadSWord,
|
| + kLoadDWord
|
| +};
|
| +
|
| +
|
| +enum StoreOperandType {
|
| + kStoreByte,
|
| + kStoreHalfword,
|
| + kStoreWord,
|
| + kStoreWordPair,
|
| + kStoreSWord,
|
| + kStoreDWord
|
| +};
|
| +
|
| +
|
| +// Load/store multiple addressing mode.
|
| +enum BlockAddressMode {
|
| + // bit encoding P U W
|
| + DA = (0|0|0) << 21, // decrement after
|
| + IA = (0|4|0) << 21, // increment after
|
| + DB = (8|0|0) << 21, // decrement before
|
| + IB = (8|4|0) << 21, // increment before
|
| + DA_W = (0|0|1) << 21, // decrement after with writeback to base
|
| + IA_W = (0|4|1) << 21, // increment after with writeback to base
|
| + DB_W = (8|0|1) << 21, // decrement before with writeback to base
|
| + IB_W = (8|4|1) << 21 // increment before with writeback to base
|
| +};
|
| +
|
| +
|
| +class Address : public ValueObject {
|
| + public:
|
| + // Memory operand addressing mode
|
| + enum Mode {
|
| + // bit encoding P U W
|
| + Offset = (8|4|0) << 21, // offset (w/o writeback to base)
|
| + PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
|
| + PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
|
| + NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base)
|
| + NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
|
| + NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
|
| + };
|
| +
|
| + Address(const Address& other) : ValueObject(), encoding_(other.encoding_) { }
|
| +
|
| + Address& operator=(const Address& other) {
|
| + encoding_ = other.encoding_;
|
| + return *this;
|
| + }
|
| +
|
| + explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
|
| + ASSERT(Utils::IsAbsoluteUint(12, offset));
|
| + if (offset < 0) {
|
| + encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign.
|
| + } else {
|
| + encoding_ = am | offset;
|
| + }
|
| + encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
|
| + }
|
| +
|
| + static bool CanHoldLoadOffset(LoadOperandType type, int offset);
|
| + static bool CanHoldStoreOffset(StoreOperandType type, int offset);
|
| +
|
| + private:
|
| + uint32_t encoding() const { return encoding_; }
|
| +
|
| + // Encoding for addressing mode 3.
|
| + uint32_t encoding3() const;
|
| +
|
| + // Encoding for vfp load/store addressing.
|
| + uint32_t vencoding() const;
|
| +
|
| + uint32_t encoding_;
|
| +
|
| + friend class Assembler;
|
| +};
|
| +
|
| +
|
| +class FieldAddress : public Address {
|
| + public:
|
| + FieldAddress(Register base, int32_t disp)
|
| + : Address(base, disp - kHeapObjectTag) { }
|
| +
|
| + FieldAddress(const FieldAddress& other) : Address(other) { }
|
| +
|
| + FieldAddress& operator=(const FieldAddress& other) {
|
| + Address::operator=(other);
|
| + return *this;
|
| + }
|
| +};
|
| +
|
| +
|
| +class Assembler : public ValueObject {
|
| + public:
|
| + Assembler() : buffer_(), prologue_offset_(-1), comments_() { }
|
| + ~Assembler() { }
|
| +
|
| + void PopRegister(Register r) { Pop(r); }
|
| +
|
| + void Bind(Label* label);
|
| +
|
| + // Misc. functionality
|
| + int CodeSize() const { return buffer_.Size(); }
|
| + int prologue_offset() const { return prologue_offset_; }
|
| const ZoneGrowableArray<int>& GetPointerOffsets() const {
|
| - UNIMPLEMENTED();
|
| - return *pointer_offsets_;
|
| + return buffer_.pointer_offsets();
|
| }
|
| +
|
| void FinalizeInstructions(const MemoryRegion& region) {
|
| - UNIMPLEMENTED();
|
| + buffer_.FinalizeInstructions(region);
|
| }
|
|
|
| // Debugging and bringup support.
|
| - void Stop(const char* message) { UNIMPLEMENTED(); }
|
| + void Stop(const char* message);
|
| void Unimplemented(const char* message);
|
| void Untested(const char* message);
|
| void Unreachable(const char* message);
|
| @@ -153,14 +290,9 @@
|
| UNIMPLEMENTED();
|
| }
|
|
|
| - void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
|
| - UNIMPLEMENTED();
|
| - }
|
| + void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
|
|
| - const Code::Comments& GetCodeComments() const {
|
| - UNIMPLEMENTED();
|
| - return Code::Comments::New(0);
|
| - }
|
| + const Code::Comments& GetCodeComments() const;
|
|
|
| static const char* RegisterName(Register reg) {
|
| UNIMPLEMENTED();
|
| @@ -172,8 +304,327 @@
|
| return NULL;
|
| }
|
|
|
| + // Data-processing instructions.
|
| + void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| + void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| + void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void tst(Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void teq(Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void cmp(Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void cmn(Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| + void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void mov(Register rd, ShifterOperand so, Condition cond = AL);
|
| + void movs(Register rd, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
|
| +
|
| + void mvn(Register rd, ShifterOperand so, Condition cond = AL);
|
| + void mvns(Register rd, ShifterOperand so, Condition cond = AL);
|
| +
|
| + // Miscellaneous data-processing instructions.
|
| + void clz(Register rd, Register rm, Condition cond = AL);
|
| + void movw(Register rd, uint16_t imm16, Condition cond = AL);
|
| + void movt(Register rd, uint16_t imm16, Condition cond = AL);
|
| +
|
| + // Multiply instructions.
|
| + void mul(Register rd, Register rn, Register rm, Condition cond = AL);
|
| + void mla(Register rd, Register rn, Register rm, Register ra,
|
| + Condition cond = AL);
|
| + void mls(Register rd, Register rn, Register rm, Register ra,
|
| + Condition cond = AL);
|
| + void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
|
| + Condition cond = AL);
|
| +
|
| + // Load/store instructions.
|
| + void ldr(Register rd, Address ad, Condition cond = AL);
|
| + void str(Register rd, Address ad, Condition cond = AL);
|
| +
|
| + void ldrb(Register rd, Address ad, Condition cond = AL);
|
| + void strb(Register rd, Address ad, Condition cond = AL);
|
| +
|
| + void ldrh(Register rd, Address ad, Condition cond = AL);
|
| + void strh(Register rd, Address ad, Condition cond = AL);
|
| +
|
| + void ldrsb(Register rd, Address ad, Condition cond = AL);
|
| + void ldrsh(Register rd, Address ad, Condition cond = AL);
|
| +
|
| + void ldrd(Register rd, Address ad, Condition cond = AL);
|
| + void strd(Register rd, Address ad, Condition cond = AL);
|
| +
|
| + void ldm(BlockAddressMode am, Register base,
|
| + RegList regs, Condition cond = AL);
|
| + void stm(BlockAddressMode am, Register base,
|
| + RegList regs, Condition cond = AL);
|
| +
|
| + void ldrex(Register rd, Register rn, Condition cond = AL);
|
| + void strex(Register rd, Register rt, Register rn, Condition cond = AL);
|
| +
|
| + // Miscellaneous instructions.
|
| + void clrex();
|
| + void nop(Condition cond = AL);
|
| +
|
| + // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
|
| + void bkpt(uint16_t imm16);
|
| + void svc(uint32_t imm24);
|
| +
|
| + // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
|
| + void vmovsr(SRegister sn, Register rt, Condition cond = AL);
|
| + void vmovrs(Register rt, SRegister sn, Condition cond = AL);
|
| + void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
|
| + void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
|
| + void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL);
|
| + void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
|
| + void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
|
| +
|
| + // Returns false if the immediate cannot be encoded.
|
| + bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
|
| + bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
|
| +
|
| + void vldrs(SRegister sd, Address ad, Condition cond = AL);
|
| + void vstrs(SRegister sd, Address ad, Condition cond = AL);
|
| + void vldrd(DRegister dd, Address ad, Condition cond = AL);
|
| + void vstrd(DRegister dd, Address ad, Condition cond = AL);
|
| +
|
| + void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
|
| + void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
|
| + void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
|
| + void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
|
| + void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
|
| + void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
|
| + void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
|
| + void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
|
| + void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
|
| + void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
|
| + void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
|
| + void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
|
| +
|
| + void vabss(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
|
| + void vnegs(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vnegd(DRegister dd, DRegister dm, Condition cond = AL);
|
| + void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
|
| +
|
| + void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
|
| + void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
|
| + void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
|
| + void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
|
| + void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
|
| + void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
|
| +
|
| + void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
|
| + void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
|
| + void vcmpsz(SRegister sd, Condition cond = AL);
|
| + void vcmpdz(DRegister dd, Condition cond = AL);
|
| + void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
|
| +
|
| + // Branch instructions.
|
| + void b(Label* label, Condition cond = AL);
|
| + void bl(Label* label, Condition cond = AL);
|
| + void blx(Register rm, Condition cond = AL);
|
| +
|
| + // Macros.
|
| + // Branch to an entry address that can be patched at runtime.
|
| + void Branch(const ExternalLabel* label);
|
| + void BranchLink(const ExternalLabel* label);
|
| +
|
| + // Branch to entry after setting LR and storing LR at ad.
|
| + void BranchLinkStore(const ExternalLabel* label, Address ad);
|
| +
|
| + // Branch to [base + offset] after setting LR.
|
| + void BranchLinkOffset(Register base, int offset);
|
| +
|
| + // Add signed constant value to rd. May clobber IP.
|
| + void AddConstant(Register rd, int32_t value, Condition cond = AL);
|
| + void AddConstant(Register rd, Register rn, int32_t value,
|
| + Condition cond = AL);
|
| + void AddConstantSetFlags(Register rd, Register rn, int32_t value,
|
| + Condition cond = AL);
|
| + void AddConstantWithCarry(Register rd, Register rn, int32_t value,
|
| + Condition cond = AL);
|
| +
|
| + // Load and Store. May clobber IP.
|
| + void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
|
| + void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
|
| + void LoadDImmediate(DRegister dd, double value,
|
| + Register scratch, Condition cond = AL);
|
| + void MarkExceptionHandler(Label* label);
|
| + void LoadObject(Register rd, const Object& object);
|
| + void LoadFromOffset(LoadOperandType type,
|
| + Register reg,
|
| + Register base,
|
| + int32_t offset,
|
| + Condition cond = AL);
|
| + void StoreToOffset(StoreOperandType type,
|
| + Register reg,
|
| + Register base,
|
| + int32_t offset,
|
| + Condition cond = AL);
|
| + void LoadSFromOffset(SRegister reg,
|
| + Register base,
|
| + int32_t offset,
|
| + Condition cond = AL);
|
| + void StoreSToOffset(SRegister reg,
|
| + Register base,
|
| + int32_t offset,
|
| + Condition cond = AL);
|
| + void LoadDFromOffset(DRegister reg,
|
| + Register base,
|
| + int32_t offset,
|
| + Condition cond = AL);
|
| + void StoreDToOffset(DRegister reg,
|
| + Register base,
|
| + int32_t offset,
|
| + Condition cond = AL);
|
| +
|
| + void Push(Register rd, Condition cond = AL);
|
| + void Pop(Register rd, Condition cond = AL);
|
| +
|
| + void PushList(RegList regs, Condition cond = AL);
|
| + void PopList(RegList regs, Condition cond = AL);
|
| +
|
| + void Mov(Register rd, Register rm, Condition cond = AL);
|
| +
|
| + // Convenience shift instructions. Use mov instruction with shifter operand
|
| + // for variants setting the status flags or using a register shift count.
|
| + void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
|
| + void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
|
| + void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
|
| + void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
|
| + void Rrx(Register rd, Register rm, Condition cond = AL);
|
| +
|
| + // Emit data (e.g encoded instruction or immediate) in instruction stream.
|
| + void Emit(int32_t value);
|
| +
|
| private:
|
| + AssemblerBuffer buffer_;
|
| ZoneGrowableArray<int>* pointer_offsets_;
|
| + int prologue_offset_;
|
| +
|
| + class CodeComment : public ZoneAllocated {
|
| + public:
|
| + CodeComment(intptr_t pc_offset, const String& comment)
|
| + : pc_offset_(pc_offset), comment_(comment) { }
|
| +
|
| + intptr_t pc_offset() const { return pc_offset_; }
|
| + const String& comment() const { return comment_; }
|
| +
|
| + private:
|
| + intptr_t pc_offset_;
|
| + const String& comment_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CodeComment);
|
| + };
|
| +
|
| + GrowableArray<CodeComment*> comments_;
|
| +
|
| + void EmitType01(Condition cond,
|
| + int type,
|
| + Opcode opcode,
|
| + int set_cc,
|
| + Register rn,
|
| + Register rd,
|
| + ShifterOperand so);
|
| +
|
| + void EmitType5(Condition cond, int offset, bool link);
|
| +
|
| + void EmitMemOp(Condition cond,
|
| + bool load,
|
| + bool byte,
|
| + Register rd,
|
| + Address ad);
|
| +
|
| + void EmitMemOpAddressMode3(Condition cond,
|
| + int32_t mode,
|
| + Register rd,
|
| + Address ad);
|
| +
|
| + void EmitMultiMemOp(Condition cond,
|
| + BlockAddressMode am,
|
| + bool load,
|
| + Register base,
|
| + RegList regs);
|
| +
|
| + void EmitShiftImmediate(Condition cond,
|
| + Shift opcode,
|
| + Register rd,
|
| + Register rm,
|
| + ShifterOperand so);
|
| +
|
| + void EmitShiftRegister(Condition cond,
|
| + Shift opcode,
|
| + Register rd,
|
| + Register rm,
|
| + ShifterOperand so);
|
| +
|
| + void EmitMulOp(Condition cond,
|
| + int32_t opcode,
|
| + Register rd,
|
| + Register rn,
|
| + Register rm,
|
| + Register rs);
|
| +
|
| + void EmitVFPsss(Condition cond,
|
| + int32_t opcode,
|
| + SRegister sd,
|
| + SRegister sn,
|
| + SRegister sm);
|
| +
|
| + void EmitVFPddd(Condition cond,
|
| + int32_t opcode,
|
| + DRegister dd,
|
| + DRegister dn,
|
| + DRegister dm);
|
| +
|
| + void EmitVFPsd(Condition cond,
|
| + int32_t opcode,
|
| + SRegister sd,
|
| + DRegister dm);
|
| +
|
| + void EmitVFPds(Condition cond,
|
| + int32_t opcode,
|
| + DRegister dd,
|
| + SRegister sm);
|
| +
|
| + void EmitBranch(Condition cond, Label* label, bool link);
|
| + static int32_t EncodeBranchOffset(int offset, int32_t inst);
|
| + static int DecodeBranchOffset(int32_t inst);
|
| + int32_t EncodeTstOffset(int offset, int32_t inst);
|
| + int DecodeTstOffset(int32_t inst);
|
| +
|
| + // Returns whether or not the given register is used for passing parameters.
|
| + static int RegisterCompare(const Register* reg1, const Register* reg2) {
|
| + return *reg1 - *reg2;
|
| + }
|
| +
|
| DISALLOW_ALLOCATION();
|
| DISALLOW_COPY_AND_ASSIGN(Assembler);
|
| };
|
|
|