コード例 #1
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::cmp(Indirect mem, Immediate imm) {
    int64_t val = imm.val;
    assert((-1L << 31) <= val && val < (1L << 31) - 1);

    int src_idx = mem.base.regnum;

    int rex = REX_W;
    if (src_idx >= 8) {
        rex |= REX_B;
        src_idx -= 8;
    }

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

    emitRex(rex);
    emitByte(0x81);

    assert(-0x80 <= mem.offset && mem.offset < 0x80);
    if (mem.offset == 0) {
        emitModRM(0b00, 7, src_idx);
    } else {
        emitModRM(0b01, 7, src_idx);
        emitByte(mem.offset);
    }

    emitInt(val, 4);
}
コード例 #2
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::cmp(Indirect mem, Register reg) {
    int mem_idx = mem.base.regnum;
    int reg_idx = reg.regnum;

    int rex = REX_W;
    if (mem_idx >= 8) {
        rex |= REX_B;
        mem_idx -= 8;
    }
    if (reg_idx >= 8) {
        rex |= REX_R;
        reg_idx -= 8;
    }

    assert(mem_idx >= 0 && mem_idx < 8);
    assert(reg_idx >= 0 && reg_idx < 8);

    emitRex(rex);
    emitByte(0x3B);

    assert(-0x80 <= mem.offset && mem.offset < 0x80);
    if (mem.offset == 0) {
        emitModRM(0b00, reg_idx, mem_idx);
    } else {
        emitModRM(0b01, reg_idx, mem_idx);
        emitByte(mem.offset);
    }
}
コード例 #3
0
ファイル: assembler.cpp プロジェクト: c-rhodes/pyston
void Assembler::emitArith(Immediate imm, Register r, int opcode, MovType type) {
    // assert(r != RSP && "This breaks unwinding, please don't use.");

    int64_t amount = imm.val;
    RELEASE_ASSERT(fitsInto<int32_t>(amount), "");
    assert(0 <= opcode && opcode < 8);

    assert(type == MovType::Q || type == MovType::L);
    int rex = type == MovType::Q ? REX_W : 0;

    int reg_idx = r.regnum;
    if (reg_idx >= 8) {
        rex |= REX_B;
        reg_idx -= 8;
    }

    if (rex)
        emitRex(rex);
    if (-0x80 <= amount && amount < 0x80) {
        emitByte(0x83);
        emitModRM(0b11, opcode, reg_idx);
        emitByte(amount);
    } else {
        emitByte(0x81);
        emitModRM(0b11, opcode, reg_idx);
        emitInt(amount, 4);
    }
}
コード例 #4
0
ファイル: assembler.cpp プロジェクト: c-rhodes/pyston
void Assembler::incq(Indirect mem) {
    int src_idx = mem.base.regnum;

    int rex = REX_W;
    if (src_idx >= 8) {
        rex |= REX_B;
        src_idx -= 8;
    }

    assert(src_idx >= 0 && src_idx < 8);
    bool needssib = (src_idx == 0b100);

    if (rex)
        emitRex(rex);
    emitByte(0xff);

    assert(-0x80 <= mem.offset && mem.offset < 0x80);
    if (mem.offset == 0) {
        emitModRM(0b00, 0, src_idx);
        if (needssib)
            emitSIB(0b00, 0b100, src_idx);
    } else {
        emitModRM(0b01, 0, src_idx);
        if (needssib)
            emitSIB(0b00, 0b100, src_idx);
        emitByte(mem.offset);
    }
}
コード例 #5
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::emitArith(Immediate imm, Register r, int opcode) {
    // assert(r != RSP && "This breaks unwinding, please don't use.");

    int64_t amount = imm.val;
    RELEASE_ASSERT((-1L << 31) <= amount && amount < (1L << 31) - 1, "");
    assert(0 <= opcode && opcode < 8);

    int rex = REX_W;

    int reg_idx = r.regnum;
    if (reg_idx >= 8) {
        rex |= REX_B;
        reg_idx -= 8;
    }

    emitRex(rex);
    if (-0x80 <= amount && amount < 0x80) {
        emitByte(0x83);
        emitModRM(0b11, opcode, reg_idx);
        emitByte(amount);
    } else {
        emitByte(0x81);
        emitModRM(0b11, opcode, reg_idx);
        emitInt(amount, 4);
    }
}
コード例 #6
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::mov(Register src, Indirect dest) {
    int rex = REX_W;

    int src_idx = src.regnum;
    int dest_idx = dest.base.regnum;

    assert(src_idx != dest_idx && "while valid this is almost certainly a register allocator bug");

    if (src_idx >= 8) {
        rex |= REX_R;
        src_idx -= 8;
    }
    if (dest_idx >= 8) {
        rex |= REX_B;
        dest_idx -= 8;
    }

    emitRex(rex);
    emitByte(0x89);

    bool needssib = (dest_idx == 0b100);
    int mode = getModeFromOffset(dest.offset);
    emitModRM(mode, src_idx, dest_idx);

    if (needssib)
        emitSIB(0b00, 0b100, dest_idx);

    if (mode == 0b01) {
        emitByte(dest.offset);
    } else if (mode == 0b10) {
        emitInt(dest.offset, 4);
    }
}
コード例 #7
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::movq(Immediate src, Indirect dest) {
    int64_t src_val = src.val;
    assert((-1L << 31) <= src_val && src_val < (1L << 31) - 1);

    int rex = REX_W;

    int dest_idx = dest.base.regnum;

    if (dest_idx >= 8) {
        rex |= REX_B;
        dest_idx -= 8;
    }

    emitRex(rex);
    emitByte(0xc7);

    bool needssib = (dest_idx == 0b100);
    int mode = getModeFromOffset(dest.offset);
    emitModRM(mode, 0, dest_idx);

    if (needssib)
        emitSIB(0b00, 0b100, dest_idx);

    if (mode == 0b01) {
        emitByte(dest.offset);
    } else if (mode == 0b10) {
        emitInt(dest.offset, 4);
    }

    emitInt(src_val, 4);
}
コード例 #8
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::movsd(XMMRegister src, Indirect dest) {
    int rex = 0;
    int src_idx = src.regnum;
    int dest_idx = dest.base.regnum;

    if (src_idx >= 8) {
        rex |= REX_R;
        src_idx -= 8;
    }
    if (dest_idx >= 8) {
        trap();
        rex |= REX_B;
        dest_idx -= 8;
    }

    emitByte(0xf2);
    if (rex)
        emitRex(rex);
    emitByte(0x0f);
    emitByte(0x11);

    bool needssib = (dest_idx == 0b100);
    int mode = getModeFromOffset(dest.offset);
    emitModRM(mode, src_idx, dest_idx);

    if (needssib)
        emitSIB(0b00, 0b100, dest_idx);

    if (mode == 0b01) {
        emitByte(dest.offset);
    } else if (mode == 0b10) {
        emitInt(dest.offset, 4);
    }
}
コード例 #9
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::jmp(Indirect dest) {
    int reg_idx = dest.base.regnum;

    assert(reg_idx >= 0 && reg_idx < 8 && "not yet implemented");
    emitByte(0xFF);
    if (dest.offset == 0) {
        emitModRM(0b00, 0b100, reg_idx);
    } else if (-0x80 <= dest.offset && dest.offset < 0x80) {
        emitModRM(0b01, 0b100, reg_idx);
        emitByte(dest.offset);
    } else {
        assert((-1L << 31) <= dest.offset && dest.offset < (1L << 31) - 1);
        emitModRM(0b10, 0b100, reg_idx);
        emitInt(dest.offset, 4);
    }
}
コード例 #10
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::lea(Indirect mem, Register reg) {
    int mem_idx = mem.base.regnum;
    int reg_idx = reg.regnum;

    int rex = REX_W;
    if (mem_idx >= 8) {
        rex |= REX_B;
        mem_idx -= 8;
    }
    if (reg_idx >= 8) {
        rex |= REX_R;
        reg_idx -= 8;
    }

    assert(mem_idx >= 0 && mem_idx < 8);
    assert(reg_idx >= 0 && reg_idx < 8);

    emitRex(rex);
    emitByte(0x8D);

    bool needssib = (mem_idx == 0b100);
    int mode = getModeFromOffset(mem.offset);
    emitModRM(mode, reg_idx, mem_idx);

    if (needssib)
        emitSIB(0b00, 0b100, mem_idx);

    if (mode == 0b01) {
        emitByte(mem.offset);
    } else if (mode == 0b10) {
        assert((-1L << 31) <= mem.offset && mem.offset < (1L << 31) - 1);
        emitInt(mem.offset, 4);
    }
}
コード例 #11
0
ファイル: assembler.cpp プロジェクト: c-rhodes/pyston
void Assembler::clear_reg(Register reg) {
    int reg_idx = reg.regnum;
    // we don't need to generate a REX_W because 32bit instructions will clear the upper 32bits.
    if (reg_idx >= 8) {
        emitRex(REX_R | REX_B);
        reg_idx -= 8;
    }
    emitByte(0x31);
    emitModRM(0b11, reg_idx, reg_idx);
}
コード例 #12
0
ファイル: assembler.cpp プロジェクト: c-rhodes/pyston
void Assembler::cmp(Indirect mem, Immediate imm, MovType type) {
    int64_t val = imm.val;
    assert(fitsInto<int32_t>(val));

    int src_idx = mem.base.regnum;
    assert(type == MovType::Q || type == MovType::L);
    int rex = type == MovType::Q ? REX_W : 0;
    if (src_idx >= 8) {
        rex |= REX_B;
        src_idx -= 8;
    }

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

    bool needssib = (src_idx == 0b100);

    if (rex)
        emitRex(rex);
    emitByte(0x81);

    if (mem.offset == 0) {
        emitModRM(0b00, 7, src_idx);
        if (needssib)
            emitSIB(0b00, 0b100, src_idx);
    } else if (-0x80 <= mem.offset && mem.offset < 0x80) {
        emitModRM(0b01, 7, src_idx);
        if (needssib)
            emitSIB(0b00, 0b100, src_idx);
        emitByte(mem.offset);
    } else {
        assert(fitsInto<int32_t>(mem.offset));
        emitModRM(0b10, 7, src_idx);
        if (needssib)
            emitSIB(0b00, 0b100, src_idx);
        emitInt(mem.offset, 4);
    }

    emitInt(val, 4);
}
コード例 #13
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::jmpq(Register dest) {
    int reg_idx = dest.regnum;

    if (reg_idx >= 8) {
        emitRex(REX_B);
        reg_idx -= 8;
    }

    assert(0 <= reg_idx && reg_idx < 8);

    emitByte(0xff);
    emitModRM(0b11, 0b100, reg_idx);
}
コード例 #14
0
ファイル: assembler.cpp プロジェクト: c-rhodes/pyston
void Assembler::emitArith(Immediate imm, Indirect mem, int opcode) {
    int64_t amount = imm.val;
    assert(fitsInto<int32_t>(amount));
    assert(0 <= opcode && opcode < 8);

    int rex = REX_W;

    int mem_idx = mem.base.regnum;
    if (mem_idx >= 8) {
        rex |= REX_B;
        mem_idx -= 8;
    }

    emitRex(rex);

    bool needssib = (mem_idx == 0b100);
    assert(!needssib && "untested");
    int mode = getModeFromOffset(mem.offset, mem_idx);
    assert(mode != 0b10 && "not yet supported");

    if (-0x80 <= amount && amount < 0x80) {
        emitByte(0x83);
        if (needssib)
            emitSIB(0b00, 0b100, mem_idx);
        emitModRM(mode, opcode, mem_idx);
        if (mode == 0b01)
            emitByte(mem.offset);
        emitByte(amount);
    } else {
        emitByte(0x81);
        if (needssib)
            emitSIB(0b00, 0b100, mem_idx);
        emitModRM(mode, opcode, mem_idx);
        if (mode == 0b01)
            emitByte(mem.offset);
        emitInt(amount, 4);
    }
}
コード例 #15
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::decl(Indirect mem) {
    int src_idx = mem.base.regnum;

    int rex = 0;
    if (src_idx >= 8) {
        rex |= REX_B;
        src_idx -= 8;
    }

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

    if (rex)
        emitRex(rex);
    emitByte(0xff);

    assert(-0x80 <= mem.offset && mem.offset < 0x80);
    if (mem.offset == 0) {
        emitModRM(0b00, 1, src_idx);
    } else {
        emitModRM(0b01, 1, src_idx);
        emitByte(mem.offset);
    }
}
コード例 #16
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::set_cond(Register reg, ConditionCode condition) {
    int reg_idx = reg.regnum;

    assert(0 <= reg_idx && reg_idx < 8);

    int rex = 0;
    // Have to emit a blank REX when accessing RSP/RBP/RDI/RSI,
    // since without it this instruction will refer to ah/bh/ch/dh.
    if (reg_idx >= 4 || rex)
        emitRex(rex);

    emitByte(0x0f);
    emitByte(0x90 + condition);
    emitModRM(0b11, 0, reg_idx);
}
コード例 #17
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::cmp(Register reg, Immediate imm) {
    int64_t val = imm.val;
    assert((-1L << 31) <= val && val < (1L << 31) - 1);

    int reg_idx = reg.regnum;

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

    emitRex(rex);
    emitByte(0x81);
    emitModRM(0b11, 7, reg_idx);
    emitInt(val, 4);
}
コード例 #18
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::movsd(Indirect src, XMMRegister dest) {
    int rex = 0;
    int src_idx = src.base.regnum;
    int dest_idx = dest.regnum;

    if (src_idx >= 8) {
        trap();
        rex |= REX_R;
        src_idx -= 8;
    }
    if (dest_idx >= 8) {
        trap();
        rex |= REX_B;
        dest_idx -= 8;
    }

    emitByte(0xf2);
    if (rex)
        emitRex(rex);
    emitByte(0x0f);
    emitByte(0x10);

    bool needssib = (src_idx == 0b100);

    int mode;
    if (src.offset == 0)
        mode = 0b00;
    else if (-0x80 <= src.offset && src.offset < 0x80)
        mode = 0b01;
    else
        mode = 0b10;

    emitModRM(mode, dest_idx, src_idx);

    if (needssib)
        emitSIB(0b00, 0b100, src_idx);

    if (mode == 0b01) {
        emitByte(src.offset);
    } else if (mode == 0b10) {
        emitInt(src.offset, 4);
    }
}
コード例 #19
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::cmp(Register reg1, Register reg2) {
    int reg1_idx = reg1.regnum;
    int reg2_idx = reg2.regnum;

    int rex = REX_W;
    if (reg1_idx >= 8) {
        rex |= REX_R;
        reg1_idx -= 8;
    }
    if (reg2_idx >= 8) {
        rex |= REX_B;
        reg2_idx -= 8;
    }

    assert(reg1_idx >= 0 && reg1_idx < 8);
    assert(reg2_idx >= 0 && reg2_idx < 8);

    emitRex(rex);
    emitByte(0x39);
    emitModRM(0b11, reg1_idx, reg2_idx);
}
コード例 #20
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::mov(Register src, Register dest) {
    ASSERT(src != dest, "probably better to avoid calling this?");

    int src_idx = src.regnum;
    int dest_idx = dest.regnum;

    uint8_t rex = REX_W;
    if (dest_idx >= 8) {
        rex |= REX_B;
        dest_idx -= 8;
    }
    if (src_idx >= 8) {
        rex |= REX_R;
        src_idx -= 8;
    }

    assert(0 <= src_idx && src_idx < 8);
    assert(0 <= dest_idx && dest_idx < 8);

    emitRex(rex);
    emitByte(0x89);
    emitModRM(0b11, src_idx, dest_idx);
}
コード例 #21
0
ファイル: assembler.cpp プロジェクト: kod3r/pyston
void Assembler::movsd(XMMRegister src, XMMRegister dest) {
    int rex = 0;
    int src_idx = src.regnum;
    int dest_idx = dest.regnum;

    if (src_idx >= 8) {
        trap();
        rex |= REX_R;
        src_idx -= 8;
    }
    if (dest_idx >= 8) {
        trap();
        rex |= REX_B;
        dest_idx -= 8;
    }

    emitByte(0xf2);
    if (rex)
        emitRex(rex);
    emitByte(0x0f);
    emitByte(0x10);

    emitModRM(0b11, src_idx, dest_idx);
}
コード例 #22
0
ファイル: assembler.cpp プロジェクト: jmgc/pyston
void Assembler::mov_generic(Indirect src, Register dest, MovType type) {
    int rex;
    switch (type) {
        case MovType::Q:
        case MovType::ZBQ:
        case MovType::SBQ:
        case MovType::ZWQ:
        case MovType::SWQ:
        case MovType::SLQ:
            rex = REX_W;
            break;
        case MovType::L:
        case MovType::B:
        case MovType::ZBL:
        case MovType::SBL:
        case MovType::ZWL:
        case MovType::SWL:
            rex = 0;
            break;
        default:
            RELEASE_ASSERT(false, "unrecognized MovType");
    }

    int src_idx = src.base.regnum;
    int dest_idx = dest.regnum;

    if (src_idx >= 8) {
        rex |= REX_B;
        src_idx -= 8;
    }
    if (dest_idx >= 8) {
        rex |= REX_R;
        dest_idx -= 8;
    }

    if (rex)
        emitRex(rex);

    // opcode
    switch (type) {
        case MovType::Q:
        case MovType::L:
            emitByte(0x8b);
            break;
        case MovType::B:
            emitByte(0x8a);
            break;
        case MovType::ZBQ:
        case MovType::ZBL:
            emitByte(0x0f);
            emitByte(0xb6);
            break;
        case MovType::SBQ:
        case MovType::SBL:
            emitByte(0x0f);
            emitByte(0xbe);
            break;
        case MovType::ZWQ:
        case MovType::ZWL:
            emitByte(0x0f);
            emitByte(0xb7);
            break;
        case MovType::SWQ:
        case MovType::SWL:
            emitByte(0x0f);
            emitByte(0xbf);
            break;
        case MovType::SLQ:
            emitByte(0x63);
            break;
        default:
            RELEASE_ASSERT(false, "unrecognized MovType");
    }

    bool needssib = (src_idx == 0b100);

    int mode;
    if (src.offset == 0)
        mode = 0b00;
    else if (-0x80 <= src.offset && src.offset < 0x80)
        mode = 0b01;
    else
        mode = 0b10;

    emitModRM(mode, dest_idx, src_idx);

    if (needssib)
        emitSIB(0b00, 0b100, src_idx);

    if (mode == 0b01) {
        emitByte(src.offset);
    } else if (mode == 0b10) {
        emitInt(src.offset, 4);
    }
}