Subversion Repositories Kolibri OS

Rev

Rev 647 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 647 Rev 6429
Line 16... Line 16...
16
 * You should have received a copy of the GNU Lesser General Public
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
19
 */
Line -... Line 20...
-
 
20
 
-
 
21
#include "tcc.h"
-
 
22
#ifdef CONFIG_TCC_ASM
20
 
23
 
21
static int asm_get_local_label_name(TCCState *s1, unsigned int n)
24
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
22
{
25
{
23
    char buf[64];
26
    char buf[64];
Line 24... Line 27...
24
    TokenSym *ts;
27
    TokenSym *ts;
25
 
28
 
26
    snprintf(buf, sizeof(buf), "L..%u", n);
29
    snprintf(buf, sizeof(buf), "L..%u", n);
27
    ts = tok_alloc(buf, strlen(buf));
30
    ts = tok_alloc(buf, strlen(buf));
Line 28... Line 31...
28
    return ts->tok;
31
    return ts->tok;
-
 
32
}
-
 
33
 
Line 29... Line 34...
29
}
34
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
30
 
35
static int tcc_assemble_internal(TCCState *s1, int do_preprocess);
Line 31... Line 36...
31
static void asm_expr(TCCState *s1, ExprValue *pe);
36
static Sym sym_dot;
Line 39... Line 44...
39
    int op, n, label;
44
    int op, n, label;
40
    const char *p;
45
    const char *p;
Line 41... Line 46...
41
 
46
 
42
    switch(tok) {
47
    switch(tok) {
43
    case TOK_PPNUM:
48
    case TOK_PPNUM:
44
        p = tokc.cstr->data;
49
        p = tokc.str.data;
45
        n = strtoul(p, (char **)&p, 0);
50
        n = strtoul(p, (char **)&p, 0);
46
        if (*p == 'b' || *p == 'f') {
51
        if (*p == 'b' || *p == 'f') {
47
            /* backward or forward label */
52
            /* backward or forward label */
48
            label = asm_get_local_label_name(s1, n);
53
            label = asm_get_local_label_name(s1, n);
49
            sym = label_find(label);
54
            sym = label_find(label);
50
            if (*p == 'b') {
55
            if (*p == 'b') {
51
                /* backward : find the last corresponding defined label */
56
                /* backward : find the last corresponding defined label */
52
                if (sym && sym->r == 0)
57
                if (sym && sym->r == 0)
53
                    sym = sym->prev_tok;
58
                    sym = sym->prev_tok;
54
                if (!sym)
59
                if (!sym)
55
                    error("local label '%d' not found backward", n);
60
                    tcc_error("local label '%d' not found backward", n);
56
            } else {
61
            } else {
57
                /* forward */
62
                /* forward */
58
                if (!sym || sym->r) {
63
                if (!sym || sym->r) {
59
                    /* if the last label is defined, then define a new one */
64
                    /* if the last label is defined, then define a new one */
Line 65... Line 70...
65
            pe->sym = sym;
70
            pe->sym = sym;
66
        } else if (*p == '\0') {
71
        } else if (*p == '\0') {
67
            pe->v = n;
72
            pe->v = n;
68
            pe->sym = NULL;
73
            pe->sym = NULL;
69
        } else {
74
        } else {
70
            error("invalid number syntax");
75
            tcc_error("invalid number syntax");
71
        }
76
        }
72
        next();
77
        next();
73
        break;
78
        break;
74
    case '+':
79
    case '+':
75
        next();
80
        next();
Line 79... Line 84...
79
    case '~':
84
    case '~':
80
        op = tok;
85
        op = tok;
81
        next();
86
        next();
82
        asm_expr_unary(s1, pe);
87
        asm_expr_unary(s1, pe);
83
        if (pe->sym)
88
        if (pe->sym)
84
            error("invalid operation with label");
89
            tcc_error("invalid operation with label");
85
        if (op == '-')
90
        if (op == '-')
86
            pe->v = -pe->v;
91
            pe->v = -pe->v;
87
        else
92
        else
88
            pe->v = ~pe->v;
93
            pe->v = ~pe->v;
89
        break;
94
        break;
Line 96... Line 101...
96
    case '(':
101
    case '(':
97
        next();
102
        next();
98
        asm_expr(s1, pe);
103
        asm_expr(s1, pe);
99
        skip(')');
104
        skip(')');
100
        break;
105
        break;
-
 
106
    case '.':
-
 
107
        pe->v = 0;
-
 
108
        pe->sym = &sym_dot;
-
 
109
        sym_dot.type.t = VT_VOID | VT_STATIC;
-
 
110
        sym_dot.r = cur_text_section->sh_num;
-
 
111
        sym_dot.jnext = ind;
-
 
112
        next();
-
 
113
        break;
101
    default:
114
    default:
102
        if (tok >= TOK_IDENT) {
115
        if (tok >= TOK_IDENT) {
103
            /* label case : if the label was not found, add one */
116
            /* label case : if the label was not found, add one */
104
            sym = label_find(tok);
117
            sym = label_find(tok);
105
            if (!sym) {
118
            if (!sym) {
Line 107... Line 120...
107
                /* NOTE: by default, the symbol is global */
120
                /* NOTE: by default, the symbol is global */
108
                sym->type.t = VT_VOID;
121
                sym->type.t = VT_VOID;
109
            }
122
            }
110
            if (sym->r == SHN_ABS) {
123
            if (sym->r == SHN_ABS) {
111
                /* if absolute symbol, no need to put a symbol value */
124
                /* if absolute symbol, no need to put a symbol value */
112
                pe->v = (long)sym->next;
125
                pe->v = sym->jnext;
113
                pe->sym = NULL;
126
                pe->sym = NULL;
114
            } else {
127
            } else {
115
                pe->v = 0;
128
                pe->v = 0;
116
                pe->sym = sym;
129
                pe->sym = sym;
117
            }
130
            }
118
            next();
131
            next();
119
        } else {
132
        } else {
120
            error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
133
            tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
121
        }
134
        }
122
        break;
135
        break;
123
    }
136
    }
124
}
137
}
Line 135... Line 148...
135
            op != TOK_SHL && op != TOK_SAR)
148
            op != TOK_SHL && op != TOK_SAR)
