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

📄 i386-asm.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 3 页
字号:
            if (reg2 == -1)                reg2 = 4; /* indicate no index */            g((op->shift << 6) + (reg2 << 3) + sib_reg1);        }        /* add offset */        if (mod == 0x40) {            g(op->e.v);        } else if (mod == 0x80 || op->reg == -1) {            gen_expr32(&op->e);        }    }}static void asm_opcode(TCCState *s1, int opcode){    const ASMInstr *pa;    int i, modrm_index, reg, v, op1, is_short_jmp;    int nb_ops, s, ss;    Operand ops[MAX_OPERANDS], *pop;    int op_type[3]; /* decoded op type */    /* get operands */    pop = ops;    nb_ops = 0;    for(;;) {        if (tok == ';' || tok == TOK_LINEFEED)            break;        if (nb_ops >= MAX_OPERANDS) {            error("incorrect number of operands");        }        parse_operand(s1, pop);        pop++;        nb_ops++;        if (tok != ',')            break;        next();    }    is_short_jmp = 0;    s = 0; /* avoid warning */        /* optimize matching by using a lookup table (no hashing is needed       !) */    for(pa = asm_instrs; pa->sym != 0; pa++) {        s = 0;        if (pa->instr_type & OPC_FARITH) {            v = opcode - pa->sym;            if (!((unsigned)v < 8 * 6 && (v % 6) == 0))                continue;        } else if (pa->instr_type & OPC_ARITH) {            if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))                continue;            goto compute_size;        } else if (pa->instr_type & OPC_SHIFT) {            if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))                continue;            goto compute_size;        } else if (pa->instr_type & OPC_TEST) {            if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))                continue;        } else if (pa->instr_type & OPC_B) {            if (!(opcode >= pa->sym && opcode <= pa->sym + 3))                continue;        compute_size:            s = (opcode - pa->sym) & 3;        } else if (pa->instr_type & OPC_WL) {            if (!(opcode >= pa->sym && opcode <= pa->sym + 2))                continue;            s = opcode - pa->sym + 1;        } else {            if (pa->sym != opcode)                continue;        }        if (pa->nb_ops != nb_ops)            continue;        /* now decode and check each operand */        for(i = 0; i < nb_ops; i++) {            int op1, op2;            op1 = pa->op_type[i];            op2 = op1 & 0x1f;            switch(op2) {            case OPT_IM:                v = OP_IM8 | OP_IM16 | OP_IM32;                break;            case OPT_REG:                v = OP_REG8 | OP_REG16 | OP_REG32;                break;            case OPT_REGW:                v = OP_REG16 | OP_REG32;                break;            case OPT_IMW:                v = OP_IM16 | OP_IM32;                break;            default:                v = 1 << op2;                break;            }            if (op1 & OPT_EA)                v |= OP_EA;            op_type[i] = v;            if ((ops[i].type & v) == 0)                goto next;        }        /* all is matching ! */        break;    next: ;    }    if (pa->sym == 0) {        if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {            int b;            b = op0_codes[opcode - TOK_ASM_pusha];            if (b & 0xff00)                 g(b >> 8);            g(b);            return;        } else {            error("unknown opcode '%s'",                   get_tok_str(opcode, NULL));        }    }    /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */    if (s == 3) {        for(i = 0; s == 3 && i < nb_ops; i++) {            if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))                s = reg_to_size[ops[i].type & OP_REG];        }        if (s == 3) {            if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&                 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))                s = 2;            else                error("cannot infer opcode suffix");        }    }    /* generate data16 prefix if needed */    ss = s;    if (s == 1 || (pa->instr_type & OPC_D16))        g(WORD_PREFIX_OPCODE);    else if (s == 2)        s = 1;    /* now generates the operation */    if (pa->instr_type & OPC_FWAIT)        g(0x9b);    v = pa->opcode;    if (v == 0x69 || v == 0x69) {        /* kludge for imul $im, %reg */        nb_ops = 3;        ops[2] = ops[1];    } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {        v--; /* int $3 case */        nb_ops = 0;    } else if ((v == 0x06 || v == 0x07)) {        if (ops[0].reg >= 4) {            /* push/pop %fs or %gs */            v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);        } else {            v += ops[0].reg << 3;        }        nb_ops = 0;    } else if (v <= 0x05) {        /* arith case */        v += ((opcode - TOK_ASM_addb) >> 2) << 3;    } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {        /* fpu arith case */        v += ((opcode - pa->sym) / 6) << 3;    }    if (pa->instr_type & OPC_REG) {        for(i = 0; i < nb_ops; i++) {            if (op_type[i] & (OP_REG | OP_ST)) {                v += ops[i].reg;                break;            }        }        /* mov $im, %reg case */        if (pa->opcode == 0xb0 && s >= 1)            v += 7;    }    if (pa->instr_type & OPC_B)        v += s;    if (pa->instr_type & OPC_TEST)        v += test_bits[opcode - pa->sym];     if (pa->instr_type & OPC_SHORTJMP) {        Sym *sym;        int jmp_disp;        /* see if we can really generate the jump with a byte offset */        sym = ops[0].e.sym;        if (!sym)            goto no_short_jump;        if (sym->r != cur_text_section->sh_num)            goto no_short_jump;        jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;        if (jmp_disp == (int8_t)jmp_disp) {            /* OK to generate jump */            is_short_jmp = 1;            ops[0].e.v = jmp_disp;        } else {        no_short_jump:            if (pa->instr_type & OPC_JMP) {                /* long jump will be allowed. need to modify the                   opcode slightly */                if (v == 0xeb)                    v = 0xe9;                else                     v += 0x0f10;            } else {                error("invalid displacement");            }        }    }    op1 = v >> 8;    if (op1)        g(op1);    g(v);            /* search which operand will used for modrm */    modrm_index = 0;    if (pa->instr_type & OPC_SHIFT) {        reg = (opcode - pa->sym) >> 2;         if (reg == 6)            reg = 7;    } else if (pa->instr_type & OPC_ARITH) {        reg = (opcode - pa->sym) >> 2;    } else if (pa->instr_type & OPC_FARITH) {        reg = (opcode - pa->sym) / 6;    } else {        reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;    }    if (pa->instr_type & OPC_MODRM) {        /* first look for an ea operand */        for(i = 0;i < nb_ops; i++) {            if (op_type[i] & OP_EA)                goto modrm_found;        }        /* then if not found, a register or indirection (shift instructions) */        for(i = 0;i < nb_ops; i++) {            if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))                goto modrm_found;        }#ifdef ASM_DEBUG        error("bad op table");#endif          modrm_found:        modrm_index = i;        /* if a register is used in another operand then it is           used instead of group */        for(i = 0;i < nb_ops; i++) {            v = op_type[i];            if (i != modrm_index &&                 (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {                reg = ops[i].reg;                break;            }        }        asm_modrm(reg, &ops[modrm_index]);    }    /* emit constants */    if (pa->opcode == 0x9a || pa->opcode == 0xea) {        /* ljmp or lcall kludge */        gen_expr32(&ops[1].e);        if (ops[0].e.sym)            error("cannot relocate");        gen_le16(ops[0].e.v);    } else {        for(i = 0;i < nb_ops; i++) {            v = op_type[i];            if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {                /* if multiple sizes are given it means we must look                   at the op size */                if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||                    v == (OP_IM16 | OP_IM32)) {                    if (ss == 0)                        v = OP_IM8;                    else if (ss == 1)                        v = OP_IM16;                    else                        v = OP_IM32;                }                if (v & (OP_IM8 | OP_IM8S)) {                    if (ops[i].e.sym)                        goto error_relocate;                    g(ops[i].e.v);                } else if (v & OP_IM16) {                    if (ops[i].e.sym) {                    error_relocate:                        error("cannot relocate");                    }                    gen_le16(ops[i].e.v);                } else {                    if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {                        if (is_short_jmp)                            g(ops[i].e.v);                        else                            gen_disp32(&ops[i].e);                    } else {                        gen_expr32(&ops[i].e);                    }                }            }        }    }}#define NB_SAVED_REGS 3#define NB_ASM_REGS 8/* return the constraint priority (we allocate first the lowest   numbered constraints) */static inline int constraint_priority(const char *str){    int priority, c, pr;    /* we take the lowest priority */    priority = 0;    for(;;) {        c = *str;        if (c == '\0')            break;        str++;        switch(c) {        case 'A':            pr = 0;            break;        case 'a':        case 'b':        case 'c':        case 'd':        case 'S':        case 'D':            pr = 1;            break;        case 'q':            pr = 2;            break;        case 'r':            pr = 3;            break;        case 'N':        case 'M':        case 'I':        case 'i':        case 'm':        case 'g':            pr = 4;            break;        default:            error("unknown constraint '%c'", c);            pr = 0;        }        if (pr > priority)            priority = pr;    }    return priority;}static const char *skip_constraint_modifiers(const char *p){    while (*p == '=' || *p == '&' || *p == '+' || *p == '%')        p++;    return p;}#define REG_OUT_MASK 0x01#define REG_IN_MASK  0x02#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)static void asm_compute_constraints(ASMOperand *operands,                                     int nb_operands, int nb_outputs,                                     const uint8_t *clobber_regs,                                    int *pout_reg){    ASMOperand *op;    int sorted_op[MAX_ASM_OPERANDS];    int i, j, k, p1, p2, tmp, reg, c, reg_mask;    const char *str;    uint8_t regs_allocated[NB_ASM_REGS];        /* init fields */    for(i=0;i<nb_operands;i++) {        op = &operands[i];        op->input_index = -1;        op->ref_index = -1;        op->reg = -1;        op->is_memory = 0;        op->is_rw = 0;    }    /* compute constraint priority and evaluate references to output       constraints if input constraints */    for(i=0;i<nb_operands;i++) {

⌨️ 快捷键说明

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