Restore ebx from *ebp because alloca might change esp. Also disable USE_EBX for upcoming release. Actually the benefit is less than one would expect, it appears that tcc can't do much with more than 3 registers except with extensive use of long longs where the disassembly looks much prettier (and shorter also).
Unified · Split
| @@ -79,7 +79,7 @@ enum { · 78 unmodified lines | ||
| 79 | 79 | #include "tcc.h" |
| 80 | 80 | |
| 81 | 81 | /* define to 1/0 to [not] have EBX as 4th register */ |
| 82 | −#define USE_EBX 1 | |
| 82 | +#define USE_EBX 0 | |
| 83 | 83 | |
| 84 | 84 | ST_DATA const int reg_classes[NB_REGS] = { |
| 85 | 85 | /* eax */ RC_INT | RC_EAX, |
| @@ -636,7 +636,15 @@ ST_FUNC void gfunc_epilog(void) · 550 unmodified lines | ||
| 636 | 636 | o(0x585a); /* restore returned value, if any */ |
| 637 | 637 | } |
| 638 | 638 | #endif |
| 639 | − o(0x5b * USE_EBX); /* pop ebx */ | |
| 639 | + | |
| 640 | + /* align local size to word & save local variables */ | |
| 641 | + v = (-loc + 3) & -4; | |
| 642 | + | |
| 643 | +#if USE_EBX | |
| 644 | + o(0x8b); | |
| 645 | + gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4)); | |
| 646 | +#endif | |
| 647 | + | |
| 640 | 648 | o(0xc9); /* leave */ |
| 641 | 649 | if (func_ret_sub == 0) { |
| 642 | 650 | o(0xc3); /* ret */ |
| @@ -645,9 +653,6 @@ ST_FUNC void gfunc_epilog(void) · 2 unmodified lines | ||
| 645 | 653 | g(func_ret_sub); |
| 646 | 654 | g(func_ret_sub >> 8); |
| 647 | 655 | } |
| 648 | − /* align local size to word & save local variables */ | |
| 649 | − | |
| 650 | − v = (-loc + 3) & -4; | |
| 651 | 656 | saved_ind = ind; |
| 652 | 657 | ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; |
| 653 | 658 | #ifdef TCC_TARGET_PE |
| @@ -5164,8 +5164,8 @@ static void expr_cond(void) · 5163 unmodified lines | ||
| 5164 | 5164 | #endif |
| 5165 | 5165 | } else |
| 5166 | 5166 | rc = RC_INT; |
| 5167 | − save_regs(1); | |
| 5168 | 5167 | gv(rc); |
| 5168 | + save_regs(1); | |
| 5169 | 5169 | if (g) |
| 5170 | 5170 | gv_dup(); |
| 5171 | 5171 | tt = gvtst(1, 0); |