Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27/i386-gen.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/i386-gen.c
r321 r331 22 22 23 23 /* number of available registers */ 24 #define NB_REGS 424 #define NB_REGS 5 25 25 #define NB_ASM_REGS 8 26 #define CONFIG_TCC_ASM 26 27 27 28 /* a register can belong to several classes. The classes must be … … 34 35 #define RC_ECX 0x0010 35 36 #define RC_EDX 0x0020 37 #define RC_EBX 0x0040 38 36 39 #define RC_IRET RC_EAX /* function return: integer register */ 37 40 #define RC_LRET RC_EDX /* function return: second integer register */ … … 43 46 TREG_ECX, 44 47 TREG_EDX, 48 TREG_EBX, 45 49 TREG_ST0, 50 TREG_ESP = 4 46 51 }; 47 52 … … 56 61 /* defined if structures are passed as pointers. Otherwise structures 57 62 are directly pushed on stack. */ 58 / /#define FUNC_STRUCT_PARAM_AS_PTR63 /* #define FUNC_STRUCT_PARAM_AS_PTR */ 59 64 60 65 /* pointer size, in bytes */ … … 67 72 #define MAX_ALIGN 8 68 73 69 70 #define psym oad71 72 /******************************************************/73 /* ELF defines */74 75 #define EM_TCC_TARGET EM_38676 77 /* relocation type for 32 bit data relocation */78 #define R_DATA_32 R_386_3279 #define R_DATA_PTR R_386_3280 #define R_JMP_SLOT R_386_JMP_SLOT81 #define R_COPY R_386_COPY82 83 #define ELF_START_ADDR 0x0804800084 #define ELF_PAGE_SIZE 0x100085 86 74 /******************************************************/ 87 75 #else /* ! TARGET_DEFS_ONLY */ … … 89 77 #include "tcc.h" 90 78 79 /* define to 1/0 to [not] have EBX as 4th register */ 80 #define USE_EBX 0 81 91 82 ST_DATA const int reg_classes[NB_REGS] = { 92 83 /* eax */ RC_INT | RC_EAX, 93 84 /* ecx */ RC_INT | RC_ECX, 94 85 /* edx */ RC_INT | RC_EDX, 86 /* ebx */ (RC_INT | RC_EBX) * USE_EBX, 95 87 /* st0 */ RC_FLOAT | RC_ST0, 96 88 }; … … 99 91 static int func_ret_sub; 100 92 #ifdef CONFIG_TCC_BCHECK 101 static unsigned long func_bound_offset; 93 static addr_t func_bound_offset; 94 static unsigned long func_bound_ind; 102 95 #endif 103 96 … … 106 99 { 107 100 int ind1; 101 if (nocode_wanted) 102 return; 108 103 ind1 = ind + 1; 109 104 if (ind1 > cur_text_section->data_allocated) … … 138 133 ST_FUNC void gsym_addr(int t, int a) 139 134 { 140 int n, *ptr;141 135 while (t) { 142 ptr = (int *)(cur_text_section->data + t);143 n = *ptr; /* next value */144 *ptr = a - t - 4;136 unsigned char *ptr = cur_text_section->data + t; 137 uint32_t n = read32le(ptr); /* next value */ 138 write32le(ptr, a - t - 4); 145 139 t = n; 146 140 } … … 152 146 } 153 147 154 /* psym is used to put an instruction with a data field which is a155 reference to a symbol. It is in fact the same as oad ! */156 #define psym oad157 158 148 /* instruction + 4 bytes data. Return the address of the data */ 159 ST_FUNC int oad(int c, int s) 160 { 161 int ind1; 162 149 static int oad(int c, int s) 150 { 151 int t; 152 if (nocode_wanted) 153 return s; 163 154 o(c); 164 ind1 = ind + 4; 165 if (ind1 > cur_text_section->data_allocated) 166 section_realloc(cur_text_section, ind1); 167 *(int *)(cur_text_section->data + ind) = s; 168 s = ind; 169 ind = ind1; 170 return s; 171 } 155 t = ind; 156 gen_le32(s); 157 return t; 158 } 159 160 /* generate jmp to a label */ 161 #define gjmp2(instr,lbl) oad(instr,lbl) 172 162 173 163 /* output constant with relocation if 'r & VT_SYM' is true */ … … 186 176 } 187 177 188 /* generate a modrm reference. 'op_reg' contains the add tionnal 3178 /* generate a modrm reference. 'op_reg' contains the additional 3 189 179 opcode bits */ 190 180 static void gen_modrm(int op_reg, int r, Sym *sym, int c) … … 221 211 222 212 fr = sv->r; 223 ft = sv->type.t; 224 fc = sv->c.ul; 213 ft = sv->type.t & ~VT_DEFSIGN; 214 fc = sv->c.i; 215 216 ft &= ~(VT_VOLATILE | VT_CONSTANT); 225 217 226 218 v = fr & VT_VALMASK; … … 229 221 v1.type.t = VT_INT; 230 222 v1.r = VT_LOCAL | VT_LVAL; 231 v1.c. ul= fc;223 v1.c.i = fc; 232 224 fr = r; 233 225 if (!(reg_classes[fr] & RC_INT)) … … 244 236 o(0xdb); /* fldt */ 245 237 r = 5; 246 } else if ((ft & VT_TYPE) == VT_BYTE ) {238 } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { 247 239 o(0xbe0f); /* movsbl */ 248 240 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { … … 297 289 298 290 ft = v->type.t; 299 fc = v->c. ul;291 fc = v->c.i; 300 292 fr = v->r & VT_VALMASK; 293 ft &= ~(VT_VOLATILE | VT_CONSTANT); 301 294 bt = ft & VT_BTYPE; 302 295 /* XXX: incorrect if float reg to reg */ … … 338 331 } 339 332 333 #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE 334 static void gen_static_call(int v) 335 { 336 Sym *sym; 337 338 sym = external_global_sym(v, &func_old_type, 0); 339 oad(0xe8, -4); 340 greloc(cur_text_section, sym, ind-4, R_386_PC32); 341 } 342 #endif 343 340 344 /* 'is_jmp' is '1' if it is a jump */ 341 345 static void gcall_or_jmp(int is_jmp) 342 346 { 343 347 int r; 344 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 345 /* constant case */ 346 if (vtop->r & VT_SYM) { 347 /* relocation case */ 348 greloc(cur_text_section, vtop->sym, 349 ind + 1, R_386_PC32); 350 } else { 351 /* put an empty PC32 relocation */ 352 put_elf_reloc(symtab_section, cur_text_section, 353 ind + 1, R_386_PC32, 0); 354 } 355 oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */ 348 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { 349 /* constant and relocation case */ 350 greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32); 351 oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ 356 352 } else { 357 353 /* otherwise, indirect call */ … … 360 356 o(0xd0 + r + (is_jmp << 4)); 361 357 } 358 if (!is_jmp) { 359 int rt; 360 /* extend the return value to the whole register if necessary 361 visual studio and gcc do not always set the whole eax register 362 when assigning the return value of a function */ 363 rt = vtop->type.ref->type.t; 364 switch (rt & VT_BTYPE) { 365 case VT_BYTE: 366 if (rt & VT_UNSIGNED) { 367 o(0xc0b60f); /* movzx %al, %eax */ 368 } 369 else { 370 o(0xc0be0f); /* movsx %al, %eax */ 371 } 372 break; 373 case VT_SHORT: 374 if (rt & VT_UNSIGNED) { 375 o(0xc0b70f); /* movzx %ax, %eax */ 376 } 377 else { 378 o(0xc0bf0f); /* movsx %ax, %eax */ 379 } 380 break; 381 default: 382 break; 383 } 384 } 362 385 } 363 386 364 387 static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; 365 388 static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; 389 390 /* Return the number of registers needed to return the struct, or 0 if 391 returning via struct pointer. */ 392 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) 393 { 394 #ifdef TCC_TARGET_PE 395 int size, align; 396 *ret_align = 1; // Never have to re-align return values for x86 397 *regsize = 4; 398 size = type_size(vt, &align); 399 if (size > 8 || (size & (size - 1))) 400 return 0; 401 if (size == 8) 402 ret->t = VT_LLONG; 403 else if (size == 4) 404 ret->t = VT_INT; 405 else if (size == 2) 406 ret->t = VT_SHORT; 407 else 408 ret->t = VT_BYTE; 409 ret->ref = NULL; 410 return 1; 411 #else 412 *ret_align = 1; // Never have to re-align return values for x86 413 return 0; 414 #endif 415 } 366 416 367 417 /* Generate function call. The function address is pushed first, then … … 422 472 save_regs(0); /* save used temporary registers */ 423 473 func_sym = vtop->type.ref; 424 func_call = FUNC_CALL(func_sym->r);474 func_call = func_sym->f.func_call; 425 475 /* fast call case */ 426 476 if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || … … 443 493 } 444 494 } 495 #ifndef TCC_TARGET_PE 496 else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) 497 args_size -= 4; 498 #endif 445 499 gcall_or_jmp(0); 446 500 447 #ifdef TCC_TARGET_PE 448 if ((func_sym->type.t & VT_BTYPE) == VT_STRUCT) 449 args_size -= 4; 450 #endif 451 if (args_size && func_call != FUNC_STDCALL) 501 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW) 452 502 gadd_sp(args_size); 453 503 vtop--; … … 455 505 456 506 #ifdef TCC_TARGET_PE 457 #define FUNC_PROLOG_SIZE 10507 #define FUNC_PROLOG_SIZE (10 + USE_EBX) 458 508 #else 459 #define FUNC_PROLOG_SIZE 9509 #define FUNC_PROLOG_SIZE (9 + USE_EBX) 460 510 #endif 461 511 … … 470 520 471 521 sym = func_type->ref; 472 func_call = FUNC_CALL(sym->r);522 func_call = sym->f.func_call; 473 523 addr = 8; 474 524 loc = 0; … … 492 542 implicit pointer parameter */ 493 543 func_vt = sym->type; 544 func_var = (sym->f.func_type == FUNC_ELLIPSIS); 545 #ifdef TCC_TARGET_PE 546 size = type_size(&func_vt,&align); 547 if (((func_vt.t & VT_BTYPE) == VT_STRUCT) 548 && (size > 8 || (size & (size - 1)))) { 549 #else 494 550 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 551 #endif 495 552 /* XXX: fastcall case ? */ 496 553 func_vc = addr; … … 524 581 } 525 582 func_ret_sub = 0; 526 /* pascal type call ? */527 if (func_call == FUNC_STDCALL )583 /* pascal type call or fastcall ? */ 584 if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW) 528 585 func_ret_sub = addr - 8; 529 #if def TCC_TARGET_PE586 #ifndef TCC_TARGET_PE 530 587 else if (func_vc) 531 588 func_ret_sub = 4; … … 535 592 /* leave some room for bound checking code */ 536 593 if (tcc_state->do_bounds_check) { 594 func_bound_offset = lbounds_section->data_offset; 595 func_bound_ind = ind; 537 596 oad(0xb8, 0); /* lbound section pointer */ 538 597 oad(0xb8, 0); /* call to function */ 539 func_bound_offset = lbounds_section->data_offset;540 598 } 541 599 #endif … … 545 603 ST_FUNC void gfunc_epilog(void) 546 604 { 547 int v, saved_ind;605 addr_t v, saved_ind; 548 606 549 607 #ifdef CONFIG_TCC_BCHECK 550 608 if (tcc_state->do_bounds_check 551 609 && func_bound_offset != lbounds_section->data_offset) { 552 int saved_ind; 553 int *bounds_ptr; 554 Sym *sym, *sym_data; 610 addr_t saved_ind; 611 addr_t *bounds_ptr; 612 Sym *sym_data; 613 555 614 /* add end of table info */ 556 bounds_ptr = section_ptr_add(lbounds_section, sizeof( int));615 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); 557 616 *bounds_ptr = 0; 617 558 618 /* generate bound local allocation */ 559 619 saved_ind = ind; 560 ind = func_ sub_sp_offset;620 ind = func_bound_ind; 561 621 sym_data = get_sym_ref(&char_pointer_type, lbounds_section, 562 622 func_bound_offset, lbounds_section->data_offset); … … 564 624 ind + 1, R_386_32); 565 625 oad(0xb8, 0); /* mov %eax, xxx */ 566 sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0); 567 greloc(cur_text_section, sym, 568 ind + 1, R_386_PC32); 569 oad(0xe8, -4); 626 gen_static_call(TOK___bound_local_new); 570 627 ind = saved_ind; 628 571 629 /* generate bound check local freeing */ 572 630 o(0x5250); /* save returned value, if any */ 573 greloc(cur_text_section, sym_data, 574 ind + 1, R_386_32); 631 greloc(cur_text_section, sym_data, ind + 1, R_386_32); 575 632 oad(0xb8, 0); /* mov %eax, xxx */ 576 sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0); 577 greloc(cur_text_section, sym, 578 ind + 1, R_386_PC32); 579 oad(0xe8, -4); 633 gen_static_call(TOK___bound_local_delete); 580 634 o(0x585a); /* restore returned value, if any */ 581 635 } 582 636 #endif 637 638 /* align local size to word & save local variables */ 639 v = (-loc + 3) & -4; 640 641 #if USE_EBX 642 o(0x8b); 643 gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4)); 644 #endif 645 583 646 o(0xc9); /* leave */ 584 647 if (func_ret_sub == 0) { … … 589 652 g(func_ret_sub >> 8); 590 653 } 591 /* align local size to word & save local variables */592 593 v = (-loc + 3) & -4;594 654 saved_ind = ind; 595 655 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; 596 656 #ifdef TCC_TARGET_PE 597 657 if (v >= 4096) { 598 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);599 658 oad(0xb8, v); /* mov stacksize, %eax */ 600 oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ 601 greloc(cur_text_section, sym, ind-4, R_386_PC32); 659 gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */ 602 660 } else 603 661 #endif … … 606 664 o(0xec81); /* sub esp, stacksize */ 607 665 gen_le32(v); 608 #if FUNC_PROLOG_SIZE == 10666 #ifdef TCC_TARGET_PE 609 667 o(0x90); /* adjust to FUNC_PROLOG_SIZE */ 610 668 #endif 611 669 } 670 o(0x53 * USE_EBX); /* push ebx */ 612 671 ind = saved_ind; 613 672 } … … 616 675 ST_FUNC int gjmp(int t) 617 676 { 618 return psym(0xe9, t);677 return gjmp2(0xe9, t); 619 678 } 620 679 … … 632 691 } 633 692 693 ST_FUNC void gtst_addr(int inv, int a) 694 { 695 int v = vtop->r & VT_VALMASK; 696 if (v == VT_CMP) { 697 inv ^= (vtop--)->c.i; 698 a -= ind + 2; 699 if (a == (char)a) { 700 g(inv - 32); 701 g(a); 702 } else { 703 g(0x0f); 704 oad(inv - 16, a - 4); 705 } 706 } else if ((v & ~1) == VT_JMP) { 707 if ((v & 1) != inv) { 708 gjmp_addr(a); 709 gsym(vtop->c.i); 710 } else { 711 gsym(vtop->c.i); 712 o(0x05eb); 713 gjmp_addr(a); 714 } 715 vtop--; 716 } 717 } 718 634 719 /* generate a test. set 'inv' to invert test. Stack entry is popped */ 635 720 ST_FUNC int gtst(int inv, int t) 636 721 { 637 int v , *p;638 639 v = vtop->r & VT_VALMASK;640 if (v == VT_CMP) {722 int v = vtop->r & VT_VALMASK; 723 if (nocode_wanted) { 724 ; 725 } else if (v == VT_CMP) { 641 726 /* fast case : can jump directly since flags are set */ 642 727 g(0x0f); 643 t = psym((vtop->c.i - 16) ^ inv, t);728 t = gjmp2((vtop->c.i - 16) ^ inv, t); 644 729 } else if (v == VT_JMP || v == VT_JMPI) { 645 730 /* && or || optimization */ 646 731 if ((v & 1) == inv) { 647 732 /* insert vtop->c jump list in t */ 648 p = &vtop->c.i; 649 while (*p != 0) 650 p = (int *)(cur_text_section->data + *p); 651 *p = t; 652 t = vtop->c.i; 733 uint32_t n1, n = vtop->c.i; 734 if (n) { 735 while ((n1 = read32le(cur_text_section->data + n))) 736 n = n1; 737 write32le(cur_text_section->data + n, t); 738 t = vtop->c.i; 739 } 653 740 } else { 654 741 t = gjmp(t); 655 742 gsym(vtop->c.i); 656 }657 } else {658 if (is_float(vtop->type.t) ||659 (vtop->type.t & VT_BTYPE) == VT_LLONG) {660 vpushi(0);661 gen_op(TOK_NE);662 }663 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {664 /* constant jmp optimization */665 if ((vtop->c.i != 0) != inv)666 t = gjmp(t);667 } else {668 v = gv(RC_INT);669 o(0x85);670 o(0xc0 + v * 9);671 g(0x0f);672 t = psym(0x85 ^ inv, t);673 743 } 674 744 } … … 695 765 if (c == (char)c) { 696 766 /* generate inc and dec for smaller code */ 697 if (c==1 && opc==0 ) {767 if (c==1 && opc==0 && op != TOK_ADDC1) { 698 768 o (0x40 | r); // inc 699 } else if (c==1 && opc==5 ) {769 } else if (c==1 && opc==5 && op != TOK_SUBC1) { 700 770 o (0x48 | r); // dec 701 771 } else { … … 789 859 vtop--; 790 860 save_reg(TREG_EDX); 861 /* save EAX too if used otherwise */ 862 save_reg_upstack(TREG_EAX, 1); 791 863 if (op == TOK_UMULL) { 792 864 o(0xf7); /* mul fr */ … … 816 888 817 889 /* generate a floating point operation 'v = t1 op t2' instruction. The 818 two operands are guarante d to have the same floating point type */890 two operands are guaranteed to have the same floating point type */ 819 891 /* XXX: need to use ST1 too */ 820 892 ST_FUNC void gen_opf(int op) … … 855 927 if (swapped) 856 928 o(0xc9d9); /* fxch %st(1) */ 857 o(0xe9da); /* fucompp */ 929 if (op == TOK_EQ || op == TOK_NE) 930 o(0xe9da); /* fucompp */ 931 else 932 o(0xd9de); /* fcompp */ 858 933 o(0xe0df); /* fnstsw %ax */ 859 934 if (op == TOK_EQ) { … … 901 976 } 902 977 ft = vtop->type.t; 903 fc = vtop->c. ul;978 fc = vtop->c.i; 904 979 if ((ft & VT_BTYPE) == VT_LDOUBLE) { 905 980 o(0xde); /* fxxxp %st, %st(1) */ … … 913 988 v1.type.t = VT_INT; 914 989 v1.r = VT_LOCAL | VT_LVAL; 915 v1.c. ul= fc;990 v1.c.i = fc; 916 991 load(r, &v1); 917 992 fc = 0; … … 959 1034 960 1035 /* convert fp to int 't' type */ 961 /* XXX: handle long long case */962 1036 ST_FUNC void gen_cvt_ftoi(int t) 963 1037 { 964 int r, r2, size; 965 Sym *sym; 966 CType ushort_type; 967 968 ushort_type.t = VT_SHORT | VT_UNSIGNED; 969 ushort_type.ref = 0; 970 971 gv(RC_FLOAT); 972 if (t != VT_INT) 973 size = 8; 974 else 975 size = 4; 976 977 o(0x2dd9); /* ldcw xxx */ 978 sym = external_global_sym(TOK___tcc_int_fpu_control, 979 &ushort_type, VT_LVAL); 980 greloc(cur_text_section, sym, 981 ind, R_386_32); 982 gen_le32(0); 983 984 oad(0xec81, size); /* sub $xxx, %esp */ 985 if (size == 4) 986 o(0x1cdb); /* fistpl */ 1038 int bt = vtop->type.t & VT_BTYPE; 1039 if (bt == VT_FLOAT) 1040 vpush_global_sym(&func_old_type, TOK___fixsfdi); 1041 else if (bt == VT_LDOUBLE) 1042 vpush_global_sym(&func_old_type, TOK___fixxfdi); 987 1043 else 988 o(0x3cdf); /* fistpll */ 989 o(0x24); 990 o(0x2dd9); /* ldcw xxx */ 991 sym = external_global_sym(TOK___tcc_fpu_control, 992 &ushort_type, VT_LVAL); 993 greloc(cur_text_section, sym, 994 ind, R_386_32); 995 gen_le32(0); 996 997 r = get_reg(RC_INT); 998 o(0x58 + r); /* pop r */ 999 if (size == 8) { 1000 if (t == VT_LLONG) { 1001 vtop->r = r; /* mark reg as used */ 1002 r2 = get_reg(RC_INT); 1003 o(0x58 + r2); /* pop r2 */ 1004 vtop->r2 = r2; 1005 } else { 1006 o(0x04c483); /* add $4, %esp */ 1007 } 1008 } 1009 vtop->r = r; 1044 vpush_global_sym(&func_old_type, TOK___fixdfdi); 1045 vswap(); 1046 gfunc_call(1); 1047 vpushi(0); 1048 vtop->r = REG_IRET; 1049 vtop->r2 = REG_LRET; 1010 1050 } 1011 1051 … … 1030 1070 ST_FUNC void gen_bounded_ptr_add(void) 1031 1071 { 1032 Sym *sym;1033 1034 1072 /* prepare fast i386 function call (args in eax and edx) */ 1035 1073 gv2(RC_EAX, RC_EDX); … … 1038 1076 save_regs(0); 1039 1077 /* do a fast function call */ 1040 sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0); 1041 greloc(cur_text_section, sym, 1042 ind + 1, R_386_PC32); 1043 oad(0xe8, -4); 1078 gen_static_call(TOK___bound_ptr_add); 1044 1079 /* returned pointer is in eax */ 1045 1080 vtop++; 1046 1081 vtop->r = TREG_EAX | VT_BOUNDED; 1047 1082 /* address of bounding function call point */ 1048 vtop->c. ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));1083 vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); 1049 1084 } 1050 1085 … … 1053 1088 ST_FUNC void gen_bounded_ptr_deref(void) 1054 1089 { 1055 int func;1056 int size, align;1090 addr_t func; 1091 int size, align; 1057 1092 Elf32_Rel *rel; 1058 1093 Sym *sym; … … 1083 1118 /* patch relocation */ 1084 1119 /* XXX: find a better solution ? */ 1085 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c. ul);1120 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i); 1086 1121 sym = external_global_sym(func, &func_old_type, 0); 1087 1122 if (!sym->c) … … 1091 1126 #endif 1092 1127 1128 /* Save the stack pointer onto the stack */ 1129 ST_FUNC void gen_vla_sp_save(int addr) { 1130 /* mov %esp,addr(%ebp)*/ 1131 o(0x89); 1132 gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); 1133 } 1134 1135 /* Restore the SP from a location on the stack */ 1136 ST_FUNC void gen_vla_sp_restore(int addr) { 1137 o(0x8b); 1138 gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); 1139 } 1140 1141 /* Subtract from the stack pointer, and push the resulting value onto the stack */ 1142 ST_FUNC void gen_vla_alloc(CType *type, int align) { 1143 #ifdef TCC_TARGET_PE 1144 /* alloca does more than just adjust %rsp on Windows */ 1145 vpush_global_sym(&func_old_type, TOK_alloca); 1146 vswap(); /* Move alloca ref past allocation size */ 1147 gfunc_call(1); 1148 #else 1149 int r; 1150 r = gv(RC_INT); /* allocation size */ 1151 /* sub r,%rsp */ 1152 o(0x2b); 1153 o(0xe0 | r); 1154 /* We align to 16 bytes rather than align */ 1155 /* and ~15, %esp */ 1156 o(0xf0e483); 1157 vpop(); 1158 #endif 1159 } 1160 1093 1161 /* end of X86 code generator */ 1094 1162 /*************************************************************/
Note:
See TracChangeset
for help on using the changeset viewer.