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

📄 i386-asm.c

📁 小而快的c编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
        }        if (pr > priority)            priority = pr;    }    return priority;}static const char *skip_constraint_modifiers(const char *p){    while (*p == '=' || *p == '&' || *p == '+' || *p == '%')        p++;    return p;}static void asm_compute_constraints(uint8_t *regs_allocated,                                    ASMOperand *operands,                                     int nb_operands1, int nb_outputs,                                     int is_output,                                    uint8_t *input_regs_allocated){    ASMOperand *op;    int sorted_op[MAX_ASM_OPERANDS];    int i, j, k, p1, p2, tmp, reg, c, base, nb_operands;    const char *str;        if (is_output) {        base = 0;        nb_operands = nb_outputs;    } else {        base = nb_outputs;        nb_operands = nb_operands1 - nb_outputs;    }    /* compute constraint priority and evaluate references to output       constraints if input constraints */    for(i=0;i<nb_operands;i++) {        j = base + i;        op = &operands[j];        str = op->constraint;        op->ref_index = -1;        op->reg = -1;        str = skip_constraint_modifiers(str);        if (!is_output && (isnum(*str) || *str == '[')) {            /* this is a reference to another constraint */            k = find_constraint(operands, nb_operands1, str, NULL);            if ((unsigned)k >= j)                error("invalid reference in constraint %d ('%s')",                      j, str);            op->ref_index = k;            str = operands[k].constraint;            str = skip_constraint_modifiers(str);        }        op->priority = constraint_priority(str);    }        /* sort operands according to their priority */    for(i=0;i<nb_operands;i++)        sorted_op[i] = base + i;    for(i=0;i<nb_operands - 1;i++) {        for(j=i+1;j<nb_operands;j++) {            p1 = operands[sorted_op[i]].priority;             p2 = operands[sorted_op[j]].priority;            if (p2 < p1) {                tmp = sorted_op[i];                sorted_op[i] = sorted_op[j];                sorted_op[j] = tmp;            }        }    }    memset(regs_allocated, 0, NB_ASM_REGS);    regs_allocated[4] = 1; /* esp cannot be used */    regs_allocated[5] = 1; /* ebp cannot be used yet */        /* allocate registers and generate corresponding asm moves */    for(i=0;i<nb_operands;i++) {        j = sorted_op[i];        op = &operands[j];        str = op->constraint;                if (op->ref_index >= 0) {            str = operands[op->ref_index].constraint;        }        str = skip_constraint_modifiers(str);    try_next:        c = *str++;        switch(c) {        case 'A':            /* allocate both eax and edx */            if (regs_allocated[TREG_EAX] || regs_allocated[TREG_EDX])                goto try_next;            op->is_llong = 1;            op->reg = TREG_EAX;            regs_allocated[TREG_EAX] = 1;            regs_allocated[TREG_EDX] = 1;            break;        case 'a':            reg = TREG_EAX;            goto alloc_reg;        case 'b':            reg = 3;            goto alloc_reg;        case 'c':            reg = TREG_ECX;            goto alloc_reg;        case 'd':            reg = TREG_EDX;            goto alloc_reg;        case 'S':            reg = 6;            goto alloc_reg;        case 'D':            reg = 7;        alloc_reg:            if (regs_allocated[reg])                goto try_next;            goto reg_found;        case 'q':            /* eax, ebx, ecx or edx */            for(reg = 0; reg < 4; reg++) {                if (!regs_allocated[reg])                    goto reg_found;            }            goto try_next;        case 'r':            /* any general register */            for(reg = 0; reg < 8; reg++) {                if (!regs_allocated[reg])                    goto reg_found;            }            goto try_next;        reg_found:            /* now we can reload in the register */            op->is_llong = 0;            op->reg = reg;            regs_allocated[reg] = 1;            break;        case 'i':            if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))                goto try_next;            break;        case 'I':        case 'N':        case 'M':            if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))                goto try_next;            break;        case 'm':        case 'g':            /* nothing special to do because the operand is               already in memory */            /* XXX: fix constant case */            if (is_output) {                /* if it is a reference to a memory zone, it must lie                   in a register, so we reserve the register in the                   input registers and a load will be generated                   later */                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {                    /* any general register */                    for(reg = 0; reg < 8; reg++) {                        if (!input_regs_allocated[reg])                            goto reg_found1;                    }                    goto try_next;                reg_found1:                    /* now we can reload in the register */                    input_regs_allocated[reg] = 1;                    op->reg = reg;                }            }            break;        default:            error("asm constraint %d ('%s') could not be satisfied",                   j, op->constraint);            break;        }    }    /* print sorted constraints */#ifdef ASM_DEBUG    if (is_output)        printf("outputs=\n");    else        printf("inputs=\n");    for(i=0;i<nb_operands;i++) {        j = sorted_op[i];        op = &operands[j];        printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",                j,                               op->id ? get_tok_str(op->id, NULL) : "",                op->constraint,               op->vt->r,               op->reg);    }#endif}static void subst_asm_operand(CString *add_str,                               SValue *sv, int modifier){    int r, reg, size, val;    char buf[64];    r = sv->r;    if ((r & VT_VALMASK) == VT_CONST) {        if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')            cstr_ccat(add_str, '$');        if (r & VT_SYM) {            cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));            if (sv->c.i != 0) {                cstr_ccat(add_str, '+');            } else {                return;            }        }        val = sv->c.i;        if (modifier == 'n')            val = -val;        snprintf(buf, sizeof(buf), "%d", sv->c.i);        cstr_cat(add_str, buf);    } else if ((r & VT_VALMASK) == VT_LOCAL) {        snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);        cstr_cat(add_str, buf);    } else if (r & VT_LVAL) {        reg = r & VT_VALMASK;        if (reg >= VT_CONST)            error("internal compiler error");        snprintf(buf, sizeof(buf), "(%%%s)",                  get_tok_str(TOK_ASM_eax + reg, NULL));        cstr_cat(add_str, buf);    } else {        /* register case */        reg = r & VT_VALMASK;        if (reg >= VT_CONST)            error("internal compiler error");        /* choose register operand size */        if ((sv->type.t & VT_BTYPE) == VT_BYTE)            size = 1;        else if ((sv->type.t & VT_BTYPE) == VT_SHORT)            size = 2;        else            size = 4;        if (size == 1 && reg >= 4)            size = 4;        if (modifier == 'b') {            if (reg >= 4)                error("cannot use byte register");            size = 1;        } else if (modifier == 'h') {            if (reg >= 4)                error("cannot use byte register");            size = -1;        } else if (modifier == 'w') {            size = 2;        }        switch(size) {        case -1:            reg = TOK_ASM_ah + reg;            break;        case 1:            reg = TOK_ASM_al + reg;            break;        case 2:            reg = TOK_ASM_ax + reg;            break;        default:            reg = TOK_ASM_eax + reg;            break;        }        snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));        cstr_cat(add_str, buf);    }}/* generate prolog and epilog code for asm statment */static void asm_gen_code(ASMOperand *operands, int nb_operands,                          int nb_outputs, int is_output,                         uint8_t *clobber_regs){    uint8_t regs_allocated[NB_ASM_REGS];    ASMOperand *op;    int i, reg;    static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };    /* mark all used registers */    memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));    for(i = 0; i < nb_operands;i++) {        op = &operands[i];        if (op->reg >= 0)            regs_allocated[op->reg] = 1;    }    if (!is_output) {        /* generate reg save code */        for(i = 0; i < NB_SAVED_REGS; i++) {            reg = reg_saved[i];            if (regs_allocated[reg])                 g(0x50 + reg);        }        /* generate load code */        for(i = nb_outputs ; i < nb_operands; i++) {            op = &operands[i];            if (op->reg >= 0) {                load(op->reg, op->vt);                if (op->is_llong) {                    SValue sv;                    sv = *op->vt;                    sv.c.ul += 4;                    load(TREG_EDX, &sv);                }            }        }        /* generate load code for output memory references */        for(i = 0 ; i < nb_outputs; i++) {            op = &operands[i];            if (op->reg >= 0 && ((op->vt->r & VT_VALMASK) == VT_LLOCAL)) {                SValue sv;                sv = *op->vt;                sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;                load(op->reg, &sv);            }        }    } else {        /* generate save code */        for(i = 0 ; i < nb_outputs; i++) {            op = &operands[i];            if (op->reg >= 0 && ((op->vt->r & VT_VALMASK) != VT_LLOCAL)) {                store(op->reg, op->vt);                if (op->is_llong) {                    SValue sv;                    sv = *op->vt;                    sv.c.ul += 4;                    store(TREG_EDX, &sv);                }            }        }        /* generate reg restore code */        for(i = NB_SAVED_REGS - 1; i >= 0; i--) {            reg = reg_saved[i];            if (regs_allocated[reg])                 g(0x58 + reg);        }    }}static void asm_clobber(uint8_t *clobber_regs, const char *str){    int reg;    TokenSym *ts;    if (!strcmp(str, "memory") ||         !strcmp(str, "cc"))        return;    ts = tok_alloc(str, strlen(str));    reg = ts->tok;    if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {        reg -= TOK_ASM_eax;    } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {        reg -= TOK_ASM_ax;    } else {        error("invalid clobber register '%s'", str);    }    clobber_regs[reg] = 1;}

⌨️ 快捷键说明

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