diff options
Diffstat (limited to 'compiler/utils/arm/assembler_arm.h')
-rw-r--r-- | compiler/utils/arm/assembler_arm.h | 715 |
1 files changed, 382 insertions, 333 deletions
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h index 396e60330b..7b662e1500 100644 --- a/compiler/utils/arm/assembler_arm.h +++ b/compiler/utils/arm/assembler_arm.h @@ -29,88 +29,118 @@ namespace art { namespace arm { -// Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1. class ShifterOperand { public: - // Data-processing operands - Uninitialized - ShifterOperand() { - type_ = -1; - encoding_ = 0; + ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister), + is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { } - // Data-processing operands - Immediate - explicit ShifterOperand(uint32_t immediate) { - CHECK(immediate < (1 << kImmed8Bits)); - type_ = 1; - encoding_ = immediate; + explicit ShifterOperand(uint32_t immed) : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister), + is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) { } - // Data-processing operands - Rotated immediate - ShifterOperand(uint32_t rotate, uint32_t immed8) { - CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits))); - type_ = 1; - encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift); + // Data-processing operands - Register + explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister), + is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { } - // Data-processing operands - Register - explicit ShifterOperand(Register rm) { - type_ = 0; - encoding_ = static_cast<uint32_t>(rm); + ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister), + rs_(kNoRegister), + is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) { } - // Data-processing operands - Logical shift/rotate by immediate - ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) { - CHECK(shift_imm < (1 << kShiftImmBits)); - type_ = 0; - encoding_ = shift_imm << kShiftImmShift | - static_cast<uint32_t>(shift) << kShiftShift | - static_cast<uint32_t>(rm); + ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm), + rs_(kNoRegister), + is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) { } // 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); + ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm), + rs_(rs), + is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) { + } + + bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); } + + uint32_t type() const { + CHECK(is_valid()); + return type_; } - static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) { + uint32_t encodingArm() const; + uint32_t encodingThumb(int version) const; + + bool IsEmpty() const { + return type_ == kUnknown; + } + + bool IsImmediate() const { + return type_ == kImmediate; + } + + bool IsRegister() const { + return type_ == kRegister; + } + + bool IsShift() const { + return is_shift_; + } + + uint32_t GetImmediate() const { + return immed_; + } + + Shift GetShift() const { + return shift_; + } + + Register GetRegister() const { + return rm_; + } + + enum Type { + kUnknown = -1, + kRegister, + kImmediate + }; + + static bool CanHoldArm(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); + shifter_op->type_ = kImmediate; + shifter_op->is_rotate_ = true; + shifter_op->rotate_ = 0; + shifter_op->immed_ = immediate; 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); + shifter_op->type_ = kImmediate; + shifter_op->is_rotate_ = true; + shifter_op->rotate_ = rot; + shifter_op->immed_ = imm8; return true; } } return false; } - private: - bool is_valid() const { return (type_ == 0) || (type_ == 1); } + static bool CanHoldThumb(Register rd, Register rn, Opcode opcode, + uint32_t immediate, ShifterOperand* shifter_op); - uint32_t type() const { - CHECK(is_valid()); - return type_; - } - uint32_t encoding() const { - CHECK(is_valid()); - return encoding_; - } - - uint32_t type_; // Encodes the type field (bits 27-25) in the instruction. - uint32_t encoding_; + private: + Type type_; + Register rm_; + Register rs_; + bool is_rotate_; + bool is_shift_; + Shift shift_; + uint32_t rotate_; + uint32_t immed_; - friend class ArmAssembler; #ifdef SOURCE_ASSEMBLER_SUPPORT friend class BinaryAssembler; #endif @@ -152,10 +182,10 @@ enum BlockAddressMode { IB_W = (8|4|1) << 21 // increment before with writeback to base }; - class Address { public: - // Memory operand addressing mode + // Memory operand addressing mode (in ARM encoding form. For others we need + // to adjust) enum Mode { // bit encoding P U W Offset = (8|4|0) << 21, // offset (w/o writeback to base) @@ -166,273 +196,366 @@ class Address { NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback }; - explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) { - CHECK(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; + explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), offset_(offset), + am_(am) { } - static bool CanHoldLoadOffset(LoadOperandType type, int offset); - static bool CanHoldStoreOffset(StoreOperandType type, int offset); + static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset); + static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset); - private: - uint32_t encoding() const { return encoding_; } - - // Encoding for addressing mode 3. - uint32_t encoding3() const { - const uint32_t offset_mask = (1 << 12) - 1; - uint32_t offset = encoding_ & offset_mask; - CHECK_LT(offset, 256u); - return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf); + static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset); + static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset); + + uint32_t encodingArm() const; + uint32_t encodingThumb(int version) const; + + uint32_t encoding3() const; + uint32_t vencoding() const; + + uint32_t encodingThumbLdrdStrd() const; + + Register GetRegister() const { + return rn_; } - // Encoding for vfp load/store addressing. - uint32_t vencoding() const { - const uint32_t offset_mask = (1 << 12) - 1; - uint32_t offset = encoding_ & offset_mask; - CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020. - CHECK_ALIGNED(offset, 2); // Multiple of 4. - int mode = encoding_ & ((8|4|1) << 21); - CHECK((mode == Offset) || (mode == NegOffset)); - uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2); - if (mode == Offset) { - vencoding |= 1 << 23; - } - return vencoding; + int32_t GetOffset() const { + return offset_; } - uint32_t encoding_; + Mode GetMode() const { + return am_; + } + + private: + Register rn_; + int32_t offset_; + Mode am_; +}; + +// Instruction encoding bits. +enum { + H = 1 << 5, // halfword (or byte) + L = 1 << 20, // load (or store) + S = 1 << 20, // set condition code (or leave unchanged) + W = 1 << 21, // writeback base register (or leave unchanged) + A = 1 << 21, // accumulate in multiply instruction (or not) + B = 1 << 22, // unsigned byte (or word) + N = 1 << 22, // long (or short) + U = 1 << 23, // positive (or negative) offset/index + P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) + I = 1 << 25, // immediate shifter operand (or not) + + B0 = 1, + B1 = 1 << 1, + B2 = 1 << 2, + B3 = 1 << 3, + B4 = 1 << 4, + B5 = 1 << 5, + B6 = 1 << 6, + B7 = 1 << 7, + B8 = 1 << 8, + B9 = 1 << 9, + B10 = 1 << 10, + B11 = 1 << 11, + B12 = 1 << 12, + B13 = 1 << 13, + B14 = 1 << 14, + B15 = 1 << 15, + B16 = 1 << 16, + B17 = 1 << 17, + B18 = 1 << 18, + B19 = 1 << 19, + B20 = 1 << 20, + B21 = 1 << 21, + B22 = 1 << 22, + B23 = 1 << 23, + B24 = 1 << 24, + B25 = 1 << 25, + B26 = 1 << 26, + B27 = 1 << 27, + B28 = 1 << 28, + B29 = 1 << 29, + B30 = 1 << 30, + B31 = 1 << 31, + + // Instruction bit masks. + RdMask = 15 << 12, // in str instruction + CondMask = 15 << 28, + CoprocessorMask = 15 << 8, + OpCodeMask = 15 << 21, // in data-processing instructions + Imm24Mask = (1 << 24) - 1, + Off12Mask = (1 << 12) - 1, + + // ldrex/strex register field encodings. + kLdExRnShift = 16, + kLdExRtShift = 12, + kStrExRnShift = 16, + kStrExRdShift = 12, + kStrExRtShift = 0, +}; - friend class ArmAssembler; +// IfThen state for IT instructions. +enum ItState { + kItOmitted, + kItThen, + kItT = kItThen, + kItElse, + kItE = kItElse }; +constexpr uint32_t kNoItCondition = 3; +constexpr uint32_t kInvalidModifiedImmediate = -1; -class ArmAssembler FINAL : public Assembler { +extern const char* kRegisterNames[]; +extern const char* kConditionNames[]; +extern std::ostream& operator<<(std::ostream& os, const Register& rhs); +extern std::ostream& operator<<(std::ostream& os, const SRegister& rhs); +extern std::ostream& operator<<(std::ostream& os, const DRegister& rhs); +extern std::ostream& operator<<(std::ostream& os, const Condition& rhs); + +// This is an abstract ARM assembler. Subclasses provide assemblers for the individual +// instruction sets (ARM32, Thumb2, etc.) +// +class ArmAssembler : public Assembler { public: - ArmAssembler() {} virtual ~ArmAssembler() {} + // Is this assembler for the thumb instruction set? + virtual bool IsThumb() const = 0; + // Data-processing instructions. - void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL); - void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; + virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL); - void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; + virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void tst(Register rn, ShifterOperand so, Condition cond = AL); + virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void teq(Register rn, ShifterOperand so, Condition cond = AL); + virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void cmp(Register rn, ShifterOperand so, Condition cond = AL); + virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void cmn(Register rn, ShifterOperand so, Condition cond = AL); + virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL); - void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; + virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void mov(Register rd, ShifterOperand so, Condition cond = AL); - void movs(Register rd, ShifterOperand so, Condition cond = AL); + virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; + virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; - void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL); + virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; - void mvn(Register rd, ShifterOperand so, Condition cond = AL); - void mvns(Register rd, ShifterOperand so, Condition cond = AL); + virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; + virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; // 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); + virtual void clz(Register rd, Register rm, Condition cond = AL) = 0; + virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0; + virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0; // 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); + virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0; + virtual void mla(Register rd, Register rn, Register rm, Register ra, + Condition cond = AL) = 0; + virtual void mls(Register rd, Register rn, Register rm, Register ra, + Condition cond = AL) = 0; + virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, + Condition cond = AL) = 0; + + virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0; + virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0; // Load/store instructions. - void ldr(Register rd, Address ad, Condition cond = AL); - void str(Register rd, Address ad, Condition cond = AL); + virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0; + virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0; - void ldrb(Register rd, Address ad, Condition cond = AL); - void strb(Register rd, Address ad, Condition cond = AL); + virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0; + virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0; - void ldrh(Register rd, Address ad, Condition cond = AL); - void strh(Register rd, Address ad, Condition cond = AL); + virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0; + virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0; - void ldrsb(Register rd, Address ad, Condition cond = AL); - void ldrsh(Register rd, Address ad, Condition cond = AL); + virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0; + virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0; - void ldrd(Register rd, Address ad, Condition cond = AL); - void strd(Register rd, Address ad, Condition cond = AL); + virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0; + virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0; - void ldm(BlockAddressMode am, Register base, - RegList regs, Condition cond = AL); - void stm(BlockAddressMode am, Register base, - RegList regs, Condition cond = AL); + virtual void ldm(BlockAddressMode am, Register base, + RegList regs, Condition cond = AL) = 0; + virtual void stm(BlockAddressMode am, Register base, + RegList regs, Condition cond = AL) = 0; - void ldrex(Register rd, Register rn, Condition cond = AL); - void strex(Register rd, Register rt, Register rn, Condition cond = AL); + virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0; + virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0; // Miscellaneous instructions. - void clrex(); - void nop(Condition cond = AL); + virtual void clrex(Condition cond = AL) = 0; + virtual void nop(Condition cond = AL) = 0; // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. - void bkpt(uint16_t imm16); - void svc(uint32_t imm24); + virtual void bkpt(uint16_t imm16) = 0; + virtual void svc(uint32_t imm24) = 0; + + virtual void it(Condition firstcond, ItState i1 = kItOmitted, + ItState i2 = kItOmitted, ItState i3 = kItOmitted) { + // Ignored if not supported. + } + + virtual void cbz(Register rn, Label* target) = 0; + virtual void cbnz(Register rn, Label* target) = 0; // 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); + virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0; + virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0; + virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0; + virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0; + virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0; + virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0; + virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0; // 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 + virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0; + virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0; + + virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0; + virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0; + virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0; + virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0; + + virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; + virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; + virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; + virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; + virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; + virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; + virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; + virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; + virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; + virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; + virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; + virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; + + virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0; + virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0; + virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0; + + virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0; + virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0; + virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0; + virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0; + virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0; + virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0; + + virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0; + virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0; + virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0; + virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0; + virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR + + virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0; + virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0; + virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0; + virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0; // Branch instructions. - void b(Label* label, Condition cond = AL); - void bl(Label* label, Condition cond = AL); - void blx(Register rm, Condition cond = AL); - void bx(Register rm, Condition cond = AL); + virtual void b(Label* label, Condition cond = AL) = 0; + virtual void bl(Label* label, Condition cond = AL) = 0; + virtual void blx(Register rm, Condition cond = AL) = 0; + virtual void bx(Register rm, Condition cond = AL) = 0; + + void Pad(uint32_t bytes); // Macros. + // Most of these are pure virtual as they need to be implemented per instruction set. + // 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); + virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0; + virtual void AddConstant(Register rd, Register rn, int32_t value, + Condition cond = AL) = 0; + virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value, + Condition cond = AL) = 0; + virtual void AddConstantWithCarry(Register rd, Register rn, int32_t value, + Condition cond = AL) = 0; // 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 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); + virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0; + virtual void LoadSImmediate(SRegister sd, float value, Condition cond = AL) = 0; + virtual void LoadDImmediate(DRegister dd, double value, + Register scratch, Condition cond = AL) = 0; + virtual void MarkExceptionHandler(Label* label) = 0; + virtual void LoadFromOffset(LoadOperandType type, + Register reg, + Register base, + int32_t offset, + Condition cond = AL) = 0; + virtual void StoreToOffset(StoreOperandType type, + Register reg, + Register base, + int32_t offset, + Condition cond = AL) = 0; + virtual void LoadSFromOffset(SRegister reg, + Register base, + int32_t offset, + Condition cond = AL) = 0; + virtual void StoreSToOffset(SRegister reg, + Register base, + int32_t offset, + Condition cond = AL) = 0; + virtual void LoadDFromOffset(DRegister reg, + Register base, + int32_t offset, + Condition cond = AL) = 0; + virtual void StoreDToOffset(DRegister reg, + Register base, + int32_t offset, + Condition cond = AL) = 0; + + virtual void Push(Register rd, Condition cond = AL) = 0; + virtual void Pop(Register rd, Condition cond = AL) = 0; + + virtual void PushList(RegList regs, Condition cond = AL) = 0; + virtual void PopList(RegList regs, Condition cond = AL) = 0; + + virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0; // 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); - - // Encode a signed constant in tst instructions, only affecting the flags. - void EncodeUint32InTstInstructions(uint32_t data); - // ... and decode from a pc pointing to the start of encoding instructions. - static uint32_t DecodeUint32FromTstInstructions(uword pc); + virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0; + virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0; + virtual void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0; + virtual void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) = 0; + virtual void Rrx(Register rd, Register rm, Condition cond = AL) = 0; + static bool IsInstructionForExceptionHandling(uword pc); - // Emit data (e.g. encoded instruction or immediate) to the - // instruction stream. - void Emit(int32_t value); - void Bind(Label* label); + virtual void Bind(Label* label) = 0; + + virtual void CompareAndBranchIfZero(Register r, Label* label) = 0; + virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0; // // Overridden common assembler high-level functionality @@ -445,7 +568,7 @@ class ArmAssembler FINAL : public Assembler { // Emit code that will remove an activation from the stack void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) - OVERRIDE; + OVERRIDE; void IncreaseFrameSize(size_t adjust) OVERRIDE; void DecreaseFrameSize(size_t adjust) OVERRIDE; @@ -509,8 +632,6 @@ class ArmAssembler FINAL : public Assembler { void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, ManagedRegister scratch, size_t size) OVERRIDE; - void MemoryBarrier(ManagedRegister scratch) OVERRIDE; - // Sign extension void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; @@ -550,81 +671,9 @@ class ArmAssembler FINAL : public Assembler { // and branch to a ExceptionSlowPath if it is. void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; - private: - 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); + static uint32_t ModifiedImmediate(uint32_t value); + protected: // Returns whether or not the given register is used for passing parameters. static int RegisterCompare(const Register* reg1, const Register* reg2) { return *reg1 - *reg2; |