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

📄 translate-copy.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  i386 on i386 translation *  *  Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "config.h"#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include <assert.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"#ifdef USE_CODE_COPY#include <signal.h>#include <sys/mman.h>#include <sys/ucontext.h>extern char exec_loop;/* operand size */enum {    OT_BYTE = 0,    OT_WORD,    OT_LONG,     OT_QUAD,};#define PREFIX_REPZ   0x01#define PREFIX_REPNZ  0x02#define PREFIX_LOCK   0x04#define PREFIX_DATA   0x08#define PREFIX_ADR    0x10typedef struct DisasContext {    /* current insn context */    int override; /* -1 if no override */    int prefix;    int aflag, dflag;    target_ulong pc; /* pc = eip + cs_base */    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU                   static state change (stop translation) */    /* code output */    uint8_t *gen_code_ptr;    uint8_t *gen_code_start;        /* current block context */    target_ulong cs_base; /* base of CS segment */    int pe;     /* protected mode */    int code32; /* 32 bit code segment */    int f_st;   /* currently unused */    int vm86;   /* vm86 mode */    int cpl;    int iopl;    int flags;    struct TranslationBlock *tb;} DisasContext;#define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)#define CPU_SEG 0x64 /* fs override */static inline void gb(DisasContext *s, uint32_t val){    *s->gen_code_ptr++ = val;}static inline void gw(DisasContext *s, uint32_t val){    *s->gen_code_ptr++ = val;    *s->gen_code_ptr++ = val >> 8;}static inline void gl(DisasContext *s, uint32_t val){    *s->gen_code_ptr++ = val;    *s->gen_code_ptr++ = val >> 8;    *s->gen_code_ptr++ = val >> 16;    *s->gen_code_ptr++ = val >> 24;}static inline void gjmp(DisasContext *s, long val){    gb(s, 0xe9); /* jmp */    gl(s, val - (long)(s->gen_code_ptr + 4));}static inline void gen_movl_addr_im(DisasContext *s,                                     uint32_t addr, uint32_t val){    gb(s, CPU_SEG); /* seg movl im, addr */    gb(s, 0xc7);     gb(s, 0x05);    gl(s, addr);    gl(s, val);}static inline void gen_movw_addr_im(DisasContext *s,                                     uint32_t addr, uint32_t val){    gb(s, CPU_SEG); /* seg movl im, addr */    gb(s, 0x66);     gb(s, 0xc7);     gb(s, 0x05);    gl(s, addr);    gw(s, val);}static void gen_jmp(DisasContext *s, uint32_t target_eip){    TranslationBlock *tb = s->tb;    gb(s, 0xe9); /* jmp */    tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;    gl(s, 0);    tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);    gjmp(s, (long)&exec_loop);    s->is_jmp = 1;}static void gen_jcc(DisasContext *s, int op,                    uint32_t target_eip, uint32_t next_eip){    TranslationBlock *tb = s->tb;    gb(s, 0x0f); /* jcc */    gb(s, 0x80 + op);    tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;    gl(s, 0);    gb(s, 0xe9); /* jmp */    tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;    gl(s, 0);        tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);    gjmp(s, (long)&exec_loop);    tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;    gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);    gjmp(s, (long)&exec_loop);    s->is_jmp = 1;}static void gen_eob(DisasContext *s){    gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);    gjmp(s, (long)&exec_loop);    s->is_jmp = 1;}static inline void gen_lea_modrm(DisasContext *s, int modrm){    int havesib;    int base, disp;    int index;    int scale;    int mod, rm, code;    mod = (modrm >> 6) & 3;    rm = modrm & 7;    if (s->aflag) {        havesib = 0;        base = rm;        index = 0;        scale = 0;                if (base == 4) {            havesib = 1;            code = ldub_code(s->pc++);            scale = (code >> 6) & 3;            index = (code >> 3) & 7;            base = code & 7;        }        switch (mod) {        case 0:            if (base == 5) {                base = -1;                disp = ldl_code(s->pc);                s->pc += 4;            } else {                disp = 0;            }            break;        case 1:            disp = (int8_t)ldub_code(s->pc++);            break;        default:        case 2:            disp = ldl_code(s->pc);            s->pc += 4;            break;        }            } else {        switch (mod) {        case 0:            if (rm == 6) {                disp = lduw_code(s->pc);                s->pc += 2;            } else {                disp = 0;            }            break;        case 1:            disp = (int8_t)ldub_code(s->pc++);            break;        default:        case 2:            disp = lduw_code(s->pc);            s->pc += 2;            break;        }    }}static inline void parse_modrm(DisasContext *s, int modrm){    if ((modrm & 0xc0) != 0xc0)        gen_lea_modrm(s, modrm);        }static inline uint32_t insn_get(DisasContext *s, int ot){    uint32_t ret;    switch(ot) {    case OT_BYTE:        ret = ldub_code(s->pc);        s->pc++;        break;    case OT_WORD:        ret = lduw_code(s->pc);        s->pc += 2;        break;    default:    case OT_LONG:        ret = ldl_code(s->pc);        s->pc += 4;        break;    }    return ret;}/* convert one instruction. s->is_jmp is set if the translation must   be stopped.  */static int disas_insn(DisasContext *s){    target_ulong pc_start, pc_tmp, pc_start_insn;    int b, prefixes, aflag, dflag, next_eip, val;    int ot;    int modrm, mod, op, rm;    pc_start = s->pc;    prefixes = 0;    aflag = s->code32;    dflag = s->code32;    s->override = -1; next_byte:    b = ldub_code(s->pc);    s->pc++;    /* check prefixes */    switch (b) {    case 0xf3:        prefixes |= PREFIX_REPZ;        goto next_byte;    case 0xf2:        prefixes |= PREFIX_REPNZ;        goto next_byte;    case 0xf0:        prefixes |= PREFIX_LOCK;        goto next_byte;    case 0x2e:        s->override = R_CS;        goto next_byte;    case 0x36:        s->override = R_SS;        goto next_byte;    case 0x3e:        s->override = R_DS;        goto next_byte;    case 0x26:        s->override = R_ES;        goto next_byte;    case 0x64:        s->override = R_FS;        goto next_byte;    case 0x65:        s->override = R_GS;        goto next_byte;    case 0x66:        prefixes |= PREFIX_DATA;        goto next_byte;    case 0x67:        prefixes |= PREFIX_ADR;        goto next_byte;    }    if (prefixes & PREFIX_DATA)        dflag ^= 1;    if (prefixes & PREFIX_ADR)        aflag ^= 1;    s->prefix = prefixes;    s->aflag = aflag;    s->dflag = dflag;    /* lock generation */    if (prefixes & PREFIX_LOCK)        goto unsupported_op;    if (s->override == R_FS || s->override == R_GS || s->override == R_CS)        goto unsupported_op;    pc_start_insn = s->pc - 1;    /* now check op code */ reswitch:    switch(b) {    case 0x0f:        /**************************/        /* extended op code */        b = ldub_code(s->pc++) | 0x100;        goto reswitch;                /**************************/        /* arith & logic */    case 0x00 ... 0x05:    case 0x08 ... 0x0d:    case 0x10 ... 0x15:    case 0x18 ... 0x1d:    case 0x20 ... 0x25:    case 0x28 ... 0x2d:    case 0x30 ... 0x35:    case 0x38 ... 0x3d:        {            int f;            f = (b >> 1) & 3;            if ((b & 1) == 0)                ot = OT_BYTE;            else                ot = dflag ? OT_LONG : OT_WORD;                        switch(f) {            case 0: /* OP Ev, Gv */                modrm = ldub_code(s->pc++);                parse_modrm(s, modrm);                break;            case 1: /* OP Gv, Ev */                modrm = ldub_code(s->pc++);                parse_modrm(s, modrm);                break;            case 2: /* OP A, Iv */                insn_get(s, ot);                break;            }        }        break;    case 0x80: /* GRP1 */    case 0x81:    case 0x82:    case 0x83:        {            if ((b & 1) == 0)                ot = OT_BYTE;            else                ot = dflag ? OT_LONG : OT_WORD;                        modrm = ldub_code(s->pc++);            parse_modrm(s, modrm);            switch(b) {            default:            case 0x80:            case 0x81:            case 0x82:                insn_get(s, ot);                break;            case 0x83:                insn_get(s, OT_BYTE);                break;            }        }        break;        /**************************/        /* inc, dec, and other misc arith */    case 0x40 ... 0x47: /* inc Gv */        break;    case 0x48 ... 0x4f: /* dec Gv */        break;    case 0xf6: /* GRP3 */    case 0xf7:        if ((b & 1) == 0)            ot = OT_BYTE;        else            ot = dflag ? OT_LONG : OT_WORD;        modrm = ldub_code(s->pc++);        op = (modrm >> 3) & 7;        parse_modrm(s, modrm);        switch(op) {        case 0: /* test */            insn_get(s, ot);            break;        case 2: /* not */            break;        case 3: /* neg */            break;        case 4: /* mul */

⌨️ 快捷键说明

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