136
            break;
149
            break;
137
        next();
150
        next();
138
        asm_expr_unary(s1, &e2);
151
        asm_expr_unary(s1, &e2);
139
        if (pe->sym || e2.sym)
152
        if (pe->sym || e2.sym)
140
            error("invalid operation with label");
153
            tcc_error("invalid operation with label");
141
        switch(op) {
154
        switch(op) {
142
        case '*':
155
        case '*':
143
            pe->v *= e2.v;
156
            pe->v *= e2.v;
144
            break;
157
            break;
145
        case '/':  
158
        case '/':  
146
            if (e2.v == 0) {
159
            if (e2.v == 0) {
147
            div_error:
160
            div_error:
148
                error("division by zero");
161
                tcc_error("division by zero");
149
            }
162
            }
150
            pe->v /= e2.v;
163
            pe->v /= e2.v;
151
            break;
164
            break;
152
        case '%':  
165
        case '%':  
153
            if (e2.v == 0)
166
            if (e2.v == 0)
Line 176... Line 189...
176
        if (op != '&' && op != '|' && op != '^')
189
        if (op != '&' && op != '|' && op != '^')
177
            break;
190
            break;
178
        next();
191
        next();
179
        asm_expr_prod(s1, &e2);
192
        asm_expr_prod(s1, &e2);
180
        if (pe->sym || e2.sym)
193
        if (pe->sym || e2.sym)
181
            error("invalid operation with label");
194
            tcc_error("invalid operation with label");
182
        switch(op) {
195
        switch(op) {
183
        case '&':
196
        case '&':
184
            pe->v &= e2.v;
197
            pe->v &= e2.v;
185
            break;
198
            break;
186
        case '|':  
199
        case '|':  
Line 223... Line 236...
223
            } else if (pe->sym && e2.sym) {
236
            } else if (pe->sym && e2.sym) {
224
                if (pe->sym == e2.sym) { 
237
                if (pe->sym == e2.sym) { 
225
                    /* OK */
238
                    /* OK */
226
                } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
239
                } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
227
                    /* we also accept defined symbols in the same section */
240
                    /* we also accept defined symbols in the same section */
228
                    pe->v += (long)pe->sym->next - (long)e2.sym->next;
241
                    pe->v += pe->sym->jnext - e2.sym->jnext;
229
                } else {
242
                } else {
230
                    goto cannot_relocate;
243
                    goto cannot_relocate;
231
                }
244
                }
232
                pe->sym = NULL; /* same symbols can be substracted to NULL */
245
                pe->sym = NULL; /* same symbols can be subtracted to NULL */
233
            } else {
246
            } else {
234
            cannot_relocate:
247
            cannot_relocate:
235
                error("invalid operation with label");
248
                tcc_error("invalid operation with label");
236
            }
249
            }
237
        }
250
        }
238
    }
251
    }
239
}
252
}
Line 240... Line 253...
240
 
253
 
241
static void asm_expr(TCCState *s1, ExprValue *pe)
254
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
242
{
255
{
243
    asm_expr_sum(s1, pe);
256
    asm_expr_sum(s1, pe);
Line 244... Line 257...
244
}
257
}
245
 
258
 
