Unified · Split
| @@ -530,74 +530,77 @@ long double __floatundixf(unsigned long long a) · 529 unmodified lines | ||
| 530 | 530 | |
| 531 | 531 | unsigned long long __fixunssfdi (float a1) |
| 532 | 532 | { |
| 533 | − register union float_long fl1; | |
| 534 | − register int exp; | |
| 535 | − register unsigned long l; | |
| 536 | − | |
| 537 | − fl1.f = a1; | |
| 538 | − | |
| 539 | − if (fl1.l == 0) | |
| 540 | − return (0); | |
| 541 | − | |
| 542 | − exp = EXP (fl1.l) - EXCESS - 24; | |
| 543 | − | |
| 544 | − l = MANT(fl1.l); | |
| 545 | − if (exp >= 41) | |
| 546 | − return (unsigned long long)-1; | |
| 547 | − else if (exp >= 0) | |
| 548 | − return (unsigned long long)l << exp; | |
| 549 | − else if (exp >= -23) | |
| 550 | − return l >> -exp; | |
| 551 | − else | |
| 552 | − return 0; | |
| 533 | + register union float_long fl1; | |
| 534 | + register int exp; | |
| 535 | + register unsigned long l; | |
| 536 | + int s; | |
| 537 | + fl1.f = a1; | |
| 538 | + | |
| 539 | + if (fl1.l == 0) | |
| 540 | + return 0; | |
| 541 | + | |
| 542 | + exp = EXP (fl1.l) - EXCESS - 24; | |
| 543 | + | |
| 544 | + l = MANT(fl1.l); | |
| 545 | + s = SIGN(fl1.l)? -1: 1; | |
| 546 | + if (exp >= 64) | |
| 547 | + return (unsigned long long)-1; | |
| 548 | + else if (exp >= 0) | |
| 549 | + return ((unsigned long long)l << exp)*s; | |
| 550 | + else if (exp >= -23) | |
| 551 | + return (l >> -exp)*s; | |
| 552 | + else | |
| 553 | + return 0; | |
| 553 | 554 | } |
| 554 | 555 | |
| 555 | 556 | unsigned long long __fixunsdfdi (double a1) |
| 556 | 557 | { |
| 557 | − register union double_long dl1; | |
| 558 | − register int exp; | |
| 559 | − register unsigned long long l; | |
| 560 | − | |
| 561 | − dl1.d = a1; | |
| 562 | − | |
| 563 | − if (dl1.ll == 0) | |
| 564 | − return (0); | |
| 565 | − | |
| 566 | − exp = EXPD (dl1) - EXCESSD - 53; | |
| 567 | − | |
| 568 | − l = MANTD_LL(dl1); | |
| 569 | − | |
| 570 | − if (exp >= 12) | |
| 571 | − return (unsigned long long)-1; | |
| 572 | − else if (exp >= 0) | |
| 573 | − return l << exp; | |
| 574 | − else if (exp >= -52) | |
| 575 | − return l >> -exp; | |
| 576 | − else | |
| 577 | − return 0; | |
| 558 | + register union double_long dl1; | |
| 559 | + register int exp; | |
| 560 | + register unsigned long long l; | |
| 561 | + int s; | |
| 562 | + dl1.d = a1; | |
| 563 | + | |
| 564 | + if (dl1.ll == 0) | |
| 565 | + return (0); | |
| 566 | + | |
| 567 | + exp = EXPD (dl1) - EXCESSD - 53; | |
| 568 | + | |
| 569 | + l = MANTD_LL(dl1); | |
| 570 | + s = SIGND(dl1)? -1: 1; | |
| 571 | + if (exp >= 64) | |
| 572 | + return (unsigned long long)-1; | |
| 573 | + else if (exp >= 0) | |
| 574 | + return (l << exp)*s; | |
| 575 | + else if (exp >= -52) | |
| 576 | + return (l >> -exp)*s; | |
| 577 | + else | |
| 578 | + return 0; | |
| 578 | 579 | } |
| 579 | 580 | |
| 580 | 581 | unsigned long long __fixunsxfdi (long double a1) |
| 581 | 582 | { |
| 582 | − register union ldouble_long dl1; | |
| 583 | − register int exp; | |
| 584 | − register unsigned long long l; | |
| 585 | − | |
| 586 | − dl1.ld = a1; | |
| 587 | − | |
| 588 | − if (dl1.l.lower == 0 && dl1.l.upper == 0) | |
| 589 | − return (0); | |
| 590 | − | |
| 591 | − exp = EXPLD (dl1) - EXCESSLD - 64; | |
| 592 | − | |
| 593 | − l = dl1.l.lower; | |
| 594 | − | |
| 595 | − if (exp > 0) | |
| 596 | − return (unsigned long long)-1; | |
| 597 | − else if (exp >= -63) | |
| 598 | − return l >> -exp; | |
| 599 | − else | |
| 600 | − return 0; | |
| 583 | + register union ldouble_long dl1; | |
| 584 | + register int exp; | |
| 585 | + register unsigned long long l; | |
| 586 | + int s; | |
| 587 | + dl1.ld = a1; | |
| 588 | + | |
| 589 | + if (dl1.l.lower == 0 && dl1.l.upper == 0) | |
| 590 | + return (0); | |
| 591 | + | |
| 592 | + exp = EXPLD (dl1) - EXCESSLD - 64; | |
| 593 | + s = SIGNLD(dl1)? -1: 1; | |
| 594 | + l = dl1.l.lower; | |
| 595 | + | |
| 596 | + if (exp >= 64) | |
| 597 | + return (unsigned long long)-1; | |
| 598 | + else if (exp >= 0) | |
| 599 | + return ((unsigned long long)l << exp)*s; | |
| 600 | + else if (exp >= -64) | |
| 601 | + return (l >> -exp)*s; | |
| 602 | + else | |
| 603 | + return 0; | |
| 601 | 604 | } |
| 602 | 605 | |
| 603 | 606 | long long __fixsfdi (float a1) |
| @@ -637,7 +640,7 @@ extern void abort(void); · 33 unmodified lines | ||
| 637 | 640 | #endif |
| 638 | 641 | |
| 639 | 642 | enum __va_arg_type { |
| 640 | − __va_gen_reg, __va_float_reg, __va_stack | |
| 643 | + __va_gen_reg, __va_float_reg, __va_ld_reg, __va_stack | |
| 641 | 644 | }; |
| 642 | 645 | |
| 643 | 646 | //This should be in sync with the declaration on our include/stdarg.h |
| @@ -688,10 +691,11 @@ void *__va_arg(__va_list_struct *ap, · 44 unmodified lines | ||
| 688 | 691 | size = 8; |
| 689 | 692 | goto use_overflow_area; |
| 690 | 693 | |
| 694 | + case __va_ld_reg: | |
| 695 | + ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align); | |
| 691 | 696 | case __va_stack: |
| 692 | 697 | use_overflow_area: |
| 693 | 698 | ap->overflow_arg_area += size; |
| 694 | − ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align); | |
| 695 | 699 | return ap->overflow_arg_area - size; |
| 696 | 700 | |
| 697 | 701 | default: |
| @@ -1194,6 +1194,7 @@ ST_DATA int func_var; /* true if current function is variadic */ · 1193 unmodified lines | ||
| 1194 | 1194 | ST_DATA int func_vc; |
| 1195 | 1195 | ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ |
| 1196 | 1196 | ST_DATA char *funcname; |
| 1197 | +ST_DATA int pop_stack; | |
| 1197 | 1198 | |
| 1198 | 1199 | ST_INLN int is_float(int t); |
| 1199 | 1200 | ST_FUNC int ieee_finite(double d); |
| @@ -70,6 +70,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in · 69 unmodified lines | ||
| 70 | 70 | ST_DATA int func_vc; |
| 71 | 71 | ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ |
| 72 | 72 | ST_DATA char *funcname; |
| 73 | +ST_DATA int pop_stack; | |
| 73 | 74 | |
| 74 | 75 | ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; |
| 75 | 76 | |
| @@ -524,6 +525,41 @@ static void vdup(void) · 448 unmodified lines | ||
| 524 | 525 | vpushv(vtop); |
| 525 | 526 | } |
| 526 | 527 | |
| 528 | +static int align_size(int size) | |
| 529 | +{ | |
| 530 | +#ifdef TCC_TARGET_X86_64 | |
| 531 | + if(size > 4) | |
| 532 | + return 8; | |
| 533 | + else | |
| 534 | +#endif | |
| 535 | + if(size > 2) | |
| 536 | + return 4; | |
| 537 | + else if(size > 1) | |
| 538 | + return 2; | |
| 539 | + else | |
| 540 | + return 1; | |
| 541 | +} | |
| 542 | + | |
| 543 | +int loc_stack(int size, int is_sub){ | |
| 544 | + int l, align; | |
| 545 | + align = align_size(size); | |
| 546 | + size = (size + align - 1) & - align; | |
| 547 | + if(is_sub){ | |
| 548 | + pop_stack -= size; | |
| 549 | + if(pop_stack >= 0) | |
| 550 | + l = loc + pop_stack; | |
| 551 | + else{ | |
| 552 | + loc += pop_stack; | |
| 553 | + l = loc &= -align; | |
| 554 | + pop_stack = 0; | |
| 555 | + } | |
| 556 | + }else{ | |
| 557 | + pop_stack += size; | |
| 558 | + l = loc + pop_stack; | |
| 559 | + } | |
| 560 | + return l; | |
| 561 | +} | |
| 562 | + | |
| 527 | 563 | /* save r to the memory stack, and mark it as being free */ |
| 528 | 564 | ST_FUNC void save_reg(int r) |
| 529 | 565 | { |
| @@ -924,13 +960,10 @@ ST_FUNC int gv(int rc) · 394 unmodified lines | ||
| 924 | 960 | /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ |
| 925 | 961 | ST_FUNC void gv2(int rc1, int rc2) |
| 926 | 962 | { |
| 927 | − int v; | |
| 928 | − | |
| 929 | 963 | /* generate more generic register first. But VT_JMP or VT_CMP |
| 930 | 964 | values must be generated first in all cases to avoid possible |
| 931 | 965 | reload errors */ |
| 932 | − v = vtop[0].r & VT_VALMASK; | |
| 933 | − if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) { | |
| 966 | + if (rc1 <= rc2) { | |
| 934 | 967 | vswap(); |
| 935 | 968 | gv(rc1); |
| 936 | 969 | vswap(); |
| @@ -1018,6 +1051,7 @@ ST_FUNC void lexpand_nr(void) · 81 unmodified lines | ||
| 1018 | 1051 | } |
| 1019 | 1052 | #endif |
| 1020 | 1053 | |
| 1054 | +#ifndef TCC_TARGET_X86_64 | |
| 1021 | 1055 | /* build a long long from two ints */ |
| 1022 | 1056 | static void lbuild(int t) |
| 1023 | 1057 | { |
| @@ -1026,6 +1060,7 @@ static void lbuild(int t) · 2 unmodified lines | ||
| 1026 | 1060 | vtop[-1].type.t = t; |
| 1027 | 1061 | vpop(); |
| 1028 | 1062 | } |
| 1063 | +#endif | |
| 1029 | 1064 | |
| 1030 | 1065 | /* rotate n first stack elements to the bottom |
| 1031 | 1066 | I1 ... In -> I2 ... In I1 [top is right] |
| @@ -1087,8 +1122,8 @@ static void gv_dup(void) · 55 unmodified lines | ||
| 1087 | 1122 | { |
| 1088 | 1123 | int rc, t, r, r1; |
| 1089 | 1124 | SValue sv; |
| 1090 | − | |
| 1091 | 1125 | t = vtop->type.t; |
| 1126 | +#ifndef TCC_TARGET_X86_64 | |
| 1092 | 1127 | if ((t & VT_BTYPE) == VT_LLONG) { |
| 1093 | 1128 | lexpand(); |
| 1094 | 1129 | gv_dup(); |
| @@ -1098,15 +1133,14 @@ static void gv_dup(void) · 3 unmodified lines | ||
| 1098 | 1133 | vrotb(4); |
| 1099 | 1134 | /* stack: H L L1 H1 */ |
| 1100 | 1135 | lbuild(t); |
| 1101 | − vrotb(3); | |
| 1102 | − vrotb(3); | |
| 1136 | + vrott(3); | |
| 1103 | 1137 | vswap(); |
| 1104 | 1138 | lbuild(t); |
| 1105 | 1139 | vswap(); |
| 1106 | − } else { | |
| 1140 | + } else | |
| 1141 | +#endif | |
| 1142 | + { | |
| 1107 | 1143 | /* duplicate value */ |
| 1108 | − rc = RC_INT; | |
| 1109 | − sv.type.t = VT_INT; | |
| 1110 | 1144 | if (is_float(t)) { |
| 1111 | 1145 | rc = RC_FLOAT; |
| 1112 | 1146 | #ifdef TCC_TARGET_X86_64 |
| @@ -1114,8 +1148,9 @@ static void gv_dup(void) · 1 unmodified line | ||
| 1114 | 1148 | rc = RC_ST0; |
| 1115 | 1149 | } |
| 1116 | 1150 | #endif |
| 1117 | − sv.type.t = t; | |
| 1118 | − } | |
| 1151 | + }else | |
| 1152 | + rc = RC_INT; | |
| 1153 | + sv.type.t = t; | |
| 1119 | 1154 | r = gv(rc); |
| 1120 | 1155 | r1 = get_reg(rc); |
| 1121 | 1156 | sv.r = r; |
| @@ -1127,7 +1162,6 @@ static void gv_dup(void) · 5 unmodified lines | ||
| 1127 | 1162 | vtop->r = r1; |
| 1128 | 1163 | } |
| 1129 | 1164 | } |
| 1130 | − | |
| 1131 | 1165 | #ifndef TCC_TARGET_X86_64 |
| 1132 | 1166 | /* generate CPU independent (unsigned) long long operations */ |
| 1133 | 1167 | static void gen_opl(int op) |
| @@ -2441,17 +2475,78 @@ static void gen_assign_cast(CType *dt) · 1307 unmodified lines | ||
| 2441 | 2475 | gen_cast(dt); |
| 2442 | 2476 | } |
| 2443 | 2477 | |
| 2478 | +static void vstore_im(){ | |
| 2479 | + int rc, ft, sbt, dbt, t, r; | |
| 2480 | + ft = vtop[-1].type.t; | |
| 2481 | + sbt = vtop->type.t & VT_BTYPE; | |
| 2482 | + dbt = ft & VT_BTYPE; | |
| 2483 | + if (is_float(ft)) { | |
| 2484 | + rc = RC_FLOAT; | |
| 2485 | +#ifdef TCC_TARGET_X86_64 | |
| 2486 | + if (dbt == VT_LDOUBLE) { | |
| 2487 | + rc = RC_ST0; | |
| 2488 | + } | |
| 2489 | +#endif | |
| 2490 | + }else | |
| 2491 | + rc = RC_INT; | |
| 2492 | + r = gv(rc); /* generate value */ | |
| 2493 | + /* if lvalue was saved on stack, must read it */ | |
| 2494 | + if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { | |
| 2495 | + SValue sv; | |
| 2496 | + t = get_reg(RC_INT); | |
| 2497 | +#ifdef TCC_TARGET_X86_64 | |
| 2498 | + sv.type.t = VT_PTR; | |
| 2499 | +#else | |
| 2500 | + sv.type.t = VT_INT; | |
| 2501 | +#endif | |
| 2502 | + sv.r = VT_LOCAL | VT_LVAL; | |
| 2503 | + sv.c.ul = vtop[-1].c.ul; | |
| 2504 | + load(t, &sv); | |
| 2505 | + vtop[-1].r = t | VT_LVAL; | |
| 2506 | + vtop[-1].c.ul = 0; | |
| 2507 | + } | |
| 2508 | + /* two word case handling : store second register at word + 4 */ | |
| 2509 | +#ifdef TCC_TARGET_X86_64 | |
| 2510 | + if ((dbt == VT_QLONG) || (dbt == VT_QFLOAT)) | |
| 2511 | +#else | |
| 2512 | + if (dbt == VT_LLONG) | |
| 2513 | +#endif | |
| 2514 | + { | |
| 2515 | +#ifdef TCC_TARGET_X86_64 | |
| 2516 | + int load_size = 8, load_type = (sbt == VT_QLONG) ? VT_LLONG : VT_DOUBLE; | |
| 2517 | +#else | |
| 2518 | + int load_size = 4, load_type = VT_INT; | |
| 2519 | +#endif | |
| 2520 | + vtop[-1].type.t = load_type; | |
| 2521 | + store(r, vtop - 1); | |
| 2522 | + vswap(); | |
| 2523 | + /* convert to int to increment easily */ | |
| 2524 | + vtop->type = char_pointer_type; | |
| 2525 | + gaddrof(); | |
| 2526 | + vpushi(load_size); | |
| 2527 | + gen_op('+'); | |
| 2528 | + vtop->r |= VT_LVAL; | |
| 2529 | + vswap(); | |
| 2530 | + vtop[-1].type.t = load_type; | |
| 2531 | + /* XXX: it works because r2 is spilled last ! */ | |
| 2532 | + store(vtop->r2, vtop - 1); | |
| 2533 | + vtop->type.t = ft; | |
| 2534 | + vtop[-1].type.t = ft; | |
| 2535 | + } else { | |
| 2536 | + store(r, vtop - 1); | |
| 2537 | + } | |
| 2538 | +} | |
| 2539 | + | |
| 2444 | 2540 | /* store vtop in lvalue pushed on stack */ |
| 2445 | 2541 | ST_FUNC void vstore(void) |
| 2446 | 2542 | { |
| 2447 | − int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast; | |
| 2543 | + int sbt, dbt, ft, size, align, bit_size, bit_pos, delayed_cast; | |
| 2448 | 2544 | |
| 2449 | 2545 | ft = vtop[-1].type.t; |
| 2450 | 2546 | sbt = vtop->type.t & VT_BTYPE; |
| 2451 | 2547 | dbt = ft & VT_BTYPE; |
| 2452 | 2548 | if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) || |
| 2453 | − (sbt == VT_INT && dbt == VT_SHORT)) | |
| 2454 | − && !(vtop->type.t & VT_BITFIELD)) { | |
| 2549 | + (sbt == VT_INT && dbt == VT_SHORT)) && !(vtop->type.t & VT_BITFIELD)) { | |
| 2455 | 2550 | /* optimize char/short casts */ |
| 2456 | 2551 | delayed_cast = VT_MUSTCAST; |
| 2457 | 2552 | vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT))); |
| @@ -2507,15 +2602,15 @@ ST_FUNC void vstore(void) · 49 unmodified lines | ||
| 2507 | 2602 | vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); |
| 2508 | 2603 | |
| 2509 | 2604 | /* duplicate source into other register */ |
| 2510 | − gv_dup(); | |
| 2511 | − vswap(); | |
| 2512 | − vrott(3); | |
| 2513 | − | |
| 2514 | 2605 | if((ft & VT_BTYPE) == VT_BOOL) { |
| 2515 | 2606 | gen_cast(&vtop[-1].type); |
| 2516 | 2607 | vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED); |
| 2517 | 2608 | } |
| 2518 | 2609 | |
| 2610 | + /* duplicate destination */ | |
| 2611 | + vdup(); | |
| 2612 | + vtop[-1] = vtop[-2]; | |
| 2613 | + | |
| 2519 | 2614 | /* duplicate destination */ |
| 2520 | 2615 | vdup(); |
| 2521 | 2616 | vtop[-1] = vtop[-2]; |
| @@ -2556,56 +2651,7 @@ ST_FUNC void vstore(void) · 34 unmodified lines | ||
| 2556 | 2651 | } |
| 2557 | 2652 | #endif |
| 2558 | 2653 | if (!nocode_wanted) { |
| 2559 | − rc = RC_INT; | |
| 2560 | − if (is_float(ft)) { | |
| 2561 | − rc = RC_FLOAT; | |
| 2562 | −#ifdef TCC_TARGET_X86_64 | |
| 2563 | − if ((ft & VT_BTYPE) == VT_LDOUBLE) { | |
| 2564 | − rc = RC_ST0; | |
| 2565 | − } else if ((ft & VT_BTYPE) == VT_QFLOAT) { | |
| 2566 | − rc = RC_FRET; | |
| 2567 | − } | |
| 2568 | −#endif | |
| 2569 | − } | |
| 2570 | − r = gv(rc); /* generate value */ | |
| 2571 | − /* if lvalue was saved on stack, must read it */ | |
| 2572 | − if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { | |
| 2573 | − SValue sv; | |
| 2574 | − t = get_reg(RC_INT); | |
| 2575 | −#ifdef TCC_TARGET_X86_64 | |
| 2576 | − sv.type.t = VT_PTR; | |
| 2577 | −#else | |
| 2578 | − sv.type.t = VT_INT; | |
| 2579 | −#endif | |
| 2580 | − sv.r = VT_LOCAL | VT_LVAL; | |
| 2581 | − sv.c.ul = vtop[-1].c.ul; | |
| 2582 | − load(t, &sv); | |
| 2583 | − vtop[-1].r = t | VT_LVAL; | |
| 2584 | − } | |
| 2585 | − /* two word case handling : store second register at word + 4 (or +8 for x86-64) */ | |
| 2586 | −#ifdef TCC_TARGET_X86_64 | |
| 2587 | − if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) { | |
| 2588 | − int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE; | |
| 2589 | −#else | |
| 2590 | − if ((ft & VT_BTYPE) == VT_LLONG) { | |
| 2591 | − int addr_type = VT_INT, load_size = 4, load_type = VT_INT; | |
| 2592 | −#endif | |
| 2593 | − vtop[-1].type.t = load_type; | |
| 2594 | − store(r, vtop - 1); | |
| 2595 | − vswap(); | |
| 2596 | − /* convert to int to increment easily */ | |
| 2597 | − vtop->type.t = addr_type; | |
| 2598 | − gaddrof(); | |
| 2599 | − vpushi(load_size); | |
| 2600 | − gen_op('+'); | |
| 2601 | − vtop->r |= VT_LVAL; | |
| 2602 | − vswap(); | |
| 2603 | − vtop[-1].type.t = load_type; | |
| 2604 | − /* XXX: it works because r2 is spilled last ! */ | |
| 2605 | − store(vtop->r2, vtop - 1); | |
| 2606 | − } else { | |
| 2607 | − store(r, vtop - 1); | |
| 2608 | − } | |
| 2654 | + vstore_im(); | |
| 2609 | 2655 | } |
| 2610 | 2656 | vswap(); |
| 2611 | 2657 | vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ |
| @@ -4623,6 +4669,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 2011 unmodified lines | ||
| 4623 | 4669 | gsym_addr(b, d); |
| 4624 | 4670 | } else if (tok == '{') { |
| 4625 | 4671 | Sym *llabel; |
| 4672 | + int saved_loc, saved_pop_stack, size; | |
| 4626 | 4673 | int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags; |
| 4627 | 4674 | |
| 4628 | 4675 | next(); |
| @@ -4632,7 +4679,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 3 unmodified lines | ||
| 4632 | 4679 | frame_bottom->next = scope_stack_bottom; |
| 4633 | 4680 | scope_stack_bottom = frame_bottom; |
| 4634 | 4681 | llabel = local_label_stack; |
| 4635 | − | |
| 4682 | + | |
| 4683 | + saved_loc = loc; | |
| 4684 | + saved_pop_stack = pop_stack; | |
| 4685 | + | |
| 4636 | 4686 | /* save VLA state */ |
| 4637 | 4687 | block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc); |
| 4638 | 4688 | if (saved_vla_sp_loc != &vla_sp_root_loc) |
| @@ -4684,7 +4734,12 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 45 unmodified lines | ||
| 4684 | 4734 | /* pop locally defined symbols */ |
| 4685 | 4735 | scope_stack_bottom = scope_stack_bottom->next; |
| 4686 | 4736 | sym_pop(&local_stack, s); |
| 4687 | − | |
| 4737 | + | |
| 4738 | + size = -(loc - saved_loc); | |
| 4739 | + pop_stack = saved_pop_stack; | |
| 4740 | + if(size) | |
| 4741 | + pop_stack += size; | |
| 4742 | + | |
| 4688 | 4743 | /* Pop VLA frames and restore stack pointer if required */ |
| 4689 | 4744 | if (saved_vla_sp_loc != &vla_sp_root_loc) |
| 4690 | 4745 | *saved_vla_sp_loc = block_vla_sp_loc; |
| @@ -1680,7 +1680,6 @@ void prefix ## fcast(type a)\ · 1679 unmodified lines | ||
| 1680 | 1680 | printf("ftof: %f %f %Lf\n", fa, da, la);\ |
| 1681 | 1681 | ia = (int)a;\ |
| 1682 | 1682 | llia = (long long)a;\ |
| 1683 | − a = (a >= 0) ? a : -a;\ | |
| 1684 | 1683 | ua = (unsigned int)a;\ |
| 1685 | 1684 | llua = (unsigned long long)a;\ |
| 1686 | 1685 | printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\ |
| @@ -1710,6 +1709,18 @@ void prefix ## call(void)\ · 23 unmodified lines | ||
| 1710 | 1709 | printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\ |
| 1711 | 1710 | }\ |
| 1712 | 1711 | \ |
| 1712 | +void prefix ## calc(type x, type y)\ | |
| 1713 | +{\ | |
| 1714 | + x=x*x;y=y*y;\ | |
| 1715 | + printf("%d, %d\n", (int)x, (int)y);\ | |
| 1716 | + x=x-y;y=y-x;\ | |
| 1717 | + printf("%d, %d\n", (int)x, (int)y);\ | |
| 1718 | + x=x/y;y=y/x;\ | |
| 1719 | + printf("%d, %d\n", (int)x, (int)y);\ | |
| 1720 | + x=x+x;y=y+y;\ | |
| 1721 | + printf("%d, %d\n", (int)x, (int)y);\ | |
| 1722 | +}\ | |
| 1723 | +\ | |
| 1713 | 1724 | void prefix ## signed_zeros(void) \ |
| 1714 | 1725 | {\ |
| 1715 | 1726 | type x = 0.0, y = -0.0, n, p;\ |
| @@ -1732,7 +1743,7 @@ void prefix ## signed_zeros(void) \ · 16 unmodified lines | ||
| 1732 | 1743 | 1.0 / x != 1.0 / p);\ |
| 1733 | 1744 | else\ |
| 1734 | 1745 | printf ("x != +y; this is wrong!\n");\ |
| 1735 | − p = -y;\ | |
| 1746 | + p = -y;\ | |
| 1736 | 1747 | if (x == p)\ |
| 1737 | 1748 | printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\ |
| 1738 | 1749 | 1.0 / x != 1.0 / p);\ |
| @@ -1748,7 +1759,8 @@ void prefix ## test(void)\ · 9 unmodified lines | ||
| 1748 | 1759 | prefix ## fcast(234.6);\ |
| 1749 | 1760 | prefix ## fcast(-2334.6);\ |
| 1750 | 1761 | prefix ## call();\ |
| 1751 | − prefix ## signed_zeros();\ | |
| 1762 | + prefix ## calc(1, 1.0000000000000001);\ | |
| 1763 | + prefix ## signed_zeros();\ | |
| 1752 | 1764 | } |
| 1753 | 1765 | |
| 1754 | 1766 | FTEST(f, float, float, "%f") |
| @@ -2572,7 +2584,6 @@ int constant_p_var; · 817 unmodified lines | ||
| 2572 | 2584 | |
| 2573 | 2585 | void builtin_test(void) |
| 2574 | 2586 | { |
| 2575 | −#if GCC_MAJOR >= 3 | |
| 2576 | 2587 | COMPAT_TYPE(int, int); |
| 2577 | 2588 | COMPAT_TYPE(int, unsigned int); |
| 2578 | 2589 | COMPAT_TYPE(int, char); |
| @@ -2582,9 +2593,9 @@ void builtin_test(void) · 3 unmodified lines | ||
| 2582 | 2593 | COMPAT_TYPE(int *, void *); |
| 2583 | 2594 | COMPAT_TYPE(int *, const int *); |
| 2584 | 2595 | COMPAT_TYPE(char *, unsigned char *); |
| 2596 | + COMPAT_TYPE(char, unsigned char); | |
| 2585 | 2597 | /* space is needed because tcc preprocessor introduces a space between each token */ |
| 2586 | − COMPAT_TYPE(char * *, void *); | |
| 2587 | −#endif | |
| 2598 | + COMPAT_TYPE(char **, void *); | |
| 2588 | 2599 | printf("res = %d\n", __builtin_constant_p(1)); |
| 2589 | 2600 | printf("res = %d\n", __builtin_constant_p(1 + 2)); |
| 2590 | 2601 | printf("res = %d\n", __builtin_constant_p(&constant_p_var)); |
| @@ -826,7 +826,7 @@ void gfunc_prolog(CType *func_type) · 825 unmodified lines | ||
| 826 | 826 | |
| 827 | 827 | func_ret_sub = 0; |
| 828 | 828 | func_scratch = 0; |
| 829 | − loc = 0; | |
| 829 | + pop_stack = loc = 0; | |
| 830 | 830 | |
| 831 | 831 | addr = PTR_SIZE * 2; |
| 832 | 832 | ind += FUNC_PROLOG_SIZE; |
| @@ -968,12 +968,14 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) · 135 unmodified lines | ||
| 968 | 968 | case VT_BYTE: |
| 969 | 969 | case VT_SHORT: |
| 970 | 970 | case VT_LLONG: |
| 971 | + case VT_QLONG: | |
| 971 | 972 | case VT_BOOL: |
| 972 | 973 | case VT_PTR: |
| 973 | 974 | case VT_FUNC: |
| 974 | 975 | case VT_ENUM: return x86_64_mode_integer; |
| 975 | 976 | |
| 976 | 977 | case VT_FLOAT: |
| 978 | + case VT_QFLOAT: | |
| 977 | 979 | case VT_DOUBLE: return x86_64_mode_sse; |
| 978 | 980 | |
| 979 | 981 | case VT_LDOUBLE: return x86_64_mode_x87; |
| @@ -984,7 +986,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) · 4 unmodified lines | ||
| 984 | 986 | // Detect union |
| 985 | 987 | if (f->next && (f->c == f->next->c)) |
| 986 | 988 | return x86_64_mode_memory; |
| 987 | − | |
| 989 | + | |
| 988 | 990 | mode = x86_64_mode_none; |
| 989 | 991 | for (f = f->next; f; f = f->next) |
| 990 | 992 | mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type)); |
| @@ -995,14 +997,14 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) · 4 unmodified lines | ||
| 995 | 997 | assert(0); |
| 996 | 998 | } |
| 997 | 999 | |
| 998 | −static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) | |
| 1000 | +static int classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) | |
| 999 | 1001 | { |
| 1000 | 1002 | X86_64_Mode mode; |
| 1001 | 1003 | int size, align, ret_t = 0; |
| 1002 | 1004 | |
| 1003 | 1005 | if (ty->t & (VT_BITFIELD|VT_ARRAY)) { |
| 1004 | 1006 | *psize = 8; |
| 1005 | − *palign = 8; | |
| 1007 | + *palign = 8; | |
| 1006 | 1008 | *reg_count = 1; |
| 1007 | 1009 | ret_t = ty->t; |
| 1008 | 1010 | mode = x86_64_mode_integer; |
| @@ -1013,6 +1015,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p · 4 unmodified lines | ||
| 1013 | 1015 | |
| 1014 | 1016 | if (size > 16) { |
| 1015 | 1017 | mode = x86_64_mode_memory; |
| 1018 | + ret_t = ty->t; | |
| 1016 | 1019 | } else { |
| 1017 | 1020 | mode = classify_x86_64_inner(ty); |
| 1018 | 1021 | switch (mode) { |
| @@ -1021,16 +1024,22 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p · 2 unmodified lines | ||
| 1021 | 1024 | *reg_count = 2; |
| 1022 | 1025 | ret_t = VT_QLONG; |
| 1023 | 1026 | } else { |
| 1024 | − *reg_count = 1; | |
| 1025 | − ret_t = (size > 4) ? VT_LLONG : VT_INT; | |
| 1026 | − } | |
| 1027 | + *reg_count = 1; | |
| 1028 | + if(size > 4) | |
| 1029 | + ret_t = VT_LLONG; | |
| 1030 | + else if(size > 2){ | |
| 1031 | + ret_t = VT_INT; | |
| 1032 | + }else if(size > 1) | |
| 1033 | + ret_t = VT_SHORT; | |
| 1034 | + else | |
| 1035 | + ret_t = VT_BYTE; | |
| 1036 | + } | |
| 1037 | + ret_t |= (ty->t & VT_UNSIGNED); | |
| 1027 | 1038 | break; |
| 1028 | − | |
| 1029 | 1039 | case x86_64_mode_x87: |
| 1030 | 1040 | *reg_count = 1; |
| 1031 | 1041 | ret_t = VT_LDOUBLE; |
| 1032 | 1042 | break; |
| 1033 | − | |
| 1034 | 1043 | case x86_64_mode_sse: |
| 1035 | 1044 | if (size > 8) { |
| 1036 | 1045 | *reg_count = 2; |
| @@ -1040,13 +1049,15 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p · 3 unmodified lines | ||
| 1040 | 1049 | ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT; |
| 1041 | 1050 | } |
| 1042 | 1051 | break; |
| 1043 | − default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/ | |
| 1052 | + default: | |
| 1053 | + ret_t = ty->t; | |
| 1054 | + break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/ | |
| 1044 | 1055 | } |
| 1045 | 1056 | } |
| 1046 | 1057 | } |
| 1047 | 1058 | |
| 1048 | 1059 | if (ret) { |
| 1049 | − ret->ref = NULL; | |
| 1060 | + ret->ref = ty->ref; | |
| 1050 | 1061 | ret->t = ret_t; |
| 1051 | 1062 | } |
| 1052 | 1063 | |
| @@ -1057,12 +1068,13 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) · 4 unmodified lines | ||
| 1057 | 1068 | { |
| 1058 | 1069 | /* This definition must be synced with stdarg.h */ |
| 1059 | 1070 | enum __va_arg_type { |
| 1060 | − __va_gen_reg, __va_float_reg, __va_stack | |
| 1061 | − }; | |
| 1071 | + __va_gen_reg, __va_float_reg, __va_ld_reg, __va_stack | |
| 1072 | + }; | |
| 1062 | 1073 | int size, align, reg_count; |
| 1063 | 1074 | X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, ®_count); |
| 1064 | 1075 | switch (mode) { |
| 1065 | 1076 | default: return __va_stack; |
| 1077 | + case x86_64_mode_x87: return __va_ld_reg; | |
| 1066 | 1078 | case x86_64_mode_integer: return __va_gen_reg; |
| 1067 | 1079 | case x86_64_mode_sse: return __va_float_reg; |
| 1068 | 1080 | } |
| @@ -1387,7 +1399,7 @@ void gfunc_prolog(CType *func_type) · 318 unmodified lines | ||
| 1387 | 1399 | |
| 1388 | 1400 | sym = func_type->ref; |
| 1389 | 1401 | addr = PTR_SIZE * 2; |
| 1390 | − loc = 0; | |
| 1402 | + pop_stack = loc = 0; | |
| 1391 | 1403 | ind += FUNC_PROLOG_SIZE; |
| 1392 | 1404 | func_sub_sp_offset = ind; |
| 1393 | 1405 | func_ret_sub = 0; |
| @@ -1398,7 +1410,6 @@ void gfunc_prolog(CType *func_type) · 4 unmodified lines | ||
| 1398 | 1410 | /* frame pointer and return address */ |
| 1399 | 1411 | seen_stack_size = PTR_SIZE * 2; |
| 1400 | 1412 | /* count the number of seen parameters */ |
| 1401 | − sym = func_type->ref; | |
| 1402 | 1413 | while ((sym = sym->next) != NULL) { |
| 1403 | 1414 | type = &sym->type; |
| 1404 | 1415 | mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); |
| @@ -1439,19 +1450,19 @@ void gfunc_prolog(CType *func_type) · 34 unmodified lines | ||
| 1439 | 1450 | o(0xf845c7); |
| 1440 | 1451 | gen_le32(seen_stack_size); |
| 1441 | 1452 | |
| 1453 | + o(0xc084);/* test %al,%al */ | |
| 1454 | + o(0x74);/* je */ | |
| 1455 | + g(4*(8 - seen_sse_num) + 3); | |
| 1456 | + | |
| 1442 | 1457 | /* save all register passing arguments */ |
| 1443 | 1458 | for (i = 0; i < 8; i++) { |
| 1444 | 1459 | loc -= 16; |
| 1445 | − o(0xd60f66); /* movq */ | |
| 1460 | + o(0x290f);/* movaps %xmm1-7,-XXX(%rbp) */ | |
| 1446 | 1461 | gen_modrm(7 - i, VT_LOCAL, NULL, loc); |
| 1447 | − /* movq $0, loc+8(%rbp) */ | |
| 1448 | − o(0x85c748); | |
| 1449 | − gen_le32(loc + 8); | |
| 1450 | − gen_le32(0); | |
| 1451 | − } | |
| 1452 | − for (i = 0; i < REGN; i++) { | |
| 1453 | − push_arg_reg(REGN-1-i); | |
| 1454 | 1462 | } |
| 1463 | + for (i = 0; i < (REGN - seen_reg_num); i++) { | |
| 1464 | + push_arg_reg(REGN-1 - i); | |
| 1465 | + } | |
| 1455 | 1466 | } |
| 1456 | 1467 | |
| 1457 | 1468 | sym = func_type->ref; |