Exemple #1
0
        // TODO verify that the arguments are being compared in the right order
        // cmpq offset(%reg), $imm
        inline void _emitAttrCmpImm(int reg, int offset, int64_t val) {
            assert((-1L<<31) <= val && val < (1L<<31)-1);

            int rex = X86::REX_W;
            if (reg >= 8) {
                rex |= X86::REX_B;
                reg -= 8;
            }

            assert(reg >= 0 && reg < 8);

            _emitRex(rex);
            _emitByte(0x81);

            assert(-0x80 <= offset && offset < 0x80);
            if (offset == 0) {
                _emitModRM(0b00, 7, reg);
            } else {
                _emitModRM(0b01, 7, reg);
                _emitByte(offset);
            }

            for (int i = 0; i < 4; i++) {
                _emitByte(val & 0xff);
                val >>= 8;
            }
        }
Exemple #2
0
        inline void _emitCmpDisplacement(uint8_t reg1, uint64_t reg2, int displacement) {
            // TODO if it's bigger, we could use a larger scale since
            // things are most likely aligned
            assert(displacement >= -0x80 && displacement < 0x80);

            uint8_t flags = 0;
            flags |= X86::REX_W;

            if (reg1 >= 8) {
                flags |= X86::REX_R;
                reg1 &= 0b111;
            }
            if (reg2 >= 8) {
                flags |= X86::REX_B;
                reg2 &= 0b111;
            }

            _emitRex(flags);
            _emitByte(0x39);
            if (displacement == 0) {
                // Since we're emitting into a fixed-size section I guess there might not be
                // too much benifit to the more compact encoding, but it makes me feel better:
                _emitModRM(0b00, reg1, reg2);
            } else {
                _emitModRM(0b01, reg1, reg2);
                _emitByte(displacement);
            }
        }
Exemple #3
0
        // movzbq %src_reg, %dest_reg
        void _emitZeroExtend(int src_reg, int dest_reg) {
            assert(0 <= src_reg && src_reg < 8);
            assert(0 <= dest_reg && dest_reg < 8);

            _emitRex(X86::REX_W);
            _emitByte(0x0f);
            _emitByte(0xb6);
            _emitModRM(0b11, dest_reg, src_reg);
        }
Exemple #4
0
        inline void _emitMoveImm64(uint8_t reg, uint64_t value) {
            assert(reg >= 0 && reg < 8);
            _emitRex(X86::REX_W);
            _emitByte(0xb8 + reg);

            for (int i = 0; i < 8; i++) {
                _emitByte(value & 0xff);
                value >>= 8;
            }
        }
Exemple #5
0
        void _emitCondSet(int dest_reg, int cond_code) {
            assert(0 <= dest_reg && dest_reg < 8);
            assert(0 <= cond_code && cond_code < 16);

            if (dest_reg >= 4)
                _emitRex(0);
            _emitByte(0x0f);
            _emitByte(0x90 + cond_code);
            _emitModRM(0b11, 0, dest_reg);
        }
Exemple #6
0
        // incq offset(%reg)
        virtual void _emitIncattr(int reg, int offset) {
            assert(offset >= -0x80 && offset < 0x80);

            int rex = X86::REX_W;
            if (reg >= 8) {
                rex |= X86::REX_B;
                reg -= 8;
            }

            _emitRex(rex);
            _emitByte(0xff);
            _emitModRM(0b01, 0b000, reg);
            _emitByte(offset);
        }
Exemple #7
0
        void _emitJmp(void* dest_addr) {
            long offset = (uint8_t*)dest_addr - addr - 2;
            if (offset >= -0x80 && offset < 0x80) {
                _emitByte(0xeb);
                _emitByte(offset);
            } else {
                assert(offset >= -1L<<31 && offset < 1L<<31);

                offset -= 3;
                _emitByte(0xe9);
                for (int i = 0; i < 4; i++) {
                    _emitByte(offset & 0xff);
                    offset >>= 8;
                }
            }
        }
Exemple #8
0
        // test[q] %reg1, %reg2
        inline void _emitTest(int reg1, int reg2) {
            assert(reg1 >= 0 && reg1 < 8);
            assert(reg2 >= 0 && reg2 < 8);

            _emitRex(X86::REX_W);
            _emitByte(0x85);
            _emitModRM(0b11, reg1, reg2);
        }
Exemple #9
0
        /// "op $val, %reg"
        inline void _emitArith(int reg, int val, int opcode)  {
            assert(val >= -0x80 && val < 0x80);
            assert(opcode < 8);

            uint8_t flags = 0;
            flags |= X86::REX_W;

            if (reg >= 8) {
                flags |= X86::REX_B;
                reg &= 0b111;
            }

            _emitRex(flags);
            _emitByte(0x83);
            _emitModRM(0b11, opcode, reg);
            _emitByte(val);
        }
Exemple #10
0
    inline void _emitJne(uint8_t* dest_addr, bool unlikely) {
        _emitJmpCond(dest_addr, X86::COND_NOT_EQUAL, unlikely);
        int offset = dest_addr - addr - 2;
        if (unlikely)
            offset -= 1;

        if (offset >= -0x80 && offset < 0x80) {
            if (unlikely)
                _emitByte(0x2e);
            _emitByte(0x75);
            _emitByte(offset);
        } else {
            offset -= 4;

            if (unlikely)
                _emitByte(0x2e);

            _emitByte(0x0f);
            _emitByte(0x85);
            for (int i = 0; i < 4; i++) {
                _emitByte(offset & 0xff);
                offset >>= 8;
            }
        }
    }