246
static int asm_int_expr(TCCState *s1)
259
ST_FUNC int asm_int_expr(TCCState *s1)
247
{
260
{
248
    ExprValue e;
261
    ExprValue e;
249
    asm_expr(s1, &e);
262
    asm_expr(s1, &e);
Line 262... Line 275...
262
    sym = label_find(label);
275
    sym = label_find(label);
263
    if (sym) {
276
    if (sym) {
264
        if (sym->r) {
277
        if (sym->r) {
265
            /* the label is already defined */
278
            /* the label is already defined */
266
            if (!is_local) {
279
            if (!is_local) {
267
                error("assembler label '%s' already defined", 
280
                tcc_error("assembler label '%s' already defined", 
268
                      get_tok_str(label, NULL));
281
                      get_tok_str(label, NULL));
269
            } else {
282
            } else {
270
                /* redefinition of local labels is possible */
283
                /* redefinition of local labels is possible */
271
                goto new_label;
284
                goto new_label;
272
            }
285
            }
Line 275... Line 288...
275
    new_label:
288
    new_label:
276
        sym = label_push(&s1->asm_labels, label, 0);
289
        sym = label_push(&s1->asm_labels, label, 0);
277
        sym->type.t = VT_STATIC | VT_VOID;
290
        sym->type.t = VT_STATIC | VT_VOID;
278
    }
291
    }
279
    sym->r = sh_num;
292
    sym->r = sh_num;
280
    sym->next = (void *)value;
293
    sym->jnext = value;
281
}
294
}
Line 282... Line 295...
282
 
295
 
283
static void asm_new_label(TCCState *s1, int label, int is_local)
296
static void asm_new_label(TCCState *s1, int label, int is_local)
284
{
297
{
Line 296... Line 309...
296
        if (s->r) {
309
        if (s->r) {
297
            if (s->r == SHN_ABS)
310
            if (s->r == SHN_ABS)
298
                sec = SECTION_ABS;
311
                sec = SECTION_ABS;
299
            else
312
            else
300
                sec = st->sections[s->r];
313
                sec = st->sections[s->r];
301
            put_extern_sym2(s, sec, (long)s->next, 0, 0);
314
            put_extern_sym2(s, sec, s->jnext, 0, 0);
302
        }
315
        }
303
        /* remove label */
316
        /* remove label */
304
        table_ident[s->v - TOK_IDENT]->sym_label = NULL;
317
        table_ident[s->v - TOK_IDENT]->sym_label = NULL;
305
        sym_free(s);
318
        sym_free(s);
306
    }
319
    }
Line 326... Line 339...
326
    int n, offset, v, size, tok1;
339
    int n, offset, v, size, tok1;
327
    Section *sec;
340
    Section *sec;
328
    uint8_t *ptr;
341
    uint8_t *ptr;
Line 329... Line 342...
329
 
342
 
330
    /* assembler directive */
-
 
331
    next();
343
    /* assembler directive */
332
    sec = cur_text_section;
344
    sec = cur_text_section;
333
    switch(tok) {
345
    switch(tok) {
-
 
346
    case TOK_ASMDIR_align:
334
    case TOK_ASM_align:
347
    case TOK_ASMDIR_p2align:
335
    case TOK_ASM_skip:
348
    case TOK_ASMDIR_skip:
336
    case TOK_ASM_space:
349
    case TOK_ASMDIR_space:
337
        tok1 = tok;
350
        tok1 = tok;
338
        next();
351
        next();
-
 
352
        n = asm_int_expr(s1);
-
 
353
        if (tok1 == TOK_ASMDIR_p2align)
-
 
354
        {
-
 
355
            if (n < 0 || n > 30)
-
 
356
                tcc_error("invalid p2align, must be between 0 and 30");
-
 
357
            n = 1 << n;
-
 
358
            tok1 = TOK_ASMDIR_align;
339
        n = asm_int_expr(s1);
359
        }
340
        if (tok1 == TOK_ASM_align) {
360
        if (tok1 == TOK_ASMDIR_align) {
341
            if (n < 0 || (n & (n-1)) != 0)
361
            if (n < 0 || (n & (n-1)) != 0)
342
                error("alignment must be a positive power of two");
362
                tcc_error("alignment must be a positive power of two");
343
            offset = (ind + n - 1) & -n;
363
            offset = (ind + n - 1) & -n;
344
            size = offset - ind;
364
            size = offset - ind;
345
            /* the section must have a compatible alignment */
365
            /* the section must have a compatible alignment */
346
            if (sec->sh_addralign < n)
366
            if (sec->sh_addralign < n)
Line 359... Line 379...
359
            ptr = section_ptr_add(sec, size);
379
            ptr = section_ptr_add(sec, size);
360
            memset(ptr, v, size);
380
            memset(ptr, v, size);
361
        }
381
        }
362
        ind += size;
382
        ind += size;
363
        break;
383
        break;
364
    case TOK_ASM_quad:
384
    case TOK_ASMDIR_quad:
365
        next();
385
        next();
366
        for(;;) {
386
        for(;;) {
367
            uint64_t vl;
387
            uint64_t vl;
368
            const char *p;
388
            const char *p;
Line 369... Line 389...
369
 
389
 
370
            p = tokc.cstr->data;
390
            p = tokc.str.data;
371
            if (tok != TOK_PPNUM) {
391
            if (tok != TOK_PPNUM) {
372
            error_constant:
392
            error_constant:
373
                error("64 bit constant");
393
                tcc_error("64 bit constant");
374
            }
394
            }
375
            vl = strtoll(p, (char **)&p, 0);
395
            vl = strtoll(p, (char **)&p, 0);
376
            if (*p != '\0')
396
            if (*p != '\0')
377
                goto error_constant;
397
                goto error_constant;
Line 386... Line 406...
386
            if (tok != ',')
406
            if (tok != ',')
387
                break;
407
                break;
388
            next();
408
            next();
389
        }
409
        }
390
        break;
410
        break;
391
    case TOK_ASM_byte:
411
    case TOK_ASMDIR_byte:
392
        size = 1;
412
        size = 1;
393
        goto asm_data;
413
        goto asm_data;
394
    case TOK_ASM_word:
414
    case TOK_ASMDIR_word:
395
    case TOK_SHORT:
415
    case TOK_ASMDIR_short:
396
        size = 2;
416
        size = 2;
397
        goto asm_data;
417
        goto asm_data;
398
    case TOK_LONG:
418
    case TOK_ASMDIR_long:
399
    case TOK_INT:
419
    case TOK_ASMDIR_int:
400
        size = 4;
420
        size = 4;
401
    asm_data:
421
    asm_data:
402
        next();
422
        next();
403
        for(;;) {
423
        for(;;) {
404
            ExprValue e;
424
            ExprValue e;
Line 420... Line 440...
420
            if (tok != ',')
440
            if (tok != ',')
421
                break;
441
                break;
422
            next();
442
            next();
423
        }
443
        }
424
        break;
444
        break;
425
    case TOK_ASM_fill:
445
    case TOK_ASMDIR_fill:
426
        {
446
        {
427
            int repeat, size, val, i, j;
447
            int repeat, size, val, i, j;
428
            uint8_t repeat_buf[8];
448
            uint8_t repeat_buf[8];
429
            next();
449
            next();
430
            repeat = asm_int_expr(s1);
450
            repeat = asm_int_expr(s1);
431
            if (repeat < 0) {
451
            if (repeat < 0) {
432
                error("repeat < 0; .fill ignored");
452
                tcc_error("repeat < 0; .fill ignored");
433
                break;
453
                break;
434
            }
454
            }
435
            size = 1;
455
            size = 1;
436
            val = 0;
456
            val = 0;
437
            if (tok == ',') {
457
            if (tok == ',') {
438
                next();
458
                next();
439
                size = asm_int_expr(s1);
459
                size = asm_int_expr(s1);
440
                if (size < 0) {
460
                if (size < 0) {
441
                    error("size < 0; .fill ignored");
461
                    tcc_error("size < 0; .fill ignored");
442
                    break;
462
                    break;
443
                }
463
                }
444
                if (size > 8)
464
                if (size > 8)
445
                    size = 8;
465
                    size = 8;
446
                if (tok == ',') {
466
                if (tok == ',') {
Line 462... Line 482...
462
                    g(repeat_buf[j]);
482
                    g(repeat_buf[j]);
463
                }
483
                }
464
            }
484
            }
465
        }
485
        }
466
        break;
486
        break;
-
 
487
    case TOK_ASMDIR_rept:
-
 
488
        {
-
 
489
            int repeat;
-
 
490
            TokenString init_str;
-
 
491
            ParseState saved_parse_state = {0};
-
 
492
            next();
-
 
493
            repeat = asm_int_expr(s1);
-
 
494
            tok_str_new(&init_str);
-
 
495
            next();
-
 
496
            while ((tok != TOK_ASMDIR_endr) && (tok != CH_EOF)) {
-
 
497
                tok_str_add_tok(&init_str);
-
 
498
                next();
-
 
499
            }
-
 
500
            if (tok == CH_EOF) tcc_error("we at end of file, .endr not found");
-
 
501
            next();
-
 
502
            tok_str_add(&init_str, -1);
-
 
503
            tok_str_add(&init_str, 0);
-
 
504
            save_parse_state(&saved_parse_state);
-
 
505
            begin_macro(&init_str, 0);
-
 
506
            while (repeat-- > 0) {
-
 
507
                tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS));
-
 
508
                macro_ptr = init_str.str;
-
 
509
            }
-
 
510
            end_macro();
-
 
511
            restore_parse_state(&saved_parse_state);
-
 
512
            break;
-
 
513
        }
467
    case TOK_ASM_org:
514
    case TOK_ASMDIR_org:
468
        {
515
        {
469
            unsigned long n;
516
            unsigned long n;
470
            next();
517
            next();
471
            /* XXX: handle section symbols too */
518
            /* XXX: handle section symbols too */
472
            n = asm_int_expr(s1);
519
            n = asm_int_expr(s1);
473
            if (n < ind)
520
            if (n < ind)
474
                error("attempt to .org backwards");
521
                tcc_error("attempt to .org backwards");
475
            v = 0;
522
            v = 0;
476
            size = n - ind;
523
            size = n - ind;
477
            goto zero_pad;
524
            goto zero_pad;
478
        }
525
        }
479
        break;
526
        break;
480
    case TOK_ASM_globl:
527
    case TOK_ASMDIR_globl:
481
    case TOK_ASM_global:
528
    case TOK_ASMDIR_global:
-
 
529
    case TOK_ASMDIR_weak:
-
 
530
    case TOK_ASMDIR_hidden:
-
 
531
    tok1 = tok;
482
	{ 
532
	do { 
483
            Sym *sym;
533
            Sym *sym;
Line 484... Line 534...
484
 
534
 
485
            next();
535
            next();
486
            sym = label_find(tok);
536
            sym = label_find(tok);
487
            if (!sym) {
537
            if (!sym) {
488
                sym = label_push(&s1->asm_labels, tok, 0);
538
                sym = label_push(&s1->asm_labels, tok, 0);
489
                sym->type.t = VT_VOID;
539
                sym->type.t = VT_VOID;
-
 
540
            }
490
            }
541
	    if (tok1 != TOK_ASMDIR_hidden)
-
 
542
                sym->type.t &= ~VT_STATIC;
-
 
543
            if (tok1 == TOK_ASMDIR_weak)
-
 
544
                sym->type.t |= VT_WEAK;
-
 
545
	    else if (tok1 == TOK_ASMDIR_hidden)
491
            sym->type.t &= ~VT_STATIC;
546
	        sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
492
            next();
547
            next();
493
	}
548
	} while (tok == ',');
494
	break;
549
	break;
495
    case TOK_ASM_string:
550
    case TOK_ASMDIR_string:
496
    case TOK_ASM_ascii:
551
    case TOK_ASMDIR_ascii:
497
    case TOK_ASM_asciz:
552
    case TOK_ASMDIR_asciz:
498
        {
553
        {
499
            const uint8_t *p;
554
            const uint8_t *p;
Line 500... Line 555...
500
            int i, size, t;
555
            int i, size, t;
501
 
556
 
502
            t = tok;
557
            t = tok;
503
            next();
558
            next();
504
            for(;;) {
559
            for(;;) {
505
                if (tok != TOK_STR)
560
                if (tok != TOK_STR)
506
                    expect("string constant");
561
                    expect("string constant");
507
                p = tokc.cstr->data;
562
                p = tokc.str.data;
508
                size = tokc.cstr->size;
563
                size = tokc.str.size;
509
                if (t == TOK_ASM_ascii && size > 0)
564
                if (t == TOK_ASMDIR_ascii && size > 0)
510
                    size--;
565
                    size--;
511
                for(i = 0; i < size; i++)
566
                for(i = 0; i < size; i++)
512
                    g(p[i]);
567
                    g(p[i]);
Line 517... Line 572...
517
                    break;
572
                    break;
518
                }
573
                }
519
            }
574
            }
520
	}
575
	}
