Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27/tccasm.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/tcc-0.9.27
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/tcc-0.9.27/tccasm.c
r321 r331 32 32 } 33 33 34 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); 34 static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global); 35 static Sym* asm_new_label(TCCState *s1, int label, int is_local); 36 static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value); 37 38 static Sym *asm_label_find(int v) 39 { 40 Sym *sym = sym_find(v); 41 while (sym && sym->sym_scope) 42 sym = sym->prev_tok; 43 return sym; 44 } 45 46 static Sym *asm_label_push(int v) 47 { 48 /* We always add VT_EXTERN, for sym definition that's tentative 49 (for .set, removed for real defs), for mere references it's correct 50 as is. */ 51 Sym *sym = global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0); 52 sym->r = VT_CONST | VT_SYM; 53 return sym; 54 } 55 56 /* Return a symbol we can use inside the assembler, having name NAME. 57 Symbols from asm and C source share a namespace. If we generate 58 an asm symbol it's also a (file-global) C symbol, but it's 59 either not accessible by name (like "L.123"), or its type information 60 is such that it's not usable without a proper C declaration. 61 62 Sometimes we need symbols accessible by name from asm, which 63 are anonymous in C, in this case CSYM can be used to transfer 64 all information from that symbol to the (possibly newly created) 65 asm symbol. */ 66 ST_FUNC Sym* get_asm_sym(int name, Sym *csym) 67 { 68 Sym *sym = asm_label_find(name); 69 if (!sym) { 70 sym = asm_label_push(name); 71 if (csym) 72 sym->c = csym->c; 73 } 74 return sym; 75 } 76 77 static Sym* asm_section_sym(TCCState *s1, Section *sec) 78 { 79 char buf[100]; 80 int label = tok_alloc(buf, 81 snprintf(buf, sizeof buf, "L.%s", sec->name) 82 )->tok; 83 Sym *sym = asm_label_find(label); 84 return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0); 85 } 35 86 36 87 /* We do not use the C expression parser to handle symbols. Maybe the … … 40 91 { 41 92 Sym *sym; 42 int op, n, label; 93 int op, label; 94 uint64_t n; 43 95 const char *p; 44 96 45 97 switch(tok) { 46 98 case TOK_PPNUM: 47 p = tokc. cstr->data;48 n = strtoul (p, (char **)&p, 0);99 p = tokc.str.data; 100 n = strtoull(p, (char **)&p, 0); 49 101 if (*p == 'b' || *p == 'f') { 50 102 /* backward or forward label */ 51 103 label = asm_get_local_label_name(s1, n); 52 sym = label_find(label);104 sym = asm_label_find(label); 53 105 if (*p == 'b') { 54 106 /* backward : find the last corresponding defined label */ 55 if (sym && sym->r == 0)107 if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF)) 56 108 sym = sym->prev_tok; 57 109 if (!sym) … … 59 111 } else { 60 112 /* forward */ 61 if (!sym || sym->r) {113 if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) { 62 114 /* if the last label is defined, then define a new one */ 63 sym = label_push(&s1->asm_labels, label, 0); 64 sym->type.t = VT_STATIC | VT_VOID; 115 sym = asm_label_push(label); 65 116 } 66 117 } 67 pe->v = 0; 68 pe->sym = sym; 118 pe->v = 0; 119 pe->sym = sym; 120 pe->pcrel = 0; 69 121 } else if (*p == '\0') { 70 122 pe->v = n; 71 123 pe->sym = NULL; 124 pe->pcrel = 0; 72 125 } else { 73 126 tcc_error("invalid number syntax"); … … 95 148 pe->v = tokc.i; 96 149 pe->sym = NULL; 150 pe->pcrel = 0; 97 151 next(); 98 152 break; … … 102 156 skip(')'); 103 157 break; 158 case '.': 159 pe->v = ind; 160 pe->sym = asm_section_sym(s1, cur_text_section); 161 pe->pcrel = 0; 162 next(); 163 break; 104 164 default: 105 165 if (tok >= TOK_IDENT) { 166 ElfSym *esym; 106 167 /* label case : if the label was not found, add one */ 107 sym = label_find(tok); 108 if (!sym) { 109 sym = label_push(&s1->asm_labels, tok, 0); 110 /* NOTE: by default, the symbol is global */ 111 sym->type.t = VT_VOID; 112 } 113 if (sym->r == SHN_ABS) { 168 sym = get_asm_sym(tok, NULL); 169 esym = elfsym(sym); 170 if (esym && esym->st_shndx == SHN_ABS) { 114 171 /* if absolute symbol, no need to put a symbol value */ 115 pe->v = sym->jnext;172 pe->v = esym->st_value; 116 173 pe->sym = NULL; 174 pe->pcrel = 0; 117 175 } else { 118 176 pe->v = 0; 119 177 pe->sym = sym; 178 pe->pcrel = 0; 120 179 } 121 180 next(); … … 220 279 /* NOTE: we are less powerful than gas in that case 221 280 because we store only one symbol in the expression */ 222 if (!pe->sym && !e2.sym) { 223 /* OK */ 224 } else if (pe->sym && !e2.sym) { 225 /* OK */ 226 } else if (pe->sym && e2.sym) { 227 if (pe->sym == e2.sym) { 228 /* OK */ 229 } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) { 230 /* we also accept defined symbols in the same section */ 231 pe->v += pe->sym->jnext - e2.sym->jnext; 232 } else { 233 goto cannot_relocate; 234 } 235 pe->sym = NULL; /* same symbols can be substracted to NULL */ 236 } else { 237 cannot_relocate: 238 tcc_error("invalid operation with label"); 239 } 240 } 281 if (!e2.sym) { 282 /* OK */ 283 } else if (pe->sym == e2.sym) { 284 /* OK */ 285 pe->sym = NULL; /* same symbols can be subtracted to NULL */ 286 } else { 287 ElfSym *esym1, *esym2; 288 esym1 = elfsym(pe->sym); 289 esym2 = elfsym(e2.sym); 290 if (esym1 && esym1->st_shndx == esym2->st_shndx 291 && esym1->st_shndx != SHN_UNDEF) { 292 /* we also accept defined symbols in the same section */ 293 pe->v += esym1->st_value - esym2->st_value; 294 pe->sym = NULL; 295 } else if (esym2->st_shndx == cur_text_section->sh_num) { 296 /* When subtracting a defined symbol in current section 297 this actually makes the value PC-relative. */ 298 pe->v -= esym2->st_value - ind - 4; 299 pe->pcrel = 1; 300 e2.sym = NULL; 301 } else { 302 cannot_relocate: 303 tcc_error("invalid operation with label"); 304 } 305 } 306 } 307 } 308 } 309 310 static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe) 311 { 312 int op; 313 ExprValue e2; 314 315 asm_expr_sum(s1, pe); 316 for(;;) { 317 op = tok; 318 if (op != TOK_EQ && op != TOK_NE 319 && (op > TOK_GT || op < TOK_ULE)) 320 break; 321 next(); 322 asm_expr_sum(s1, &e2); 323 if (pe->sym || e2.sym) 324 tcc_error("invalid operation with label"); 325 switch(op) { 326 case TOK_EQ: 327 pe->v = pe->v == e2.v; 328 break; 329 case TOK_NE: 330 pe->v = pe->v != e2.v; 331 break; 332 case TOK_LT: 333 pe->v = (int64_t)pe->v < (int64_t)e2.v; 334 break; 335 case TOK_GE: 336 pe->v = (int64_t)pe->v >= (int64_t)e2.v; 337 break; 338 case TOK_LE: 339 pe->v = (int64_t)pe->v <= (int64_t)e2.v; 340 break; 341 case TOK_GT: 342 pe->v = (int64_t)pe->v > (int64_t)e2.v; 343 break; 344 default: 345 break; 346 } 347 /* GAS compare results are -1/0 not 1/0. */ 348 pe->v = -(int64_t)pe->v; 241 349 } 242 350 } … … 244 352 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe) 245 353 { 246 asm_expr_ sum(s1, pe);354 asm_expr_cmp(s1, pe); 247 355 } 248 356 … … 256 364 } 257 365 258 /* NOTE: the same name space as C labels is used to avoid using too 259 much memory when storing labels in TokenStrings */ 260 static void asm_new_label1(TCCState *s1, int label, int is_local, 366 static Sym* asm_new_label1(TCCState *s1, int label, int is_local, 261 367 int sh_num, int value) 262 368 { 263 369 Sym *sym; 264 265 sym = label_find(label); 370 ElfSym *esym; 371 372 sym = asm_label_find(label); 266 373 if (sym) { 267 if (sym->r) { 374 esym = elfsym(sym); 375 /* A VT_EXTERN symbol, even if it has a section is considered 376 overridable. This is how we "define" .set targets. Real 377 definitions won't have VT_EXTERN set. */ 378 if (esym && esym->st_shndx != SHN_UNDEF) { 268 379 /* the label is already defined */ 269 if (!is_local) { 270 tcc_error("assembler label '%s' already defined", 271 get_tok_str(label, NULL)); 272 } else { 273 /* redefinition of local labels is possible */ 380 if (IS_ASM_SYM(sym) 381 && (is_local == 1 || (sym->type.t & VT_EXTERN))) 274 382 goto new_label; 275 } 383 if (!(sym->type.t & VT_EXTERN)) 384 tcc_error("assembler label '%s' already defined", 385 get_tok_str(label, NULL)); 276 386 } 277 387 } else { 278 388 new_label: 279 sym = label_push(&s1->asm_labels, label, 0); 280 sym->type.t = VT_STATIC | VT_VOID; 281 } 282 sym->r = sh_num; 283 sym->jnext = value; 284 } 285 286 static void asm_new_label(TCCState *s1, int label, int is_local) 287 { 288 asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind); 289 } 290 291 static void asm_free_labels(TCCState *st) 292 { 293 Sym *s, *s1; 294 Section *sec; 295 296 for(s = st->asm_labels; s != NULL; s = s1) { 297 s1 = s->prev; 298 /* define symbol value in object file */ 299 if (s->r) { 300 if (s->r == SHN_ABS) 301 sec = SECTION_ABS; 302 else 303 sec = st->sections[s->r]; 304 put_extern_sym2(s, sec, s->jnext, 0, 0); 305 } 306 /* remove label */ 307 table_ident[s->v - TOK_IDENT]->sym_label = NULL; 308 sym_free(s); 309 } 310 st->asm_labels = NULL; 389 sym = asm_label_push(label); 390 } 391 if (!sym->c) 392 put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0); 393 esym = elfsym(sym); 394 esym->st_shndx = sh_num; 395 esym->st_value = value; 396 if (is_local != 2) 397 sym->type.t &= ~VT_EXTERN; 398 return sym; 399 } 400 401 static Sym* asm_new_label(TCCState *s1, int label, int is_local) 402 { 403 return asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind); 404 } 405 406 /* Set the value of LABEL to that of some expression (possibly 407 involving other symbols). LABEL can be overwritten later still. */ 408 static Sym* set_symbol(TCCState *s1, int label) 409 { 410 long n; 411 ExprValue e; 412 Sym *sym; 413 ElfSym *esym; 414 next(); 415 asm_expr(s1, &e); 416 n = e.v; 417 esym = elfsym(e.sym); 418 if (esym) 419 n += esym->st_value; 420 sym = asm_new_label1(s1, label, 2, esym ? esym->st_shndx : SHN_ABS, n); 421 elfsym(sym)->st_other |= ST_ASM_SET; 422 return sym; 311 423 } 312 424 … … 325 437 } 326 438 327 static void asm_parse_directive(TCCState *s1) 439 static void push_section(TCCState *s1, const char *name) 440 { 441 Section *sec = find_section(s1, name); 442 sec->prev = cur_text_section; 443 use_section1(s1, sec); 444 } 445 446 static void pop_section(TCCState *s1) 447 { 448 Section *prev = cur_text_section->prev; 449 if (!prev) 450 tcc_error(".popsection without .pushsection"); 451 cur_text_section->prev = NULL; 452 use_section1(s1, prev); 453 } 454 455 static void asm_parse_directive(TCCState *s1, int global) 328 456 { 329 457 int n, offset, v, size, tok1; … … 332 460 333 461 /* assembler directive */ 334 next();335 462 sec = cur_text_section; 336 463 switch(tok) { 337 case TOK_ASM_align: 338 case TOK_ASM_skip: 339 case TOK_ASM_space: 464 case TOK_ASMDIR_align: 465 case TOK_ASMDIR_balign: 466 case TOK_ASMDIR_p2align: 467 case TOK_ASMDIR_skip: 468 case TOK_ASMDIR_space: 340 469 tok1 = tok; 341 470 next(); 342 471 n = asm_int_expr(s1); 343 if (tok1 == TOK_ASM_align) { 472 if (tok1 == TOK_ASMDIR_p2align) 473 { 474 if (n < 0 || n > 30) 475 tcc_error("invalid p2align, must be between 0 and 30"); 476 n = 1 << n; 477 tok1 = TOK_ASMDIR_align; 478 } 479 if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) { 344 480 if (n < 0 || (n & (n-1)) != 0) 345 481 tcc_error("alignment must be a positive power of two"); … … 350 486 sec->sh_addralign = n; 351 487 } else { 488 if (n < 0) 489 n = 0; 352 490 size = n; 353 491 } … … 365 503 ind += size; 366 504 break; 367 case TOK_ASM_quad: 505 case TOK_ASMDIR_quad: 506 #ifdef TCC_TARGET_X86_64 507 size = 8; 508 goto asm_data; 509 #else 368 510 next(); 369 511 for(;;) { … … 371 513 const char *p; 372 514 373 p = tokc. cstr->data;515 p = tokc.str.data; 374 516 if (tok != TOK_PPNUM) { 375 517 error_constant: … … 392 534 } 393 535 break; 394 case TOK_ASM_byte: 536 #endif 537 case TOK_ASMDIR_byte: 395 538 size = 1; 396 539 goto asm_data; 397 case TOK_ASM _word:398 case TOK_ SHORT:540 case TOK_ASMDIR_word: 541 case TOK_ASMDIR_short: 399 542 size = 2; 400 543 goto asm_data; 401 case TOK_ LONG:402 case TOK_ INT:544 case TOK_ASMDIR_long: 545 case TOK_ASMDIR_int: 403 546 size = 4; 404 547 asm_data: … … 410 553 if (size == 4) { 411 554 gen_expr32(&e); 555 #ifdef TCC_TARGET_X86_64 556 } else if (size == 8) { 557 gen_expr64(&e); 558 #endif 412 559 } else { 413 560 if (e.sym) … … 426 573 } 427 574 break; 428 case TOK_ASM _fill:575 case TOK_ASMDIR_fill: 429 576 { 430 577 int repeat, size, val, i, j; … … 468 615 } 469 616 break; 470 case TOK_ASM_org: 617 case TOK_ASMDIR_rept: 618 { 619 int repeat; 620 TokenString *init_str; 621 next(); 622 repeat = asm_int_expr(s1); 623 init_str = tok_str_alloc(); 624 while (next(), tok != TOK_ASMDIR_endr) { 625 if (tok == CH_EOF) 626 tcc_error("we at end of file, .endr not found"); 627 tok_str_add_tok(init_str); 628 } 629 tok_str_add(init_str, -1); 630 tok_str_add(init_str, 0); 631 begin_macro(init_str, 1); 632 while (repeat-- > 0) { 633 tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS), 634 global); 635 macro_ptr = init_str->str; 636 } 637 end_macro(); 638 next(); 639 break; 640 } 641 case TOK_ASMDIR_org: 471 642 { 472 643 unsigned long n; 473 next(); 474 /* XXX: handle section symbols too */ 475 n = asm_int_expr(s1); 644 ExprValue e; 645 ElfSym *esym; 646 next(); 647 asm_expr(s1, &e); 648 n = e.v; 649 esym = elfsym(e.sym); 650 if (esym) { 651 if (esym->st_shndx != cur_text_section->sh_num) 652 expect("constant or same-section symbol"); 653 n += esym->st_value; 654 } 476 655 if (n < ind) 477 656 tcc_error("attempt to .org backwards"); … … 481 660 } 482 661 break; 483 case TOK_ASM_globl: 484 case TOK_ASM_global: 485 case TOK_ASM_weak: 486 tok1 = tok; 662 case TOK_ASMDIR_set: 663 next(); 664 tok1 = tok; 665 next(); 666 /* Also accept '.set stuff', but don't do anything with this. 667 It's used in GAS to set various features like '.set mips16'. */ 668 if (tok == ',') 669 set_symbol(s1, tok1); 670 break; 671 case TOK_ASMDIR_globl: 672 case TOK_ASMDIR_global: 673 case TOK_ASMDIR_weak: 674 case TOK_ASMDIR_hidden: 675 tok1 = tok; 487 676 do { 488 677 Sym *sym; 489 490 next(); 491 sym = label_find(tok); 492 if (!sym) { 493 sym = label_push(&s1->asm_labels, tok, 0); 494 sym->type.t = VT_VOID; 495 } 496 sym->type.t &= ~VT_STATIC; 497 if (tok1 == TOK_ASM_weak) 498 sym->type.t |= VT_WEAK; 678 next(); 679 sym = get_asm_sym(tok, NULL); 680 if (tok1 != TOK_ASMDIR_hidden) 681 sym->type.t &= ~VT_STATIC; 682 if (tok1 == TOK_ASMDIR_weak) 683 sym->a.weak = 1; 684 else if (tok1 == TOK_ASMDIR_hidden) 685 sym->a.visibility = STV_HIDDEN; 686 update_storage(sym); 499 687 next(); 500 688 } while (tok == ','); 501 689 break; 502 case TOK_ASM _string:503 case TOK_ASM _ascii:504 case TOK_ASM _asciz:690 case TOK_ASMDIR_string: 691 case TOK_ASMDIR_ascii: 692 case TOK_ASMDIR_asciz: 505 693 { 506 694 const uint8_t *p; … … 512 700 if (tok != TOK_STR) 513 701 expect("string constant"); 514 p = tokc. cstr->data;515 size = tokc. cstr->size;516 if (t == TOK_ASM _ascii && size > 0)702 p = tokc.str.data; 703 size = tokc.str.size; 704 if (t == TOK_ASMDIR_ascii && size > 0) 517 705 size--; 518 706 for(i = 0; i < size; i++) … … 527 715 } 528 716 break; 529 case TOK_ASM _text:530 case TOK_ASM _data:531 case TOK_ASM _bss:717 case TOK_ASMDIR_text: 718 case TOK_ASMDIR_data: 719 case TOK_ASMDIR_bss: 532 720 { 533 721 char sname[64]; … … 539 727 next(); 540 728 } 541 sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); 729 if (n) 730 sprintf(sname, "%s%d", get_tok_str(tok1, NULL), n); 731 else 732 sprintf(sname, "%s", get_tok_str(tok1, NULL)); 542 733 use_section(s1, sname); 543 734 } 544 735 break; 545 case TOK_ASM _file:736 case TOK_ASMDIR_file: 546 737 { 547 738 char filename[512]; … … 551 742 552 743 if (tok == TOK_STR) 553 pstrcat(filename, sizeof(filename), tokc. cstr->data);744 pstrcat(filename, sizeof(filename), tokc.str.data); 554 745 else 555 746 pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL)); … … 561 752 } 562 753 break; 563 case TOK_ASM _ident:754 case TOK_ASMDIR_ident: 564 755 { 565 756 char ident[256]; … … 569 760 570 761 if (tok == TOK_STR) 571 pstrcat(ident, sizeof(ident), tokc. cstr->data);762 pstrcat(ident, sizeof(ident), tokc.str.data); 572 763 else 573 764 pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL)); … … 579 770 } 580 771 break; 581 case TOK_ASM _size:772 case TOK_ASMDIR_size: 582 773 { 583 774 Sym *sym; 584 775 585 776 next(); 586 sym = label_find(tok);777 sym = asm_label_find(tok); 587 778 if (!sym) { 588 779 tcc_error("label not found: %s", get_tok_str(tok, NULL)); 589 780 } 590 781 591 next();592 skip(',');593 782 /* XXX .size name,label2-label1 */ 594 783 if (s1->warn_unsupported) 595 784 tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); 596 785 597 while (tok != '\n' && tok != CH_EOF) { 786 next(); 787 skip(','); 788 while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) { 598 789 next(); 599 790 } 600 791 } 601 792 break; 602 case TOK_ASM _type:793 case TOK_ASMDIR_type: 603 794 { 604 795 Sym *sym; … … 606 797 607 798 next(); 608 sym = label_find(tok); 609 if (!sym) { 610 sym = label_push(&s1->asm_labels, tok, 0); 611 sym->type.t = VT_VOID; 612 } 613 799 sym = get_asm_sym(tok, NULL); 614 800 next(); 615 801 skip(','); 616 802 if (tok == TOK_STR) { 617 newtype = tokc. cstr->data;803 newtype = tokc.str.data; 618 804 } else { 619 805 if (tok == '@' || tok == '%') 620 skip(tok);806 next(); 621 807 newtype = get_tok_str(tok, NULL); 622 808 } 623 809 624 810 if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { 625 sym->type.t = VT_FUNC;811 sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC; 626 812 } 627 813 else if (s1->warn_unsupported) … … 632 818 } 633 819 break; 634 case TOK_SECTION1: 820 case TOK_ASMDIR_pushsection: 821 case TOK_ASMDIR_section: 635 822 { 636 823 char sname[256]; 637 824 int old_nb_section = s1->nb_sections; 825 826 tok1 = tok; 638 827 /* XXX: support more options */ 639 828 next(); … … 641 830 while (tok != ';' && tok != TOK_LINEFEED && tok != ',') { 642 831 if (tok == TOK_STR) 643 pstrcat(sname, sizeof(sname), tokc. cstr->data);832 pstrcat(sname, sizeof(sname), tokc.str.data); 644 833 else 645 834 pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL)); … … 652 841 expect("string constant"); 653 842 next(); 843 if (tok == ',') { 844 next(); 845 if (tok == '@' || tok == '%') 846 next(); 847 next(); 848 } 654 849 } 655 850 last_text_section = cur_text_section; 656 use_section(s1, sname); 657 } 658 break; 659 case TOK_ASM_previous: 851 if (tok1 == TOK_ASMDIR_section) 852 use_section(s1, sname); 853 else 854 push_section(s1, sname); 855 /* If we just allocated a new section reset its alignment to 856 1. new_section normally acts for GCC compatibility and 857 sets alignment to PTR_SIZE. The assembler behaves different. */ 858 if (old_nb_section != s1->nb_sections) 859 cur_text_section->sh_addralign = 1; 860 } 861 break; 862 case TOK_ASMDIR_previous: 660 863 { 661 864 Section *sec; … … 668 871 } 669 872 break; 873 case TOK_ASMDIR_popsection: 874 next(); 875 pop_section(s1); 876 break; 670 877 #ifdef TCC_TARGET_I386 671 case TOK_ASM _code16:878 case TOK_ASMDIR_code16: 672 879 { 673 880 next(); … … 675 882 } 676 883 break; 677 case TOK_ASM _code32:884 case TOK_ASMDIR_code32: 678 885 { 679 886 next(); … … 684 891 #ifdef TCC_TARGET_X86_64 685 892 /* added for compatibility with GAS */ 686 case TOK_ASM _code64:893 case TOK_ASMDIR_code64: 687 894 next(); 688 895 break; … … 696 903 697 904 /* assemble a file */ 698 static int tcc_assemble_internal(TCCState *s1, int do_preprocess )905 static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) 699 906 { 700 907 int opcode; 701 702 #if 0 703 /* print stats about opcodes */ 704 { 705 const ASMInstr *pa; 706 int freq[4]; 707 int op_vals[500]; 708 int nb_op_vals, i, j; 709 710 nb_op_vals = 0; 711 memset(freq, 0, sizeof(freq)); 712 for(pa = asm_instrs; pa->sym != 0; pa++) { 713 freq[pa->nb_ops]++; 714 for(i=0;i<pa->nb_ops;i++) { 715 for(j=0;j<nb_op_vals;j++) { 716 if (pa->op_type[i] == op_vals[j]) 717 goto found; 718 } 719 op_vals[nb_op_vals++] = pa->op_type[i]; 720 found: ; 721 } 722 } 723 for(i=0;i<nb_op_vals;i++) { 724 int v = op_vals[i]; 725 if ((v & (v - 1)) != 0) 726 printf("%3d: %08x\n", i, v); 727 } 728 printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n", 729 sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr), 730 freq[0], freq[1], freq[2], freq[3]); 731 } 732 #endif 733 734 /* XXX: undefine C labels */ 735 736 ch = file->buf_ptr[0]; 737 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 738 parse_flags = PARSE_FLAG_ASM_COMMENTS; 908 int saved_parse_flags = parse_flags; 909 910 parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR; 739 911 if (do_preprocess) 740 912 parse_flags |= PARSE_FLAG_PREPROCESS; 741 next();742 913 for(;;) { 914 next(); 743 915 if (tok == TOK_EOF) 744 916 break; 917 /* generate line number info */ 918 if (global && s1->do_debug) 919 tcc_debug_line(s1); 745 920 parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ 746 921 redo: … … 749 924 while (tok != TOK_LINEFEED) 750 925 next(); 751 } else if (tok == '.') {752 asm_parse_directive(s1 );926 } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) { 927 asm_parse_directive(s1, global); 753 928 } else if (tok == TOK_PPNUM) { 754 929 const char *p; 755 930 int n; 756 p = tokc. cstr->data;931 p = tokc.str.data; 757 932 n = strtoul(p, (char **)&p, 10); 758 933 if (*p != '\0') … … 773 948 goto redo; 774 949 } else if (tok == '=') { 775 int n; 776 next(); 777 n = asm_int_expr(s1); 778 asm_new_label1(s1, opcode, 0, SHN_ABS, n); 950 set_symbol(s1, opcode); 779 951 goto redo; 780 952 } else { … … 783 955 } 784 956 /* end of line */ 785 if (tok != ';' && tok != TOK_LINEFEED) {957 if (tok != ';' && tok != TOK_LINEFEED) 786 958 expect("end of line"); 787 }788 959 parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ 789 next(); 790 } 791 792 asm_free_labels(s1); 793 960 } 961 962 parse_flags = saved_parse_flags; 794 963 return 0; 795 964 } … … 798 967 ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) 799 968 { 800 Sym *define_start;801 969 int ret; 802 803 preprocess_init(s1); 804 970 tcc_debug_start(s1); 805 971 /* default section is text */ 806 972 cur_text_section = text_section; 807 973 ind = cur_text_section->data_offset; 808 809 define_start = define_stack; 810 811 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL 812 symbols can be safely used */ 813 put_elf_sym(symtab_section, 0, 0, 814 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, 815 SHN_ABS, file->filename); 816 817 ret = tcc_assemble_internal(s1, do_preprocess); 818 974 nocode_wanted = 0; 975 ret = tcc_assemble_internal(s1, do_preprocess, 1); 819 976 cur_text_section->data_offset = ind; 820 821 free_defines(define_start); 822 977 tcc_debug_end(s1); 823 978 return ret; 824 979 } … … 830 985 C preprocessing. NOTE: str is modified by modifying the '\0' at the 831 986 end */ 832 static void tcc_assemble_inline(TCCState *s1, char *str, int len) 833 { 834 int saved_parse_flags; 835 const int *saved_macro_ptr; 836 837 saved_parse_flags = parse_flags; 838 saved_macro_ptr = macro_ptr; 987 static void tcc_assemble_inline(TCCState *s1, char *str, int len, int global) 988 { 989 const int *saved_macro_ptr = macro_ptr; 990 int dotid = set_idnum('.', IS_ID); 839 991 840 992 tcc_open_bf(s1, ":asm:", len); 841 993 memcpy(file->buffer, str, len); 842 843 994 macro_ptr = NULL; 844 tcc_assemble_internal(s1, 0 );995 tcc_assemble_internal(s1, 0, global); 845 996 tcc_close(); 846 997 847 parse_flags = saved_parse_flags;998 set_idnum('.', dotid); 848 999 macro_ptr = saved_macro_ptr; 849 1000 } … … 891 1042 892 1043 static void subst_asm_operands(ASMOperand *operands, int nb_operands, 893 int nb_outputs,894 1044 CString *out_str, CString *in_str) 895 1045 { … … 910 1060 modifier = 0; 911 1061 if (*str == 'c' || *str == 'n' || 912 *str == 'b' || *str == 'w' || *str == 'h') 1062 *str == 'b' || *str == 'w' || *str == 'h' || *str == 'k' || 1063 *str == 'q' || 1064 /* P in GCC would add "@PLT" to symbol refs in PIC mode, 1065 and make literal operands not be decorated with '$'. */ 1066 *str == 'P') 913 1067 modifier = *str++; 914 1068 index = find_constraint(operands, nb_operands, str, &str); … … 942 1096 nb_operands = *nb_operands_ptr; 943 1097 for(;;) { 1098 CString astr; 944 1099 if (nb_operands >= MAX_ASM_OPERANDS) 945 1100 tcc_error("too many asm operands"); … … 954 1109 skip(']'); 955 1110 } 956 if (tok != TOK_STR) 957 expect("string constant"); 958 op->constraint = tcc_malloc(tokc.cstr->size); 959 strcpy(op->constraint, tokc.cstr->data); 960 next(); 1111 parse_mult_str(&astr, "string constant"); 1112 op->constraint = tcc_malloc(astr.size); 1113 strcpy(op->constraint, astr.data); 1114 cstr_free(&astr); 961 1115 skip('('); 962 1116 gexpr(); 963 1117 if (is_output) { 964 test_lvalue(); 1118 if (!(vtop->type.t & VT_ARRAY)) 1119 test_lvalue(); 965 1120 } else { 966 1121 /* we want to avoid LLOCAL case, except when the 'm' … … 1024 1179 if (tok != TOK_STR) 1025 1180 expect("string constant"); 1026 asm_clobber(clobber_regs, tokc. cstr->data);1181 asm_clobber(clobber_regs, tokc.str.data); 1027 1182 next(); 1028 1183 if (tok == ',') { … … 1055 1210 #endif 1056 1211 if (must_subst) { 1057 subst_asm_operands(operands, nb_operands, nb_outputs,&astr1, &astr);1212 subst_asm_operands(operands, nb_operands, &astr1, &astr); 1058 1213 cstr_free(&astr); 1059 1214 } else { … … 1069 1224 1070 1225 /* assemble the string with tcc internal assembler */ 1071 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1 );1226 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1, 0); 1072 1227 1073 1228 /* restore the current C token */ … … 1091 1246 { 1092 1247 CString astr; 1093 1248 int saved_nocode_wanted = nocode_wanted; 1249 1250 /* Global asm blocks are always emitted. */ 1251 nocode_wanted = 0; 1094 1252 next(); 1095 1253 parse_asm_str(&astr); … … 1107 1265 1108 1266 /* assemble the string with tcc internal assembler */ 1109 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1 );1267 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 1); 1110 1268 1111 1269 cur_text_section->data_offset = ind; … … 1115 1273 1116 1274 cstr_free(&astr); 1275 nocode_wanted = saved_nocode_wanted; 1117 1276 } 1118 1277 #endif /* CONFIG_TCC_ASM */
Note:
See TracChangeset
for help on using the changeset viewer.