Exemple #11
0
        // TODO verify that the arguments are being compared in the right order
        // cmp $val, %reg
        inline void _emitCmpImm(int reg, int64_t val) {
            assert((-1L<<31) <= val && val < (1L<<31)-1);

            int rex = X86::REX_W;
            if (reg > 8) {
                rex |= X86::REX_B;
                reg -= 8;
            }
            assert(0 <= reg && reg < 8);

            _emitRex(rex);
            _emitByte(0x81);
            _emitModRM(0b11, 7, reg);
            for (int i = 0; i < 4; i++) {
                _emitByte(val & 0xff);
                val >>= 8;
            }
        }
Exemple #12
0
        inline void _emitPop(uint8_t reg) {
            assert(reg != X86::REG_STACK_POINTER); // this might work but most likely a bug
            assert(0 <= reg && reg < 16);

            if (reg >= 8) {
                _emitRex(X86::REX_B);
                reg -= 8;
            }
            assert(reg < 8);
            _emitByte(0x58 + reg);
        }
Exemple #13
0
        // TODO verify that the arguments are being compared in the right order
        // cmpq offset(%reg1), %reg2
        inline void _emitAttrCmp(int reg1, int reg1_offset, int reg2) {
            int rex = X86::REX_W;
            if (reg1 >= 8) {
                rex |= X86::REX_B;
                reg1 -= 8;
            }

            assert(reg1 >= 0 && reg1 < 8);
            assert(reg2 >= 0 && reg2 < 8);

            _emitRex(rex);
            _emitByte(0x3B);

            assert(-0x80 <= reg1_offset && reg1_offset < 0x80);
            if (reg1_offset == 0) {
                _emitModRM(0b00, reg2, reg1);
            } else {
                _emitModRM(0b01, reg2, reg1);
                _emitByte(reg1_offset);
            }
        }
Exemple #14
0
        /// mov $displacement(%source) %dest
        inline void _emitLoadRegIndirect(int source, int displacement, int dest) {
            bool usesib = false;
            if (source == 0b100 || dest == 0b1100) {
                usesib = true;
            }

            uint8_t flags = X86::REX_W;
            if (dest >= 8) {
                flags |= X86::REX_R;
                dest &= 0b111;
            }
            if (source >= 8) {
                flags |= X86::REX_B;
                source &= 0b111;
            }

            _emitRex(flags);
            _emitByte(0x8b);

            int mode;
            if (displacement == 0)
                mode = 0b00;
            else if (-0x80 <= displacement && displacement < 0x79)
                mode = 0b01;
            else
                mode = 0b10;

            _emitModRM(mode, dest, source);
            if (usesib)
                _emitSIB(0b00, 0b100, source);

            if (mode == 0b01) {
                _emitByte(displacement);
            } else if (mode == 0b10) {
                for (int i = 0; i < 4; i++) {
                    _emitByte(displacement & 0xff);
                    displacement >>= 8;
                }
            }
        }
Exemple #15
0
        // TODO verify that the arguments are being compared in the right order
        // cmpq %reg1, %reg2 # or maybe they're reversed?
        inline void _emitCmp(int reg1, int reg2) {
            int rex = X86::REX_W;
            if (reg1 >= 8) {
                rex |= X86::REX_R;
                reg1 -= 8;
            }

            assert(reg1 >= 0 && reg1 < 8);
            assert(reg2 >= 0 && reg2 < 8);

            _emitRex(rex);
            _emitByte(0x39);
            _emitModRM(0b11, reg1, reg2);
        }
Exemple #16
0
        inline void _emitMoveReg(int source, int dest) {
            uint8_t flags = 0;
            flags |= X86::REX_W;
            if (dest >= 8) {
                flags |= X86::REX_B;
                dest &= 0b111;
            }
            if (source >= 8) {
                flags |= X86::REX_R;
                source &= 0b111;
            }

            _emitRex(flags);
            _emitByte(0x89);
            _emitModRM(0b11, source, dest);
        }
Exemple #17
0
        inline void _emitJmpCond(uint8_t* dest_addr, X86::ConditionCode condition, bool unlikely) {
            int offset = dest_addr - addr - 2;
            if (unlikely) offset -= 1;

            if (offset >= -0x80 && offset < 0x80) {
                if (unlikely)
                    _emitByte(0x2e);
                _emitByte(0x75);
                _emitByte(offset);
            } else {
                offset -= 4;

                if (unlikely)
                    _emitByte(0x2e);

                _emitByte(0x0f);
                _emitByte(0x80 | condition);
                for (int i = 0; i < 4; i++) {
                    _emitByte(offset & 0xff);
                    offset >>= 8;
                }
            }
        }
Exemple #18
0
 inline void _emitRex(uint8_t flags) {
     assert(0 <= flags && flags < 16);
     _emitByte(0x40 | flags);
 }
Exemple #19
0
 inline void _emitModRM(uint8_t mod, uint8_t reg, uint8_t rm) {
     assert(mod < 4);
     assert(reg < 8);
     assert(rm < 8);
     _emitByte((mod << 6) | (reg << 3) | rm);
 }
Exemple #20
0
 inline void _emitSIB(uint8_t scalebits, uint8_t index, uint8_t base) {
     assert(scalebits < 4);
     assert(index < 8);
     assert(base < 8);
     _emitByte((scalebits << 6) | (index << 3) | base);
 }