521
	break;
576
	break;
522
    case TOK_ASM_text:
577
    case TOK_ASMDIR_text:
523
    case TOK_ASM_data:
578
    case TOK_ASMDIR_data:
524
    case TOK_ASM_bss:
579
    case TOK_ASMDIR_bss:
525
	{ 
580
	{ 
526
            char sname[64];
581
            char sname[64];
527
            tok1 = tok;
582
            tok1 = tok;
528
            n = 0;
583
            n = 0;
529
            next();
584
            next();
530
            if (tok != ';' && tok != TOK_LINEFEED) {
585
            if (tok != ';' && tok != TOK_LINEFEED) {
531
		n = asm_int_expr(s1);
586
		n = asm_int_expr(s1);
532
		next();
587
		next();
533
            }
588
            }
-
 
589
            if (n)
534
            sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
590
                sprintf(sname, "%s%d", get_tok_str(tok1, NULL), n);
-
 
591
            else
-
 
592
                sprintf(sname, "%s", get_tok_str(tok1, NULL));
535
            use_section(s1, sname);
593
            use_section(s1, sname);
536
	}
594
	}
537
	break;
595
	break;
-
 
596
    case TOK_ASMDIR_file:
-
 
597
        {
-
 
598
            char filename[512];
-
 
599
 
-
 
600
            filename[0] = '\0';
-
 
601
            next();
-
 
602
 
-
 
603
            if (tok == TOK_STR)
-
 
604
                pstrcat(filename, sizeof(filename), tokc.str.data);
-
 
605
            else
-
 
606
                pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL));
