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

📄 tccasm.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  GAS like assembler for TCC *  *  Copyright (c) 2001-2004 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;}static void asm_expr(TCCState *s1, ExprValue *pe);/* 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;    case '(':        next();        asm_expr(s1, pe);        skip(')');        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;            }            if (sym->r == SHN_ABS) {                /* if absolute symbol, no need to put a symbol value */                pe->v = (long)sym->next;                pe->sym = NULL;            } else {                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_label1(TCCState *s1, int label, int is_local,                           int sh_num, int value){    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 = sh_num;    sym->next = (void *)value;}static void asm_new_label(TCCState *s1, int label, int is_local){    asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);}static void asm_free_labels(TCCState *st){    Sym *s, *s1;    Section *sec;        for(s = st->asm_labels; s != NULL; s = s1) {        s1 = s->prev;        /* define symbol value in object file */        if (s->r) {            if (s->r == SHN_ABS)                sec = SECTION_ABS;            else                sec = st->sections[s->r];            put_extern_sym(s, sec, (long)s->next, 0);        }        /* remove label */        table_ident[s->v - TOK_IDENT]->sym_label = NULL;        sym_free(s);    }    st->asm_labels = NULL;}static void use_section1(TCCState *s1, Section *sec){    cur_text_section->data_offset = ind;    cur_text_section = sec;    ind = cur_text_section->data_offset;}static void use_section(TCCState *s1, const char *name){    Section *sec;    sec = find_section(s1, name);    use_section1(s1, sec);}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;            /* the section must have a compatible alignment */            if (sec->sh_addralign < n)                sec->sh_addralign = n;        } else {            size = n;        }        v = 0;        if (tok == ',') {            next();            v = asm_int_expr(s1);        }    zero_pad:        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_quad:        next();        for(;;) {            uint64_t vl;            const char *p;            p = tokc.cstr->data;            if (tok != TOK_PPNUM) {            error_constant:                error("64 bit constant");            }            vl = strtoll(p, (char **)&p, 0);            if (*p != '\0')                goto error_constant;            next();            if (sec->sh_type != SHT_NOBITS) {                /* XXX: endianness */                gen_le32(vl);                gen_le32(vl >> 32);            } else {                ind += 8;            }            if (tok != ',')                break;            next();        }        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_fill:        {            int repeat, size, val, i, j;            uint8_t repeat_buf[8];            next();            repeat = asm_int_expr(s1);            if (repeat < 0) {                error("repeat < 0; .fill ignored");                break;            }            size = 1;            val = 0;            if (tok == ',') {                next();                size = asm_int_expr(s1);                if (size < 0) {                    error("size < 0; .fill ignored");                    break;                }                if (size > 8)                    size = 8;                if (tok == ',') {                    next();                    val = asm_int_expr(s1);                }            }            /* XXX: endianness */            repeat_buf[0] = val;            repeat_buf[1] = val >> 8;            repeat_buf[2] = val >> 16;            repeat_buf[3] = val >> 24;            repeat_buf[4] = 0;            repeat_buf[5] = 0;            repeat_buf[6] = 0;            repeat_buf[7] = 0;            for(i = 0; i < repeat; i++) {                for(j = 0; j < size; j++) {                    g(repeat_buf[j]);                }            }        }        break;    case TOK_ASM_org:        {            unsigned long n;            next();            /* XXX: handle section symbols too */            n = asm_int_expr(s1);            if (n < ind)                error("attempt to .org backwards");            v = 0;            size = n - ind;            goto zero_pad;        }        break;    case TOK_ASM_globl:    case TOK_ASM_global:	{             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:    case TOK_ASM_ascii:    case TOK_ASM_asciz:        {            const uint8_t *p;            int i, size, t;            t = tok;            next();            for(;;) {                if (tok != TOK_STR)                    expect("string constant");                p = tokc.cstr->data;                size = tokc.cstr->size;                if (t == TOK_ASM_ascii && size > 0)                    size--;

⌨️ 快捷键说明

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