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