-
 
607
 
-
 
608
            if (s1->warn_unsupported)
-
 
609
                tcc_warning("ignoring .file %s", filename);
-
 
610
 
-
 
611
            next();
-
 
612
        }
-
 
613
        break;
-
 
614
    case TOK_ASMDIR_ident:
-
 
615
        {
-
 
616
            char ident[256];
-
 
617
 
-
 
618
            ident[0] = '\0';
-
 
619
            next();
-
 
620
 
-
 
621
            if (tok == TOK_STR)
-
 
622
                pstrcat(ident, sizeof(ident), tokc.str.data);
-
 
623
            else
-
 
624
                pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL));
-
 
625
 
-
 
626
            if (s1->warn_unsupported)
-
 
627
                tcc_warning("ignoring .ident %s", ident);
-
 
628
 
-
 
629
            next();
-
 
630
        }
-
 
631
        break;
-
 
632
    case TOK_ASMDIR_size:
-
 
633
        { 
-
 
634
            Sym *sym;
-
 
635
 
-
 
636
            next();
-
 
637
            sym = label_find(tok);
-
 
638
            if (!sym) {
-
 
639
                tcc_error("label not found: %s", get_tok_str(tok, NULL));
-
 
640
            }
-
 
641
 
-
 
642
            /* XXX .size name,label2-label1 */
-
 
643
            if (s1->warn_unsupported)
-
 
644
                tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
-
 
645
 
-
 
646
            next();
-
 
647
            skip(',');
-
 
648
            while (tok != '\n' && tok != CH_EOF) {
-
 
649
                next();
-
 
650
            }
-
 
651
        }
-
 
652
        break;
538
    case TOK_SECTION1:
653
    case TOK_ASMDIR_type:
-
 
654
        { 
-
 
655
            Sym *sym;
-
 
656
            const char *newtype;
-
 
657
 
-
 
658
            next();
-
 
659
            sym = label_find(tok);
-
 
660
            if (!sym) {
-
 
661
                sym = label_push(&s1->asm_labels, tok, 0);
-
 
662
                sym->type.t = VT_VOID;
-
 
663
            }
-
 
664
 
-
 
665
            next();
-
 
666
            skip(',');
-
 
667
            if (tok == TOK_STR) {
-
 
668
                newtype = tokc.str.data;
-
 
669
            } else {
-
 
670
                if (tok == '@' || tok == '%')
-
 
671
                    next();
-
 
672
                newtype = get_tok_str(tok, NULL);
-
 
673
            }
-
 
674
 
-
 
675
            if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
-
 
676
                sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
-
 
677
            }
-
 
678
            else if (s1->warn_unsupported)
-
 
679
                tcc_warning("change type of '%s' from 0x%x to '%s' ignored", 
-
 
680
                    get_tok_str(sym->v, NULL), sym->type.t, newtype);
