| Index: src/arm/assembler-thumb2.h
|
| ===================================================================
|
| --- src/arm/assembler-thumb2.h (revision 3826)
|
| +++ src/arm/assembler-thumb2.h (working copy)
|
| @@ -30,9 +30,9 @@
|
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
| // OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| -// The original source code covered by the above license above has been modified
|
| +// The original source code covered by the above license has been modified
|
| // significantly by Google Inc.
|
| -// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
| +// Copyright 2010 the V8 project authors. All rights reserved.
|
|
|
| // A light-weight ARM Assembler
|
| // Generates user mode instructions for the ARM architecture up to version 5
|
| @@ -46,6 +46,138 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +// The beginning of this file contains some enum declarations that are
|
| +// redundant with declarations in constants-arm.h, but in a different namespace
|
| +// Please keep the order and values consistent, so we can merge the files
|
| +// later easily.
|
| +
|
| +// Opcodes for Data-processing instructions (instructions with a type 0 and 1)
|
| +// as defined in section A3.4
|
| +enum Opcode {
|
| + no_operand = -1,
|
| + AND = 0, // Logical AND
|
| + EOR = 1, // Logical Exclusive OR
|
| + SUB = 2, // Subtract
|
| + RSB = 3, // Reverse Subtract
|
| + ADD = 4, // Add
|
| + ADC = 5, // Add with Carry
|
| + SBC = 6, // Subtract with Carry
|
| + RSC = 7, // Reverse Subtract with Carry
|
| + TST = 8, // Test
|
| + TEQ = 9, // Test Equivalence
|
| + CMP = 10, // Compare
|
| + CMN = 11, // Compare Negated
|
| + ORR = 12, // Logical (inclusive) OR
|
| + MOV = 13, // Move
|
| + BIC = 14, // Bit Clear
|
| + MVN = 15, // Move Not
|
| + max_operand = 16
|
| +};
|
| +
|
| +enum BitPositions {
|
| + B0 = 1 << 0,
|
| + 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,
|
| + B16 = 1 << 16,
|
| + 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
|
| +};
|
| +
|
| +enum Bits1 {
|
| + b0 = 0x0,
|
| + b1 = 0x1
|
| +};
|
| +
|
| +enum Bits2 {
|
| + b00 = 0x0,
|
| + b01 = 0x1,
|
| + b10 = 0x2,
|
| + b11 = 0x3
|
| +};
|
| +
|
| +enum Bits3 {
|
| + b000 = 0x0,
|
| + b001 = 0x1,
|
| + b010 = 0x2,
|
| + b011 = 0x3,
|
| + b100 = 0x4,
|
| + b101 = 0x5,
|
| + b110 = 0x6,
|
| + b111 = 0x7
|
| +};
|
| +
|
| +enum Bits4 {
|
| + b0000 = 0x0,
|
| + b0001 = 0x1,
|
| + b0010 = 0x2,
|
| + b0011 = 0x3,
|
| + b0100 = 0x4,
|
| + b0101 = 0x5,
|
| + b0110 = 0x6,
|
| + b0111 = 0x7,
|
| + b1000 = 0x8,
|
| + b1001 = 0x9,
|
| + b1010 = 0xa,
|
| + b1011 = 0xb,
|
| + b1100 = 0xc,
|
| + b1101 = 0xd,
|
| + b1110 = 0xe,
|
| + b1111 = 0xf
|
| +};
|
| +
|
| +enum Bits5 {
|
| + b00000 = 0x00,
|
| + b00001 = 0x01,
|
| + b00010 = 0x02,
|
| + b00011 = 0x03,
|
| + b00100 = 0x04,
|
| + b00101 = 0x05,
|
| + b00110 = 0x06,
|
| + b00111 = 0x07,
|
| + b01000 = 0x08,
|
| + b01001 = 0x09,
|
| + b01010 = 0x0a,
|
| + b01011 = 0x0b,
|
| + b01100 = 0x0c,
|
| + b01101 = 0x0d,
|
| + b01110 = 0x0e,
|
| + b01111 = 0x0f,
|
| + b10000 = 0x10,
|
| + b10001 = 0x11,
|
| + b10010 = 0x12,
|
| + b10011 = 0x13,
|
| + b10100 = 0x14,
|
| + b10101 = 0x15,
|
| + b10110 = 0x16,
|
| + b10111 = 0x17,
|
| + b11000 = 0x18,
|
| + b11001 = 0x19,
|
| + b11010 = 0x1a,
|
| + b11011 = 0x1b,
|
| + b11100 = 0x1c,
|
| + b11101 = 0x1d,
|
| + b11110 = 0x1e,
|
| + b11111 = 0x1f
|
| +};
|
| +
|
| // CPU Registers.
|
| //
|
| // 1) We would prefer to use an enum, but enum values are assignment-
|
| @@ -250,7 +382,7 @@
|
| };
|
|
|
|
|
| -// Condition field in instructions
|
| +// Condition field in instructions.
|
| enum Condition {
|
| eq = 0 << 28, // Z set equal.
|
| ne = 1 << 28, // Z clear not equal.
|
| @@ -316,10 +448,10 @@
|
|
|
| // Shifter operand shift operation
|
| enum ShiftOp {
|
| - LSL = 0 << 5,
|
| - LSR = 1 << 5,
|
| - ASR = 2 << 5,
|
| - ROR = 3 << 5,
|
| + LSL = 0,
|
| + LSR = 1,
|
| + ASR = 2,
|
| + ROR = 3,
|
| RRX = -1
|
| };
|
|
|
| @@ -506,14 +638,16 @@
|
| static unsigned found_by_runtime_probing_;
|
| };
|
|
|
| +typedef int32_t InstrArm;
|
| +typedef int16_t InstrThumb;
|
|
|
| -typedef int32_t Instr;
|
| +// hack to keep the code patcher happy for now
|
| +typedef InstrArm Instr;
|
|
|
| +extern const InstrArm kMovLrPc;
|
| +extern const InstrArm kLdrPCPattern;
|
|
|
| -extern const Instr kMovLrPc;
|
| -extern const Instr kLdrPCPattern;
|
|
|
| -
|
| class Assembler : public Malloced {
|
| public:
|
| // Create an assembler. Instructions and relocation information are emitted
|
| @@ -589,15 +723,19 @@
|
| static const int kExternalTargetSize = kPointerSize;
|
|
|
| // Size of an instruction.
|
| + static const int kInstrArmSize = sizeof(InstrArm);
|
| + static const int kInstrThumbSize = sizeof(InstrThumb);
|
| + // Keep the code generator happy for now.
|
| static const int kInstrSize = sizeof(Instr);
|
|
|
| +
|
| // Distance between the instruction referring to the address of the call
|
| // target (ldr pc, [target addr in const pool]) and the return address
|
| - static const int kCallTargetAddressOffset = kInstrSize;
|
| + static const int kCallTargetAddressOffset = kInstrArmSize;
|
|
|
| // Distance between start of patched return sequence and the emitted address
|
| // to jump to.
|
| - static const int kPatchReturnSequenceAddressOffset = kInstrSize;
|
| + static const int kPatchReturnSequenceAddressOffset = kInstrArmSize;
|
|
|
| // Difference between address of current opcode and value read from pc
|
| // register.
|
| @@ -630,6 +768,9 @@
|
| void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
|
|
|
| // Data-processing instructions
|
| + void ubfx(Register dst, Register src1, const Operand& src2,
|
| + const Operand& src3, Condition cond = al);
|
| +
|
| void and_(Register dst, Register src1, const Operand& src2,
|
| SBit s = LeaveCC, Condition cond = al);
|
|
|
| @@ -796,6 +937,14 @@
|
| // However, some simple modifications can allow
|
| // these APIs to support D16 to D31.
|
|
|
| + void vldr(const DwVfpRegister dst,
|
| + const Register base,
|
| + int offset, // Offset must be a multiple of 4.
|
| + const Condition cond = al);
|
| + void vstr(const DwVfpRegister src,
|
| + const Register base,
|
| + int offset, // Offset must be a multiple of 4.
|
| + const Condition cond = al);
|
| void vmov(const DwVfpRegister dst,
|
| const Register src1,
|
| const Register src2,
|
| @@ -864,7 +1013,7 @@
|
|
|
| // Check the code size generated from label to here.
|
| int InstructionsGeneratedSince(Label* l) {
|
| - return (pc_offset() - l->pos()) / kInstrSize;
|
| + return (pc_offset() - l->pos()) / kInstrArmSize;
|
| }
|
|
|
| // Check whether an immediate fits an addressing mode 1 instruction.
|
| @@ -895,15 +1044,22 @@
|
| int 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;
|
| + static InstrArm instr_arm_at(byte* pc) {
|
| + return *reinterpret_cast<InstrArm*>(pc);
|
| }
|
| - 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;
|
| +
|
| + void instr_arm_at_put(byte* pc, InstrArm instr) {
|
| + *reinterpret_cast<InstrArm*>(pc) = instr;
|
| }
|
|
|
| + InstrArm instr_arm_at(int pos) {
|
| + return *reinterpret_cast<InstrArm*>(buffer_ + pos);
|
| + }
|
| +
|
| + void instr_arm_at_put(int pos, InstrArm instr) {
|
| + *reinterpret_cast<InstrArm*>(buffer_ + pos) = instr;
|
| + }
|
| +
|
| // Decode branch instruction at pos and return branch target pos
|
| int target_at(int pos);
|
|
|
| @@ -954,7 +1110,8 @@
|
| // has been generated. That also means that the sizing of the buffers is not
|
| // an exact science, and that we rely on some slop to not overrun buffers.
|
| static const int kCheckConstIntervalInst = 32;
|
| - static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
|
| + static const int kCheckConstInterval =
|
| + kCheckConstIntervalInst * kInstrArmSize;
|
|
|
|
|
| // Pools are emitted after function return and in dead code at (more or less)
|
| @@ -983,7 +1140,7 @@
|
| // stored in a separate buffer until a constant pool is emitted.
|
| // If every instruction in a long sequence is accessing the pool, we need one
|
| // pending relocation entry per instruction.
|
| - static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
|
| + static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrArmSize;
|
| RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info
|
| int num_prinfo_; // number of pending reloc info entries in the buffer
|
|
|
| @@ -995,19 +1152,32 @@
|
| int current_statement_position_;
|
| int written_position_;
|
| int written_statement_position_;
|
| + bool thumb_mode_;
|
|
|
| +
|
| // Code emission
|
| inline void CheckBuffer();
|
| + inline void EnsureThumbMode();
|
| + inline void EnsureArmMode();
|
| void GrowBuffer();
|
| - inline void emit(Instr x);
|
| + inline void emit_thumb(InstrThumb x);
|
| + inline void emit_arm(InstrArm x);
|
| + inline void emit_int32(int32_t x);
|
|
|
| - // Instruction generation
|
| - void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
|
| - void addrmod2(Instr instr, Register rd, const MemOperand& x);
|
| - void addrmod3(Instr instr, Register rd, const MemOperand& x);
|
| - void addrmod4(Instr instr, Register rn, RegList rl);
|
| - void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
|
| + // ARM Instruction generation
|
| + void addrmod1(InstrArm instr, Register rn, Register rd, const Operand& x);
|
| + void addrmod2(InstrArm instr, Register rd, const MemOperand& x);
|
| + void addrmod3(InstrArm instr, Register rd, const MemOperand& x);
|
| + void addrmod4(InstrArm instr, Register rn, RegList rl);
|
| + void addrmod5(InstrArm instr, CRegister crd, const MemOperand& x);
|
|
|
| + // Thumb2 Instruction generation
|
| + void DataProcessing(Condition cond, Opcode op, SBit s,
|
| + Register rn, Register rd, const Operand& x);
|
| + void DataProcessingReg(Opcode op, SBit s, Register rn, Register rd,
|
| + Register rm, ShiftOp shiftOp, int shiftBy);
|
| + void DataProcessingImm(Opcode op, SBit s, Register rn, Register rd, int imm);
|
| +
|
| // Labels
|
| void print(Label* L);
|
| void bind_to(Label* L, int pos);
|
|
|