| Index: src/arm/assembler-thumb2.h
|
| ===================================================================
|
| --- src/arm/assembler-thumb2.h (revision 4001)
|
| +++ src/arm/assembler-thumb2.h (working copy)
|
| @@ -46,6 +46,64 @@
|
| 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,
|
| + B13 = 1 << 13,
|
| + B14 = 1 << 14,
|
| + B15 = 1 << 15,
|
| + 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
|
| +};
|
| +
|
| // CPU Registers.
|
| //
|
| // 1) We would prefer to use an enum, but enum values are assignment-
|
| @@ -316,10 +374,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
|
| };
|
|
|
| @@ -504,12 +562,15 @@
|
| 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 Instr kMovLrPc;
|
| -extern const Instr kLdrPCPattern;
|
| +extern const InstrArm kMovLrPc;
|
| +extern const InstrArm kLdrPCPattern;
|
|
|
|
|
| class Assembler : public Malloced {
|
| @@ -587,15 +648,18 @@
|
| 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.
|
| @@ -873,7 +937,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.
|
| @@ -904,15 +968,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);
|
|
|
| @@ -963,7 +1034,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)
|
| @@ -992,7 +1064,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
|
|
|
| @@ -1004,19 +1076,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);
|
|
|