-
 
681
 
-
 
682
            next();
-
 
683
        }
-
 
684
        break;
-
 
685
    case TOK_ASMDIR_section:
539
        {
686
        {
540
            char sname[256];
687
            char sname[256];
Line 541... Line 688...
541
 
688
 
542
            /* XXX: support more options */
689
            /* XXX: support more options */
543
            next();
690
            next();
544
            sname[0] = '\0';
691
            sname[0] = '\0';
545
            while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
692
            while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
546
                if (tok == TOK_STR)
693
                if (tok == TOK_STR)
547
                    pstrcat(sname, sizeof(sname), tokc.cstr->data);
694
                    pstrcat(sname, sizeof(sname), tokc.str.data);
548
                else
695
                else
549
                    pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
696
                    pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
550
                next();
697
                next();
551
            }
698
            }
552
            if (tok == ',') {
699
            if (tok == ',') {
553
                /* skip section options */
700
                /* skip section options */
554
                next();
701
                next();
555
                if (tok != TOK_STR)
702
                if (tok != TOK_STR)
556
                    expect("string constant");
703
                    expect("string constant");
-
 
704
                next();
-
 
705
                if (tok == ',') {
-
 
706
                    next();
-
 
707
                    if (tok == '@' || tok == '%')
-
 
708
                        next();
-
 
709
                    next();
557
                next();
710
                }
558
            }
711
            }
559
            last_text_section = cur_text_section;
712
            last_text_section = cur_text_section;
560
            use_section(s1, sname);
713
            use_section(s1, sname);
561
        }
714
        }
562
        break;
715
        break;
563
    case TOK_ASM_previous:
716
    case TOK_ASMDIR_previous:
564
        { 
717
        { 
565
            Section *sec;
718
            Section *sec;
566
            next();
719
            next();
567
            if (!last_text_section)
720
            if (!last_text_section)
568
                error("no previous section referenced");
721
                tcc_error("no previous section referenced");
569
            sec = cur_text_section;
722
            sec = cur_text_section;
570
            use_section1(s1, last_text_section);
723
            use_section1(s1, last_text_section);
571
            last_text_section = sec;
724
            last_text_section = sec;
572
        }
725
        }
-
 
726
        break;
-
 
727
#ifdef TCC_TARGET_I386
-
 
728
    case TOK_ASMDIR_code16:
-
 
729
        {
-
 
730
            next();
-
 
731
            s1->seg_size = 16;
-
 
732
        }
-
 
733
        break;
-
 
734
    case TOK_ASMDIR_code32:
-
 
735
        {
-
 
736
            next();
-
 
737
            s1->seg_size = 32;
-
 
738
        }
-
 
739
        break;
-
 
740
#endif
-
 
741
#ifdef TCC_TARGET_X86_64
-
 
742
    /* added for compatibility with GAS */
-
 
743
    case TOK_ASMDIR_code64:
-
 
744
        next();
-
 
745
        break;
573
        break;
746
#endif
574
    default:
747
    default:
575
        error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
748
        tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
576
        break;
749
        break;
577
    }
750
    }
Line 617... Line 790...
617
 
790
 
Line 618... Line 791...
618
    /* XXX: undefine C labels */
791
    /* XXX: undefine C labels */
619
 
792
 
620
    ch = file->buf_ptr[0];
793
    ch = file->buf_ptr[0];
621
    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
794
    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
622
    parse_flags = PARSE_FLAG_ASM_COMMENTS;
795
    parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;
623
    if (do_preprocess)
796
    if (do_preprocess)
624
        parse_flags |= PARSE_FLAG_PREPROCESS;
797
        parse_flags |= PARSE_FLAG_PREPROCESS;
625
    next();
798
    next();
Line 630... Line 803...
630
    redo:
803
    redo:
631
        if (tok == '#') {
804
        if (tok == '#') {
632
            /* horrible gas comment */
805
            /* horrible gas comment */
633
            while (tok != TOK_LINEFEED)
806
            while (tok != TOK_LINEFEED)
634
                next();
807
                next();
635
        } else if (tok == '.') {
808
        } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
636
            asm_parse_directive(s1);
809
            asm_parse_directive(s1);
637
        } else if (tok == TOK_PPNUM) {
810
        } else if (tok == TOK_PPNUM) {
638
            const char *p;
811
            const char *p;
639
            int n;
812
            int n;
640
            p = tokc.cstr->data;
813
            p = tokc.str.data;
641
            n = strtoul(p, (char **)&p, 10);
814
            n = strtoul(p, (char **)&p, 10);
642
            if (*p != '\0')
815
            if (*p != '\0')
643
                expect("':'");
816
                expect("':'");
644
            /* new local label */
817
            /* new local label */
645
            asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
818
            asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
Line 677... Line 850...
677
 
850
 
678
    return 0;
851
    return 0;
Line 679... Line 852...
679
}
852
}
680
 
853
 
