⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x86assembler.h

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 H
📖 第 1 页 / 共 4 页
字号:
        static void patchPointer(intptr_t where, intptr_t value)    {        reinterpret_cast<intptr_t*>(where)[-1] = value;    }        void* executableCopy(ExecutablePool* allocator)    {        void* copy = m_formatter.executableCopy(allocator);        ASSERT(copy);        return copy;    }private:    class X86InstructionFormatter {        static const int maxInstructionSize = 16;    public:        // Legacy prefix bytes:        //        // These are emmitted prior to the instruction.        void prefix(OneByteOpcodeID pre)        {            m_buffer.putByte(pre);        }        // Word-sized operands / no operand instruction formatters.        //        // In addition to the opcode, the following operand permutations are supported:        //   * None - instruction takes no operands.        //   * One register - the low three bits of the RegisterID are added into the opcode.        //   * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place).        //   * Three argument ModRM - a register, and a register and an offset describing a memory operand.        //   * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.        //        // For 32-bit x86 targets, the address operand may also be provided as a void*.        // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.        //        // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).        void oneByteOp(OneByteOpcodeID opcode)        {            m_buffer.ensureSpace(maxInstructionSize);            m_buffer.putByteUnchecked(opcode);        }        void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(0, 0, reg);            m_buffer.putByteUnchecked(opcode + (reg & 7));        }        void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, 0, rm);            m_buffer.putByteUnchecked(opcode);            registerModRM(reg, rm);        }        void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, 0, base);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, base, offset);        }        void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, 0, base);            m_buffer.putByteUnchecked(opcode);            memoryModRM_disp32(reg, base, offset);        }        void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, index, base);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, base, index, scale, offset);        }#if !PLATFORM(X86_64)        void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)        {            m_buffer.ensureSpace(maxInstructionSize);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, address);        }#endif        void twoByteOp(TwoByteOpcodeID opcode)        {            m_buffer.ensureSpace(maxInstructionSize);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);        }        void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, 0, rm);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);            registerModRM(reg, rm);        }        void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, 0, base);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, base, offset);        }        void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIfNeeded(reg, index, base);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, base, index, scale, offset);        }#if PLATFORM(X86_64)        // Quad-word-sized operands:        //        // Used to format 64-bit operantions, planting a REX.w prefix.        // When planting d64 or f64 instructions, not requiring a REX.w prefix,        // the normal (non-'64'-postfixed) formatters should be used.        void oneByteOp64(OneByteOpcodeID opcode)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(0, 0, 0);            m_buffer.putByteUnchecked(opcode);        }        void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(0, 0, reg);            m_buffer.putByteUnchecked(opcode + (reg & 7));        }        void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(reg, 0, rm);            m_buffer.putByteUnchecked(opcode);            registerModRM(reg, rm);        }        void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(reg, 0, base);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, base, offset);        }        void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(reg, 0, base);            m_buffer.putByteUnchecked(opcode);            memoryModRM_disp32(reg, base, offset);        }        void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(reg, index, base);            m_buffer.putByteUnchecked(opcode);            memoryModRM(reg, base, index, scale, offset);        }        void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexW(reg, 0, rm);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);            registerModRM(reg, rm);        }#endif        // Byte-operands:        //        // These methods format byte operations.  Byte operations differ from the normal        // formatters in the circumstances under which they will decide to emit REX prefixes.        // These should be used where any register operand signifies a byte register.        //        // The disctinction is due to the handling of register numbers in the range 4..7 on        // x86-64.  These register numbers may either represent the second byte of the first        // four registers (ah..bh) or the first byte of the second four registers (spl..dil).        //        // Since ah..bh cannot be used in all permutations of operands (specifically cannot        // be accessed where a REX prefix is present), these are likely best treated as        // deprecated.  In order to ensure the correct registers spl..dil are selected a        // REX prefix will be emitted for any byte register operand in the range 4..15.        //        // These formatters may be used in instructions where a mix of operand sizes, in which        // case an unnecessary REX will be emitted, for example:        //     movzbl %al, %edi        // In this case a REX will be planted since edi is 7 (and were this a byte operand        // a REX would be required to specify dil instead of bh).  Unneeded REX prefixes will        // be silently ignored by the processor.        //        // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()        // is provided to check byte register operands.        void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);            m_buffer.putByteUnchecked(opcode);            registerModRM(groupOp, rm);        }        void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);            registerModRM(reg, rm);        }        void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)        {            m_buffer.ensureSpace(maxInstructionSize);            emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);            m_buffer.putByteUnchecked(opcode);            registerModRM(groupOp, rm);        }        // Immediates:        //        // An immedaite should be appended where appropriate after an op has been emitted.        // The writes are unchecked since the opcode formatters above will have ensured space.        void immediate8(int imm)        {            m_buffer.putByteUnchecked(imm);        }        void immediate32(int imm)        {            m_buffer.putIntUnchecked(imm);        }        void immediate64(int64_t imm)        {            m_buffer.putInt64Unchecked(imm);        }        JmpSrc immediateRel32()        {            m_buffer.putIntUnchecked(0);            return JmpSrc(m_buffer.size());        }        // Administrative methods:        size_t size() const { return m_buffer.size(); }        bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }        void* data() const { return m_buffer.data(); }        void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }    private:        // Internals; ModRm and REX formatters.        static const RegisterID noBase = X86::ebp;        static const RegisterID hasSib = X86::esp;        static const RegisterID noIndex = X86::esp;#if PLATFORM(X86_64)        static const RegisterID noBase2 = X86::r13;        static const RegisterID hasSib2 = X86::r12;        // Registers r8 & above require a REX prefixe.        inline bool regRequiresRex(int reg)        {            return (reg >= X86::r8);        }        // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).        inline bool byteRegRequiresRex(int reg)        {            return (reg >= X86::esp);        }        // Format a REX prefix byte.        inline void emitRex(bool w, int r, int x, int b)        {            m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));        }        // Used to plant a REX byte with REX.w set (for 64-bit operations).        inline void emitRexW(int r, int x, int b)        {            emitRex(true, r, x, b);        }        // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,        // regRequiresRex() to check other registers (i.e. address base & index).        inline void emitRexIf(bool condition, int r, int x, int b)        {            if (condition) emitRex(false, r, x, b);        }        // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).        inline void emitRexIfNeeded(int r, int x, int b)        {            emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b);        }#else        // No REX prefix bytes on 32-bit x86.        inline bool regRequiresRex(int) { return false; }        inline bool byteRegRequiresRex(int) { return false; }        inline void emitRexIf(bool, int, int, int) {}        inline void emitRexIfNeeded(int, int, int) {}#endif        enum ModRmMode {            ModRmMemoryNoDisp,            ModRmMemoryDisp8,            ModRmMemoryDisp32,            ModRmRegister,        };        void putModRm(ModRmMode mode, int reg, RegisterID rm)        {            m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));        }        void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)        {            ASSERT(mode != ModRmRegister);            putModRm(mode, reg, hasSib);            m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7));        }        void registerModRM(int reg, RegisterID rm)        {            putModRm(ModRmRegister, reg, rm);        }        void memoryModRM(int reg, RegisterID base, int offset)        {            // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.#if PLATFORM(X86_64)            if ((base == hasSib) || (base == hasSib2)) {#else            if (base == hasSib) {#endif                if (!offset) // No need to check if the base is noBase, since we know it is hasSib!                    putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0);                else if (CAN_SIGN_EXTEND_8_32(offset)) {                    putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);                    m_buffer.putByteUnchecked(offset);                } else {                    putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);                    m_buffer.putIntUnchecked(offset);                }            } else {#if PLATFORM(X86_64)                if (!offset && (base != noBase) && (base != noBase2))#else                if (!offset && (base != noBase))#endif                    putModRm(ModRmMemoryNoDisp, reg, base);                else if (CAN_SIGN_EXTEND_8_32(offset)) {                    putModRm(ModRmMemoryDisp8, reg, base);                    m_buffer.putByteUnchecked(offset);                } else {                    putModRm(ModRmMemoryDisp32, reg, base);                    m_buffer.putIntUnchecked(offset);                }            }        }            void memoryModRM_disp32(int reg, RegisterID base, int offset)        {            // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.#if PLATFORM(X86_64)            if ((base == hasSib) || (base == hasSib2)) {#else            if (base == hasSib) {#endif                putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);                m_buffer.putIntUnchecked(offset);            } else {                putModRm(ModRmMemoryDisp32, reg, base);                m_buffer.putIntUnchecked(offset);            }        }            void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)        {            ASSERT(index != noIndex);#if PLATFORM(X86_64)            if (!offset && (base != noBase) && (base != noBase2))#else            if (!offset && (base != noBase))#endif                putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale);            else if (CAN_SIGN_EXTEND_8_32(offset)) {                putModRmSib(ModRmMemoryDisp8, reg, base, index, scale);                m_buffer.putByteUnchecked(offset);            } else {                putModRmSib(ModRmMemoryDisp32, reg, base, index, scale);                m_buffer.putIntUnchecked(offset);            }        }#if !PLATFORM(X86_64)        void memoryModRM(int reg, void* address)        {            // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!            putModRm(ModRmMemoryNoDisp, reg, noBase);            m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));        }#endif        AssemblerBuffer m_buffer;    } m_formatter;};} // namespace JSC#endif // ENABLE(ASSEMBLER) && PLATFORM(X86)#endif // X86Assembler_h

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -