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

📄 tccasm.c

📁 一个GNU的C语言编译器源代码,源代码过万行.
💻 C
📖 第 1 页 / 共 2 页
字号:
            sname[0] = '\0';            while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {                if (tok == TOK_STR)                    pstrcat(sname, sizeof(sname), tokc.cstr->data);                else                    pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));                next();            }            use_section(s1, sname);        }        break;    default:        error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));        break;    }}/* assemble a file */static int tcc_assemble_internal(TCCState *s1, int do_preprocess){    int opcode;#if 0    /* print stats about opcodes */    {        const ASMInstr *pa;        int freq[4];        int op_vals[500];        int nb_op_vals, i, j;        nb_op_vals = 0;        memset(freq, 0, sizeof(freq));        for(pa = asm_instrs; pa->sym != 0; pa++) {            freq[pa->nb_ops]++;            for(i=0;i<pa->nb_ops;i++) {                for(j=0;j<nb_op_vals;j++) {                    if (pa->op_type[i] == op_vals[j])                        goto found;                }                op_vals[nb_op_vals++] = pa->op_type[i];            found: ;            }        }        for(i=0;i<nb_op_vals;i++) {            int v = op_vals[i];            if ((v & (v - 1)) != 0)                printf("%3d: %08x\n", i, v);        }        printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",               sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),               freq[0], freq[1], freq[2], freq[3]);    }#endif    /* XXX: undefine C labels */    ch = file->buf_ptr[0];    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;    parse_flags = 0;    if (do_preprocess)        parse_flags |= PARSE_FLAG_PREPROCESS;    next();    for(;;) {        if (tok == TOK_EOF)            break;        parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */    redo:        if (tok == '#') {            /* horrible gas comment */            while (tok != TOK_LINEFEED)                next();        } else if (tok == '.') {            asm_parse_directive(s1);        } else if (tok == TOK_PPNUM) {            const char *p;            int n;            p = tokc.cstr->data;            n = strtoul(p, (char **)&p, 10);            if (*p != '\0')                expect("':'");            /* new local label */            asm_new_label(s1, asm_get_local_label_name(s1, n), 1);            next();            skip(':');            goto redo;        } else if (tok >= TOK_IDENT) {            /* instruction or label */            opcode = tok;            next();            if (tok == ':') {                /* new label */                asm_new_label(s1, opcode, 0);                next();                goto redo;            } else {                asm_opcode(s1, opcode);            }        }        /* end of line */        if (tok != ';' && tok != TOK_LINEFEED){            expect("end of line");        }        parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */        next();    }    asm_free_labels(s1);    return 0;}/* Assemble the current file */static int tcc_assemble(TCCState *s1, int do_preprocess){    int ret;    preprocess_init(s1);    /* default section is text */    cur_text_section = text_section;    ind = cur_text_section->data_offset;    ret = tcc_assemble_internal(s1, do_preprocess);    cur_text_section->data_offset = ind;    return ret;}/********************************************************************//* GCC inline asm support *//* assemble the string 'str' in the current C compilation unit without   C preprocessing. NOTE: str is modified by modifying the '\0' at the   end */static void tcc_assemble_inline(TCCState *s1, char *str, int len){    BufferedFile *bf, *saved_file;    int saved_parse_flags, *saved_macro_ptr;    bf = tcc_malloc(sizeof(BufferedFile));    memset(bf, 0, sizeof(BufferedFile));    bf->fd = -1;    bf->buf_ptr = str;    bf->buf_end = str + len;    str[len] = CH_EOB;    /* same name as current file so that errors are correctly       reported */    pstrcpy(bf->filename, sizeof(bf->filename), file->filename);    bf->line_num = file->line_num;    saved_file = file;    file = bf;    saved_parse_flags = parse_flags;    saved_macro_ptr = macro_ptr;    macro_ptr = NULL;        tcc_assemble_internal(s1, 0);    parse_flags = saved_parse_flags;    macro_ptr = saved_macro_ptr;    file = saved_file;    tcc_free(bf);}/* find a constraint by its number or id (gcc 3 extended   syntax). return -1 if not found. Return in *pp in char after the   constraint */static int find_constraint(ASMOperand *operands, int nb_operands,                            const char *name, const char **pp){    int index;    TokenSym *ts;    const char *p;    if (isnum(*name)) {        index = 0;        while (isnum(*name)) {            index = (index * 10) + (*name) - '0';            name++;        }        if ((unsigned)index >= nb_operands)            index = -1;    } else if (*name == '[') {        name++;        p = strchr(name, ']');        if (p) {            ts = tok_alloc(name, p - name);            for(index = 0; index < nb_operands; index++) {                if (operands[index].id == ts->tok)                    goto found;            }            index = -1;        found:            name = p + 1;        } else {            index = -1;        }    } else {        index = -1;    }    if (pp)        *pp = name;    return index;}static void subst_asm_operands(ASMOperand *operands, int nb_operands,                                int nb_outputs,                               CString *out_str, CString *in_str){    int c, index, modifier;    const char *str;    ASMOperand *op;    SValue sv;    cstr_new(out_str);    str = in_str->data;    for(;;) {        c = *str++;        if (c == '%') {            if (*str == '%') {                str++;                goto add_char;            }            modifier = 0;            if (*str == 'c' || *str == 'n' ||                *str == 'b' || *str == 'w' || *str == 'h')                modifier = *str++;            index = find_constraint(operands, nb_operands, str, &str);            if (index < 0)                error("invalid operand reference after %%");            op = &operands[index];            sv = *op->vt;            if (op->reg >= 0) {                sv.r = op->reg;                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)                    sv.r |= VT_LVAL;            }            subst_asm_operand(out_str, &sv, modifier);        } else {        add_char:            cstr_ccat(out_str, c);            if (c == '\0')                break;        }    }}static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,                               int is_output){    ASMOperand *op;    int nb_operands;    if (tok != ':') {        nb_operands = *nb_operands_ptr;        for(;;) {            if (nb_operands >= MAX_ASM_OPERANDS)                error("too many asm operands");            op = &operands[nb_operands++];            op->id = 0;            if (tok == '[') {                next();                if (tok < TOK_IDENT)                    expect("identifier");                op->id = tok;                next();                skip(']');            }            if (tok != TOK_STR)                expect("string constant");            op->constraint = tcc_malloc(tokc.cstr->size);            strcpy(op->constraint, tokc.cstr->data);            next();            skip('(');            gexpr();            if (is_output) {                test_lvalue();            } else {                /* we want to avoid LLOCAL case. note that it may come                   from register storage, so we need to convert (reg)                   case */                if ((vtop->r & VT_LVAL) &&                    ((vtop->r & VT_VALMASK) == VT_LLOCAL ||                     (vtop->r & VT_VALMASK) < VT_CONST)) {                    gv(RC_INT);                }            }            op->vt = vtop;            skip(')');            if (tok == ',') {                next();            } else {                break;            }        }        *nb_operands_ptr = nb_operands;    }}/* parse the GCC asm() instruction */static void asm_instr(void){    CString astr, astr1;    ASMOperand operands[MAX_ASM_OPERANDS];    int nb_inputs, nb_outputs, nb_operands, i;    uint8_t input_regs_allocated[NB_ASM_REGS];    uint8_t output_regs_allocated[NB_ASM_REGS];    uint8_t clobber_regs[NB_ASM_REGS];    next();    /* since we always generate the asm() instruction, we can ignore       volatile */    if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {        next();    }    skip('(');    /* read the string */    if (tok != TOK_STR)        expect("string constant");    cstr_new(&astr);    while (tok == TOK_STR) {        /* XXX: add \0 handling too ? */        cstr_cat(&astr, tokc.cstr->data);        next();    }    cstr_ccat(&astr, '\0');    nb_operands = 0;    nb_outputs = 0;    memset(clobber_regs, 0, sizeof(clobber_regs));    if (tok == ':') {        next();        /* output args */        parse_asm_operands(operands, &nb_operands, 1);        nb_outputs = nb_operands;        if (tok == ':') {            next();            /* input args */            parse_asm_operands(operands, &nb_operands, 0);            if (tok == ':') {                /* clobber list */                /* XXX: handle registers */                next();                for(;;) {                    if (tok != TOK_STR)                        expect("string constant");                    asm_clobber(clobber_regs, tokc.cstr->data);                    next();                    if (tok == ',') {                        next();                    } else {                        break;                    }                }            }        }    }    skip(')');    /* NOTE: we do not eat the ';' so that we can restore the current       token after the assembler parsing */    if (tok != ';')        expect("';'");    nb_inputs = nb_operands - nb_outputs;        /* save all values in the memory */    save_regs(0);    /* compute constraints */    asm_compute_constraints(input_regs_allocated,                             operands, nb_operands, nb_outputs, 0,                             NULL);    asm_compute_constraints(output_regs_allocated,                            operands, nb_operands, nb_outputs, 1,                             input_regs_allocated);    /* substitute the operands in the asm string. No substitution is       done if no operands (GCC behaviour) */#ifdef ASM_DEBUG    printf("asm: \"%s\"\n", (char *)astr.data);#endif    if (nb_operands > 0) {        subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);        cstr_free(&astr);    } else {        astr1 = astr;    }#ifdef ASM_DEBUG    printf("subst_asm: \"%s\"\n", (char *)astr1.data);#endif    /* generate loads */    asm_gen_code(operands, nb_operands, nb_outputs, 0, clobber_regs);        /* assemble the string with tcc internal assembler */    tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);    /* restore the current C token */    next();    /* store the output values if needed */    asm_gen_code(operands, nb_operands, nb_outputs, 1, clobber_regs);            /* free everything */    for(i=0;i<nb_operands;i++) {        ASMOperand *op;        op = &operands[i];        tcc_free(op->constraint);        vpop();    }    cstr_free(&astr1);}

⌨️ 快捷键说明

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