681
/* Assemble the current file */
854
/* Assemble the current file */
682
static int tcc_assemble(TCCState *s1, int do_preprocess)
855
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
683
{
856
{
Line 684... Line 857...
684
    Sym *define_start;
857
    Sym *define_start;
Line 690... Line 863...
690
    cur_text_section = text_section;
863
    cur_text_section = text_section;
691
    ind = cur_text_section->data_offset;
864
    ind = cur_text_section->data_offset;
Line 692... Line 865...
692
 
865
 
Line -... Line 866...
-
 
866
    define_start = define_stack;
-
 
867
 
-
 
868
    /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
-
 
869
       symbols can be safely used */
-
 
870
    put_elf_sym(symtab_section, 0, 0,
-
 
871
                ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
693
    define_start = define_stack;
872
                SHN_ABS, file->filename);
Line 694... Line 873...
694
 
873
 
Line 695... Line 874...
695
    ret = tcc_assemble_internal(s1, do_preprocess);
874
    ret = tcc_assemble_internal(s1, do_preprocess);
Line 707... Line 886...
707
/* assemble the string 'str' in the current C compilation unit without
886
/* assemble the string 'str' in the current C compilation unit without
708
   C preprocessing. NOTE: str is modified by modifying the '\0' at the
887
   C preprocessing. NOTE: str is modified by modifying the '\0' at the
709
   end */
888
   end */
710
static void tcc_assemble_inline(TCCState *s1, char *str, int len)
889
static void tcc_assemble_inline(TCCState *s1, char *str, int len)
711
{
890
{
712
    BufferedFile *bf, *saved_file;
891
    int saved_parse_flags;
713
    int saved_parse_flags, *saved_macro_ptr;
892
    const int *saved_macro_ptr;
Line 714... Line -...
714
 
-
 
715
    bf = tcc_malloc(sizeof(BufferedFile));
-
 
716
    memset(bf, 0, sizeof(BufferedFile));
-
 
717
    bf->fd = -1;
-
 
718
    bf->buf_ptr = str;
-
 
719
    bf->buf_end = str + len;
-
 
720
    str[len] = CH_EOB;
-
 
721
    /* same name as current file so that errors are correctly
-
 
722
       reported */
-
 
723
    pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
-
 
724
    bf->line_num = file->line_num;
-
 
725
    saved_file = file;
-
 
726
    file = bf;
893
 
727
    saved_parse_flags = parse_flags;
894
    saved_parse_flags = parse_flags;
728
    saved_macro_ptr = macro_ptr;
-
 
Line -... Line 895...
-
 
895
    saved_macro_ptr = macro_ptr;
-
 
896
 
-
 
897
    tcc_open_bf(s1, ":asm:", len);
-
 
898
    memcpy(file->buffer, str, len);
729
    macro_ptr = NULL;
899
 
-
 
900
    macro_ptr = NULL;
Line 730... Line 901...
730
    
901
    tcc_assemble_internal(s1, 0);
731
    tcc_assemble_internal(s1, 0);
902
    tcc_close();
732
 
-
 
733
    parse_flags = saved_parse_flags;
-
 
734
    macro_ptr = saved_macro_ptr;
903
 
Line 735... Line 904...
735
    file = saved_file;
904
    parse_flags = saved_parse_flags;
736
    tcc_free(bf);
905
    macro_ptr = saved_macro_ptr;
737
}
906
}
738
 
907
 
739
/* find a constraint by its number or id (gcc 3 extended
908
/* find a constraint by its number or id (gcc 3 extended
740
   syntax). return -1 if not found. Return in *pp in char after the
909
   syntax). return -1 if not found. Return in *pp in char after the
741
   constraint */
910
   constraint */
742
static int find_constraint(ASMOperand *operands, int nb_operands, 
911
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, 
743
                           const char *name, const char **pp)
912
                           const char *name, const char **pp)
Line 799... Line 968...
799
            if (*str == 'c' || *str == 'n' ||
968
            if (*str == 'c' || *str == 'n' ||
800
                *str == 'b' || *str == 'w' || *str == 'h')
969
                *str == 'b' || *str == 'w' || *str == 'h')
801
                modifier = *str++;
970
                modifier = *str++;
802
            index = find_constraint(operands, nb_operands, str, &str);
971
            index = find_constraint(operands, nb_operands, str, &str);
803
            if (index < 0)
972
            if (index < 0)
804
                error("invalid operand reference after %%");
973
                tcc_error("invalid operand reference after %%");
805
            op = &operands[index];
974
            op = &operands[index];
806
            sv = *op->vt;
975
            sv = *op->vt;
807
            if (op->reg >= 0) {
976
            if (op->reg >= 0) {
808
                sv.r = op->reg;
977
                sv.r = op->reg;
809
                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
978
                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
810
                    sv.r |= VT_LVAL;
979
                    sv.r |= VT_LVAL;
811
            }
980
            }
812
            subst_asm_operand(out_str, &sv, modifier);
981
            subst_asm_operand(out_str, &sv, modifier);
813
        } else {
982
        } else {
814
        add_char:
983
        add_char:
Line 828... Line 997...
828
 
997
 
829
    if (tok != ':') {
998
    if (tok != ':') {
830
        nb_operands = *nb_operands_ptr;
999
        nb_operands = *nb_operands_ptr;
831
        for(;;) {
1000
        for(;;) {
832
            if (nb_operands >= MAX_ASM_OPERANDS)
1001
            if (nb_operands >= MAX_ASM_OPERANDS)
833
                error("too many asm operands");
1002
                tcc_error("too many asm operands");
834
            op = &operands[nb_operands++];
1003
            op = &operands[nb_operands++];
835
            op->id = 0;
1004
            op->id = 0;
836
            if (tok == '[') {
1005
            if (tok == '[') {
837
                next();
1006
                next();
Line 841... Line 1010...
841
                next();
1010
                next();
842
                skip(']');
1011
                skip(']');
843
            }
1012
            }
844
            if (tok != TOK_STR)
1013
            if (tok != TOK_STR)
845
                expect("string constant");
1014
                expect("string constant");
846
            op->constraint = tcc_malloc(tokc.cstr->size);
1015
            op->constraint = tcc_malloc(tokc.str.size);
847
            strcpy(op->constraint, tokc.cstr->data);
1016
            strcpy(op->constraint, tokc.str.data);
848
            next();
1017
            next();
849
            skip('(');
1018
            skip('(');
850
            gexpr();
1019
            gexpr();
851
            if (is_output) {
1020
            if (is_output) {
852
                test_lvalue();
1021
                test_lvalue();
Line 872... Line 1041...
872
        }
1041
        }
873
        *nb_operands_ptr = nb_operands;
1042
        *nb_operands_ptr = nb_operands;
874
    }
1043
    }
875
}
1044
}
Line 876... Line -...
876
 
-
 
877
static void parse_asm_str(CString *astr)
-
 
878
{
-
 
879
    skip('(');
-
 
880
    /* read the string */
-
 
881
    if (tok != TOK_STR)
-
 
882
        expect("string constant");
-
 
883
    cstr_new(astr);
-
 
884
    while (tok == TOK_STR) {
-
 
885
        /* XXX: add \0 handling too ? */
-
 
886
        cstr_cat(astr, tokc.cstr->data);
-
 
887
        next();
-
 
888
    }
-
 
889
    cstr_ccat(astr, '\0');
-
 
890
}
-
 
891
 
1045
 
892
/* parse the GCC asm() instruction */
1046
/* parse the GCC asm() instruction */
893
static void asm_instr(void)
1047
ST_FUNC void asm_instr(void)
894
{
1048
{
895
    CString astr, astr1;
1049
    CString astr, astr1;
896
    ASMOperand operands[MAX_ASM_OPERANDS];
1050
    ASMOperand operands[MAX_ASM_OPERANDS];
897
    int nb_inputs, nb_outputs, nb_operands, i, must_subst, out_reg;
1051
    int nb_outputs, nb_operands, i, must_subst, out_reg;
Line 898... Line 1052...
898
    uint8_t clobber_regs[NB_ASM_REGS];
1052
    uint8_t clobber_regs[NB_ASM_REGS];
899
 
1053
 
900
    next();
1054
    next();
Line 914... Line 1068...
914
        /* output args */
1068
        /* output args */
915
        parse_asm_operands(operands, &nb_operands, 1);
1069
        parse_asm_operands(operands, &nb_operands, 1);
916
        nb_outputs = nb_operands;
1070
        nb_outputs = nb_operands;
917
        if (tok == ':') {
1071
        if (tok == ':') {
918
            next();
1072
            next();
-
 
1073
            if (tok != ')') {
919
            /* input args */
1074
                /* input args */
920
            parse_asm_operands(operands, &nb_operands, 0);
1075
                parse_asm_operands(operands, &nb_operands, 0);
921
            if (tok == ':') {
1076
                if (tok == ':') {
922
                /* clobber list */
1077
                    /* clobber list */
923
                /* XXX: handle registers */
1078
                    /* XXX: handle registers */
924
                next();
1079
                    next();
925
                for(;;) {
1080
                    for(;;) {
926
                    if (tok != TOK_STR)
1081
                        if (tok != TOK_STR)
927
                        expect("string constant");
1082
                            expect("string constant");
928
                    asm_clobber(clobber_regs, tokc.cstr->data);
1083
                        asm_clobber(clobber_regs, tokc.str.data);
929
                    next();
1084
                        next();
930
                    if (tok == ',') {
1085
                        if (tok == ',') {
931
                        next();
1086
                            next();
932
                    } else {
1087
                        } else {
933
                        break;
1088
                            break;
934
                    }
1089
                        }
935
                }
1090
                    }
936
            }
1091
                }
937
        }
1092
            }
938
    }
1093
        }
-
 
1094
    }
939
    skip(')');
1095
    skip(')');
940
    /* NOTE: we do not eat the ';' so that we can restore the current
1096
    /* NOTE: we do not eat the ';' so that we can restore the current
941
       token after the assembler parsing */
1097
       token after the assembler parsing */
942
    if (tok != ';')
1098
    if (tok != ';')
943
        expect("';'");
1099
        expect("';'");
944
    nb_inputs = nb_operands - nb_outputs;
-
 
Line 945... Line 1100...
945
    
1100
    
946
    /* save all values in the memory */
1101
    /* save all values in the memory */
Line 947... Line 1102...
947
    save_regs(0);
1102
    save_regs(0);
Line 987... Line 1142...
987
        vpop();
1142
        vpop();
988
    }
1143
    }
989
    cstr_free(&astr1);
1144
    cstr_free(&astr1);
990
}
1145
}
Line 991... Line 1146...
991
 
1146
 
992
static void asm_global_instr(void)
1147
ST_FUNC void asm_global_instr(void)
993
{
1148
{
Line 994... Line 1149...
994
    CString astr;
1149
    CString astr;
995
 
1150
 
Line 1015... Line 1170...
1015
    /* restore the current C token */
1170
    /* restore the current C token */
1016
    next();
1171
    next();
Line 1017... Line 1172...
1017
 
1172
 
1018
    cstr_free(&astr);
1173
    cstr_free(&astr);
-
 
1174
}