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

📄 tccasm.c

📁 一个GNU的C语言编译器源代码,源代码过万行.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  GAS like assembler for TCC *  *  Copyright (c) 2001, 2002 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 */static int asm_get_local_label_name(TCCState *s1, unsigned int n){    char buf[64];    TokenSym *ts;    snprintf(buf, sizeof(buf), "L..%u", n);    ts = tok_alloc(buf, strlen(buf));    return ts->tok;}/* We do not use the C expression parser to handle symbols. Maybe the   C expression parser could be tweaked to do so. */static void asm_expr_unary(TCCState *s1, ExprValue *pe){    Sym *sym;    int op, n, label;    const char *p;    switch(tok) {    case TOK_PPNUM:        p = tokc.cstr->data;        n = strtoul(p, (char **)&p, 0);        if (*p == 'b' || *p == 'f') {            /* backward or forward label */            label = asm_get_local_label_name(s1, n);            sym = label_find(label);            if (*p == 'b') {                /* backward : find the last corresponding defined label */                if (sym && sym->r == 0)                    sym = sym->prev_tok;                if (!sym)                    error("local label '%d' not found backward", n);            } else {                /* forward */                if (!sym || sym->r) {                    /* if the last label is defined, then define a new one */                    sym = label_push(&s1->asm_labels, label, 0);                    sym->type.t = VT_STATIC | VT_VOID;                }            }            pe->v = 0;            pe->sym = sym;        } else if (*p == '\0') {            pe->v = n;            pe->sym = NULL;        } else {            error("invalid number syntax");        }        next();        break;    case '+':        next();        asm_expr_unary(s1, pe);        break;    case '-':    case '~':        op = tok;        next();        asm_expr_unary(s1, pe);        if (pe->sym)            error("invalid operation with label");        if (op == '-')            pe->v = -pe->v;        else            pe->v = ~pe->v;        break;    case TOK_CCHAR:    case TOK_LCHAR:	pe->v = tokc.i;	pe->sym = NULL;	next();	break;    default:        if (tok >= TOK_IDENT) {            /* label case : if the label was not found, add one */            sym = label_find(tok);            if (!sym) {                sym = label_push(&s1->asm_labels, tok, 0);                /* NOTE: by default, the symbol is global */                sym->type.t = VT_VOID;            }            pe->v = 0;            pe->sym = sym;            next();        } else {            error("bad expression syntax [%s]", get_tok_str(tok, &tokc));        }        break;    }}    static void asm_expr_prod(TCCState *s1, ExprValue *pe){    int op;    ExprValue e2;    asm_expr_unary(s1, pe);    for(;;) {        op = tok;        if (op != '*' && op != '/' && op != '%' &&             op != TOK_SHL && op != TOK_SAR)            break;        next();        asm_expr_unary(s1, &e2);        if (pe->sym || e2.sym)            error("invalid operation with label");        switch(op) {        case '*':            pe->v *= e2.v;            break;        case '/':              if (e2.v == 0) {            div_error:                error("division by zero");            }            pe->v /= e2.v;            break;        case '%':              if (e2.v == 0)                goto div_error;            pe->v %= e2.v;            break;        case TOK_SHL:            pe->v <<= e2.v;            break;        default:        case TOK_SAR:            pe->v >>= e2.v;            break;        }    }}static void asm_expr_logic(TCCState *s1, ExprValue *pe){    int op;    ExprValue e2;    asm_expr_prod(s1, pe);    for(;;) {        op = tok;        if (op != '&' && op != '|' && op != '^')            break;        next();        asm_expr_prod(s1, &e2);        if (pe->sym || e2.sym)            error("invalid operation with label");        switch(op) {        case '&':            pe->v &= e2.v;            break;        case '|':              pe->v |= e2.v;            break;        default:        case '^':            pe->v ^= e2.v;            break;        }    }}static inline void asm_expr_sum(TCCState *s1, ExprValue *pe){    int op;    ExprValue e2;    asm_expr_logic(s1, pe);    for(;;) {        op = tok;        if (op != '+' && op != '-')            break;        next();        asm_expr_logic(s1, &e2);        if (op == '+') {            if (pe->sym != NULL && e2.sym != NULL)                goto cannot_relocate;            pe->v += e2.v;            if (pe->sym == NULL && e2.sym != NULL)                pe->sym = e2.sym;        } else {            pe->v -= e2.v;            /* NOTE: we are less powerful than gas in that case               because we store only one symbol in the expression */            if (!pe->sym && !e2.sym) {                /* OK */            } else if (pe->sym && !e2.sym) {                /* OK */            } else if (pe->sym && e2.sym) {                if (pe->sym == e2.sym) {                     /* OK */                } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {                    /* we also accept defined symbols in the same section */                    pe->v += (long)pe->sym->next - (long)e2.sym->next;                } else {                    goto cannot_relocate;                }                pe->sym = NULL; /* same symbols can be substracted to NULL */            } else {            cannot_relocate:                error("invalid operation with label");            }        }    }}static void asm_expr(TCCState *s1, ExprValue *pe){    asm_expr_sum(s1, pe);}static int asm_int_expr(TCCState *s1){    ExprValue e;    asm_expr(s1, &e);    if (e.sym)        expect("constant");    return e.v;}/* NOTE: the same name space as C labels is used to avoid using too   much memory when storing labels in TokenStrings */static void asm_new_label(TCCState *s1, int label, int is_local){    Sym *sym;    sym = label_find(label);    if (sym) {        if (sym->r) {            /* the label is already defined */            if (!is_local) {                error("assembler label '%s' already defined",                       get_tok_str(label, NULL));            } else {                /* redefinition of local labels is possible */                goto new_label;            }        }    } else {    new_label:        sym = label_push(&s1->asm_labels, label, 0);        sym->type.t = VT_STATIC | VT_VOID;    }    sym->r = cur_text_section->sh_num;    sym->next = (void *)ind;}static void asm_free_labels(TCCState *st){    Sym *s, *s1;    for(s = st->asm_labels; s != NULL; s = s1) {        s1 = s->prev;        /* define symbol value in object file */        if (s->r) {            put_extern_sym(s, st->sections[s->r], (long)s->next, 0);        }        /* remove label */        table_ident[s->v - TOK_IDENT]->sym_label = NULL;        tcc_free(s);    }    st->asm_labels = NULL;}static void use_section(TCCState *s1, const char *name){    Section *sec;    sec = find_section(s1, name);    cur_text_section->data_offset = ind;    cur_text_section = sec;    ind = cur_text_section->data_offset;}static void asm_parse_directive(TCCState *s1){    int n, offset, v, size, tok1;    Section *sec;    uint8_t *ptr;    /* assembler directive */    next();    sec = cur_text_section;    switch(tok) {    case TOK_ASM_align:    case TOK_ASM_skip:    case TOK_ASM_space:        tok1 = tok;        next();        n = asm_int_expr(s1);        if (tok1 == TOK_ASM_align) {            if (n < 0 || (n & (n-1)) != 0)                error("alignment must be a positive power of two");            offset = (ind + n - 1) & -n;            size = offset - ind;        } else {            size = n;        }        v = 0;        if (tok == ',') {            next();            v = asm_int_expr(s1);        }        if (sec->sh_type != SHT_NOBITS) {            sec->data_offset = ind;            ptr = section_ptr_add(sec, size);            memset(ptr, v, size);        }        ind += size;        break;    case TOK_ASM_byte:        size = 1;        goto asm_data;    case TOK_ASM_word:    case TOK_SHORT:        size = 2;        goto asm_data;    case TOK_LONG:    case TOK_INT:        size = 4;    asm_data:        next();        for(;;) {            ExprValue e;            asm_expr(s1, &e);            if (sec->sh_type != SHT_NOBITS) {                if (size == 4) {                    gen_expr32(&e);                } else {                    if (e.sym)                        expect("constant");                    if (size == 1)                        g(e.v);                    else                        gen_le16(e.v);                }            } else {                ind += size;            }            if (tok != ',')                break;            next();        }        break;    case TOK_ASM_globl:	{             Sym *sym;            next();            sym = label_find(tok);            if (!sym) {                sym = label_push(&s1->asm_labels, tok, 0);                sym->type.t = VT_VOID;            }            sym->type.t &= ~VT_STATIC;            next();	}	break;    case TOK_ASM_string:        {            const uint8_t *p;            int i;            next();            if (tok != TOK_STR)                expect("string constant");            p = tokc.cstr->data;            for(i = 0; i < tokc.cstr->size; i++)                g(p[i]);            next();	}	break;    case TOK_ASM_text:    case TOK_ASM_data:    case TOK_ASM_bss:	{             char sname[64];            tok1 = tok;            n = 0;            next();            if (tok != ';' && tok != TOK_LINEFEED) {		n = asm_int_expr(s1);		next();            }            sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);            use_section(s1, sname);	}	break;    case TOK_SECTION1:        {            char sname[256];            /* XXX: support more options */            next();

⌨️ 快捷键说明

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