This unifies VT_CMP with VT_JMP(i) by using mostly VT_CMP with both a positive and a negative jump target list. Such we can delay putting the non-inverted or inverted jump until we can see which one is nore suitable (in most cases). example: if (a && b || c && d) e = 0; before this patch: a: 8b 45 fc mov 0xfffffffc(%ebp),%eax d: 83 f8 00 cmp $0x0,%eax 10: 0f 84 11 00 00 00 je 27 <main+0x27> 16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 19: 83 f8 00 cmp $0x0,%eax 1c: 0f 84 05 00 00 00 je 27 <main+0x27> 22: e9 22 00 00 00 jmp 49 <main+0x49> 27: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 2a: 83 f8 00 cmp $0x0,%eax 2d: 0f 84 11 00 00 00 je 44 <main+0x44> 33: 8b 45 f0 mov 0xfffffff0(%ebp),%eax 36: 83 f8 00 cmp $0x0,%eax 39: 0f 84 05 00 00 00 je 44 <main+0x44> 3f: e9 05 00 00 00 jmp 49 <main+0x49> 44: e9 08 00 00 00 jmp 51 <main+0x51> 49: b8 00 00 00 00 mov $0x0,%eax 4e: 89 45 ec mov %eax,0xffffffec(%ebp) 51: ... with this patch: a: 8b 45 fc mov 0xfffffffc(%ebp),%eax d: 83 f8 00 cmp $0x0,%eax 10: 0f 84 0c 00 00 00 je 22 <main+0x22> 16: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 19: 83 f8 00 cmp $0x0,%eax 1c: 0f 85 18 00 00 00 jne 3a <main+0x3a> 22: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 25: 83 f8 00 cmp $0x0,%eax 28: 0f 84 14 00 00 00 je 42 <main+0x42> 2e: 8b 45 f0 mov 0xfffffff0(%ebp),%eax 31: 83 f8 00 cmp $0x0,%eax 34: 0f 84 08 00 00 00 je 42 <main+0x42> 3a: b8 00 00 00 00 mov $0x0,%eax 3f: 89 45 ec mov %eax,0xffffffec(%ebp) 42: ...
Unified · Split
| @@ -125,7 +125,7 @@ DEF-i386-win32 = -DTCC_TARGET_PE -DTCC_TARGET_I386 · 124 unmodified lines | |||
| 125 | DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64 | 125 | DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64 |
| 126 | DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64 | 126 | DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64 |
| 127 | DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT | 127 | DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT |
| 128 | DEF-arm64 = -DTCC_TARGET_ARM64 | 128 | DEF-arm64 = -DTCC_TARGET_ARM64 -Wno-format |
| 129 | DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs | 129 | DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs |
| 130 | DEF-arm-fpa = -DTCC_TARGET_ARM | 130 | DEF-arm-fpa = -DTCC_TARGET_ARM |
| 131 | DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12 | 131 | DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12 |
| @@ -1419,7 +1419,7 @@ ST_FUNC void gen_fill_nops(int bytes) · 1418 unmodified lines | |||
| 1419 | } | 1419 | } |
| 1420 | 1420 | ||
| 1421 | /* generate a jump to a label */ | 1421 | /* generate a jump to a label */ |
| 1422 | int gjmp(int t) | 1422 | ST_FUNC int gjmp(int t) |
| 1423 | { | 1423 | { |
| 1424 | int r; | 1424 | int r; |
| 1425 | if (nocode_wanted) | 1425 | if (nocode_wanted) |
| @@ -1430,51 +1430,37 @@ int gjmp(int t) · 4 unmodified lines | |||
| 1430 | } | 1430 | } |
| 1431 | 1431 | ||
| 1432 | /* generate a jump to a fixed address */ | 1432 | /* generate a jump to a fixed address */ |
| 1433 | void gjmp_addr(int a) | 1433 | ST_FUNC void gjmp_addr(int a) |
| 1434 | { | 1434 | { |
| 1435 | gjmp(a); | 1435 | gjmp(a); |
| 1436 | } | 1436 | } |
| 1437 | 1437 | ||
| 1438 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ | 1438 | ST_FUNC int gjmp_cond(int op, int t) |
| 1439 | int gtst(int inv, int t) | ||
| 1440 | { | 1439 | { |
| 1441 | int v, r; | 1440 | int r; |
| 1442 | uint32_t op; | 1441 | if (nocode_wanted) |
| 1443 | 1442 | return t; | |
| 1444 | v = vtop->r & VT_VALMASK; | ||
| 1445 | r=ind; | 1443 | r=ind; |
| 1444 | op=mapcc(op); | ||
| 1445 | op|=encbranch(r,t,1); | ||
| 1446 | o(op); | ||
| 1447 | return r; | ||
| 1448 | } | ||
| 1446 | 1449 | ||
| 1447 | if (nocode_wanted) { | 1450 | ST_FUNC int gjmp_append(int n, int t) |
| 1448 | ; | 1451 | { |
| 1449 | } else if (v == VT_CMP) { | 1452 | uint32_t *x; |
| 1450 | op=mapcc(inv?negcc(vtop->c.i):vtop->c.i); | 1453 | int p,lp; |
| 1451 | op|=encbranch(r,t,1); | 1454 | if(n) { |
| 1452 | o(op); | 1455 | p = n; |
| 1453 | t=r; | 1456 | do { |
| 1454 | } else if (v == VT_JMP || v == VT_JMPI) { | 1457 | p = decbranch(lp=p); |
| 1455 | if ((v & 1) == inv) { | 1458 | } while(p); |
| 1456 | if(!vtop->c.i) | 1459 | x = (uint32_t *)(cur_text_section->data + lp); |
| 1457 | vtop->c.i=t; | 1460 | *x &= 0xff000000; |
| 1458 | else { | 1461 | *x |= encbranch(lp,t,1); |
| 1459 | uint32_t *x; | 1462 | t = n; |
| 1460 | int p,lp; | ||
| 1461 | if(t) { | ||
| 1462 | p = vtop->c.i; | ||
| 1463 | do { | ||
| 1464 | p = decbranch(lp=p); | ||
| 1465 | } while(p); | ||
| 1466 | x = (uint32_t *)(cur_text_section->data + lp); | ||
| 1467 | *x &= 0xff000000; | ||
| 1468 | *x |= encbranch(lp,t,1); | ||
| 1469 | } | ||
| 1470 | t = vtop->c.i; | ||
| 1471 | } | ||
| 1472 | } else { | ||
| 1473 | t = gjmp(t); | ||
| 1474 | gsym(vtop->c.i); | ||
| 1475 | } | ||
| 1476 | } | 1463 | } |
| 1477 | vtop--; | ||
| 1478 | return t; | 1464 | return t; |
| 1479 | } | 1465 | } |
| 1480 | 1466 | ||
| @@ -1611,10 +1597,8 @@ void gen_opi(int op) · 130 unmodified lines | |||
| 1611 | o(opc|(r<<12)|fr); | 1597 | o(opc|(r<<12)|fr); |
| 1612 | done: | 1598 | done: |
| 1613 | vtop--; | 1599 | vtop--; |
| 1614 | if (op >= TOK_ULT && op <= TOK_GT) { | 1600 | if (op >= TOK_ULT && op <= TOK_GT) |
| 1615 | vtop->r = VT_CMP; | 1601 | vset_VT_CMP(op); |
| 1616 | vtop->c.i = op; | ||
| 1617 | } | ||
| 1618 | break; | 1602 | break; |
| 1619 | case 2: | 1603 | case 2: |
| 1620 | opc=0xE1A00000|(opc<<5); | 1604 | opc=0xE1A00000|(opc<<5); |
| @@ -1730,9 +1714,7 @@ void gen_opf(int op) · 109 unmodified lines | |||
| 1730 | case TOK_UGE: op=TOK_GE; break; | 1714 | case TOK_UGE: op=TOK_GE; break; |
| 1731 | case TOK_UGT: op=TOK_GT; break; | 1715 | case TOK_UGT: op=TOK_GT; break; |
| 1732 | } | 1716 | } |
| 1733 | 1717 | vset_VT_CMP(op); | |
| 1734 | vtop->r = VT_CMP; | ||
| 1735 | vtop->c.i = op; | ||
| 1736 | return; | 1718 | return; |
| 1737 | } | 1719 | } |
| 1738 | r=gv(RC_FLOAT); | 1720 | r=gv(RC_FLOAT); |
| @@ -1934,8 +1916,9 @@ void gen_opf(int op) · 195 unmodified lines | |||
| 1934 | } else { | 1916 | } else { |
| 1935 | r2=fpr(gv(RC_FLOAT)); | 1917 | r2=fpr(gv(RC_FLOAT)); |
| 1936 | } | 1918 | } |
| 1937 | vtop[-1].r = VT_CMP; | 1919 | --vtop; |
| 1938 | vtop[-1].c.i = op; | 1920 | vset_VT_CMP(op); |
| 1921 | ++vtop; | ||
| 1939 | } else { | 1922 | } else { |
| 1940 | tcc_error("unknown fp op %x!",op); | 1923 | tcc_error("unknown fp op %x!",op); |
| 1941 | return; | 1924 | return; |
| @@ -91,6 +91,9 @@ static uint32_t fltr(int r) · 90 unmodified lines | |||
| 91 | return r - TREG_F(0); | 91 | return r - TREG_F(0); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | #define dprintf(x) ((void)(tcc_state->verbose == 2 && printf x)) | ||
| 95 | //#define dprintf(x) | ||
| 96 | |||
| 94 | // Add an instruction to text section: | 97 | // Add an instruction to text section: |
| 95 | ST_FUNC void o(unsigned int c) | 98 | ST_FUNC void o(unsigned int c) |
| 96 | { | 99 | { |
| @@ -100,6 +103,7 @@ ST_FUNC void o(unsigned int c) · 3 unmodified lines | |||
| 100 | if (ind1 > cur_text_section->data_allocated) | 103 | if (ind1 > cur_text_section->data_allocated) |
| 101 | section_realloc(cur_text_section, ind1); | 104 | section_realloc(cur_text_section, ind1); |
| 102 | write32le(cur_text_section->data + ind, c); | 105 | write32le(cur_text_section->data + ind, c); |
| 106 | dprintf(("o %04x : %08x\n", ind, c)); //gr | ||
| 103 | ind = ind1; | 107 | ind = ind1; |
| 104 | } | 108 | } |
| 105 | 109 | ||
| @@ -232,6 +236,7 @@ ST_FUNC void gsym_addr(int t_, int a_) · 126 unmodified lines | |||
| 232 | tcc_error("branch out of range"); | 236 | tcc_error("branch out of range"); |
| 233 | write32le(ptr, (a - t == 4 ? 0xd503201f : // nop | 237 | write32le(ptr, (a - t == 4 ? 0xd503201f : // nop |
| 234 | 0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b | 238 | 0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b |
| 239 | dprintf((". gsym TARG=%04x ADDR=%04x\n", t, a)); //gr | ||
| 235 | t = next; | 240 | t = next; |
| 236 | } | 241 | } |
| 237 | } | 242 | } |
| @@ -440,6 +445,8 @@ static void arm64_sym(int r, Sym *sym, unsigned long addend) · 202 unmodified lines | |||
| 440 | } | 445 | } |
| 441 | } | 446 | } |
| 442 | 447 | ||
| 448 | static void arm64_load_cmp(int r, SValue *sv); | ||
| 449 | |||
| 443 | ST_FUNC void load(int r, SValue *sv) | 450 | ST_FUNC void load(int r, SValue *sv) |
| 444 | { | 451 | { |
| 445 | int svtt = sv->type.t; | 452 | int svtt = sv->type.t; |
| @@ -531,6 +538,11 @@ ST_FUNC void load(int r, SValue *sv) · 85 unmodified lines | |||
| 531 | return; | 538 | return; |
| 532 | } | 539 | } |
| 533 | 540 | ||
| 541 | if (svr == VT_CMP) { | ||
| 542 | arm64_load_cmp(r, sv); | ||
| 543 | return; | ||
| 544 | } | ||
| 545 | |||
| 534 | printf("load(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul); | 546 | printf("load(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul); |
| 535 | assert(0); | 547 | assert(0); |
| 536 | } | 548 | } |
| @@ -1284,6 +1296,7 @@ ST_FUNC void gen_fill_nops(int bytes) · 747 unmodified lines | |||
| 1284 | ST_FUNC int gjmp(int t) | 1296 | ST_FUNC int gjmp(int t) |
| 1285 | { | 1297 | { |
| 1286 | int r = ind; | 1298 | int r = ind; |
| 1299 | dprintf((". gjmp T=%04x\n", t)); //gr | ||
| 1287 | if (nocode_wanted) | 1300 | if (nocode_wanted) |
| 1288 | return t; | 1301 | return t; |
| 1289 | o(t); | 1302 | o(t); |
| @@ -1295,11 +1308,57 @@ ST_FUNC void gjmp_addr(int a) · 5 unmodified lines | |||
| 1295 | { | 1308 | { |
| 1296 | assert(a - ind + 0x8000000 < 0x10000000); | 1309 | assert(a - ind + 0x8000000 < 0x10000000); |
| 1297 | o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff)); | 1310 | o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff)); |
| 1311 | dprintf((". gjmp_addr T=%04x\n", a)); //gr | ||
| 1298 | } | 1312 | } |
| 1299 | 1313 | ||
| 1300 | ST_FUNC int gtst(int inv, int t) | 1314 | ST_FUNC int gjmp_append(int n, int t) |
| 1315 | { | ||
| 1316 | void *p; | ||
| 1317 | /* insert vtop->c jump list in t */ | ||
| 1318 | if (n) { | ||
| 1319 | uint32_t n1 = n, n2; | ||
| 1320 | while ((n2 = read32le(p = cur_text_section->data + n1))) | ||
| 1321 | n1 = n2; | ||
| 1322 | write32le(p, t); | ||
| 1323 | t = n; | ||
| 1324 | } | ||
| 1325 | return t; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | void arm64_vset_VT_CMP(int op) | ||
| 1329 | { | ||
| 1330 | if (op >= TOK_ULT && op <= TOK_GT) { | ||
| 1331 | vtop->cmp_r = vtop->r; | ||
| 1332 | vset_VT_CMP(0x80); | ||
| 1333 | dprintf((". set VT_CMP OP(%s) R=%x\n", get_tok_str(op, 0), vtop->cmp_r)); | ||
| 1334 | } | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static void arm64_gen_opil(int op, uint32_t l); | ||
| 1338 | |||
| 1339 | static void arm64_load_cmp(int r, SValue *sv) | ||
| 1340 | { | ||
| 1341 | sv->r = sv->cmp_r; | ||
| 1342 | dprintf((". load VT_CMP OP(%x), R=%x/%x\n", (int)sv->c.i, sv->r, r)); | ||
| 1343 | if (sv->c.i & 1) { | ||
| 1344 | vpushi(1); | ||
| 1345 | arm64_gen_opil('^', 0); | ||
| 1346 | } | ||
| 1347 | if (r != sv->r) { | ||
| 1348 | load(r, sv); | ||
| 1349 | sv->r = r; | ||
| 1350 | } | ||
| 1351 | dprintf((". load VT_CMP done\n")); //gr | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | ST_FUNC int gjmp_cond(int op, int t) | ||
| 1301 | { | 1355 | { |
| 1302 | int bt = vtop->type.t & VT_BTYPE; | 1356 | int bt = vtop->type.t & VT_BTYPE; |
| 1357 | |||
| 1358 | int inv = op & 1; | ||
| 1359 | vtop->r = vtop->cmp_r; | ||
| 1360 | dprintf((". gjmp_cond OP(%x) R=%x T=%04x\n", op, vtop->r, t)); //gr | ||
| 1361 | |||
| 1303 | if (bt == VT_LDOUBLE) { | 1362 | if (bt == VT_LDOUBLE) { |
| 1304 | uint32_t a, b, f = fltr(gv(RC_FLOAT)); | 1363 | uint32_t a, b, f = fltr(gv(RC_FLOAT)); |
| 1305 | a = get_reg(RC_INT); | 1364 | a = get_reg(RC_INT); |
| @@ -1324,7 +1383,6 @@ ST_FUNC int gtst(int inv, int t) · 18 unmodified lines | |||
| 1324 | uint32_t a = intr(gv(RC_INT)); | 1383 | uint32_t a = intr(gv(RC_INT)); |
| 1325 | o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+8 | 1384 | o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+8 |
| 1326 | } | 1385 | } |
| 1327 | --vtop; | ||
| 1328 | return gjmp(t); | 1386 | return gjmp(t); |
| 1329 | } | 1387 | } |
| 1330 | 1388 | ||
| @@ -1553,11 +1611,13 @@ static void arm64_gen_opil(int op, uint32_t l) · 222 unmodified lines | |||
| 1553 | ST_FUNC void gen_opi(int op) | 1611 | ST_FUNC void gen_opi(int op) |
| 1554 | { | 1612 | { |
| 1555 | arm64_gen_opil(op, 0); | 1613 | arm64_gen_opil(op, 0); |
| 1614 | arm64_vset_VT_CMP(op); | ||
| 1556 | } | 1615 | } |
| 1557 | 1616 | ||
| 1558 | ST_FUNC void gen_opl(int op) | 1617 | ST_FUNC void gen_opl(int op) |
| 1559 | { | 1618 | { |
| 1560 | arm64_gen_opil(op, 1); | 1619 | arm64_gen_opil(op, 1); |
| 1620 | arm64_vset_VT_CMP(op); | ||
| 1561 | } | 1621 | } |
| 1562 | 1622 | ||
| 1563 | ST_FUNC void gen_opf(int op) | 1623 | ST_FUNC void gen_opf(int op) |
| @@ -1657,6 +1717,7 @@ ST_FUNC void gen_opf(int op) · 93 unmodified lines | |||
| 1657 | default: | 1717 | default: |
| 1658 | assert(0); | 1718 | assert(0); |
| 1659 | } | 1719 | } |
| 1720 | arm64_vset_VT_CMP(op); | ||
| 1660 | } | 1721 | } |
| 1661 | 1722 | ||
| 1662 | // Generate sign extension from 32 to 64 bits: | 1723 | // Generate sign extension from 32 to 64 bits: |
| @@ -2072,15 +2072,13 @@ void gjmp_addr(int a) · 2071 unmodified lines | |||
| 2072 | } | 2072 | } |
| 2073 | 2073 | ||
| 2074 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ | 2074 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ |
| 2075 | int gtst(int inv, int t) | 2075 | ST_FUNC int gjmp_cond(int op, int t) |
| 2076 | { | 2076 | { |
| 2077 | int ind1, n; | 2077 | int ind1; |
| 2078 | int v, *p; | 2078 | int inv = op & 1; |
| 2079 | if (nocode_wanted) | ||
| 2080 | return t; | ||
| 2079 | 2081 | ||
| 2080 | v = vtop->r & VT_VALMASK; | ||
| 2081 | if (nocode_wanted) { | ||
| 2082 | ; | ||
| 2083 | } else if (v == VT_CMP) { | ||
| 2084 | /* fast case : can jump directly since flags are set */ | 2082 | /* fast case : can jump directly since flags are set */ |
| 2085 | // C67 uses B2 sort of as flags register | 2083 | // C67 uses B2 sort of as flags register |
| 2086 | ind1 = ind; | 2084 | ind1 = ind; |
| @@ -2098,16 +2096,18 @@ int gtst(int inv, int t) · 11 unmodified lines | |||
| 2098 | C67_NOP(5); | 2096 | C67_NOP(5); |
| 2099 | t = ind1; //return where we need to patch | 2097 | t = ind1; //return where we need to patch |
| 2100 | 2098 | ||
| 2101 | } else if (v == VT_JMP || v == VT_JMPI) { | 2099 | return t; |
| 2102 | /* && or || optimization */ | 2100 | } |
| 2103 | if ((v & 1) == inv) { | 2101 | |
| 2102 | ST_FUNC int gjmp_append(int n0, int t) | ||
| 2103 | { | ||
| 2104 | if (n0) { | ||
| 2105 | int n = n0, *p; | ||
| 2104 | /* insert vtop->c jump list in t */ | 2106 | /* insert vtop->c jump list in t */ |
| 2105 | 2107 | ||
| 2106 | // I guess the idea is to traverse to the | 2108 | // I guess the idea is to traverse to the |
| 2107 | // null at the end of the list and store t | 2109 | // null at the end of the list and store t |
| 2108 | // there | 2110 | // there |
| 2109 | |||
| 2110 | n = vtop->c.i; | ||
| 2111 | while (n != 0) { | 2111 | while (n != 0) { |
| 2112 | p = (int *) (cur_text_section->data + n); | 2112 | p = (int *) (cur_text_section->data + n); |
| 2113 | 2113 | ||
| @@ -2117,14 +2117,8 @@ int gtst(int inv, int t) · 3 unmodified lines | |||
| 2117 | } | 2117 | } |
| 2118 | *p |= (t & 0xffff) << 7; | 2118 | *p |= (t & 0xffff) << 7; |
| 2119 | *(p + 1) |= ((t >> 16) & 0xffff) << 7; | 2119 | *(p + 1) |= ((t >> 16) & 0xffff) << 7; |
| 2120 | t = vtop->c.i; | 2120 | t = n0; |
| 2121 | |||
| 2122 | } else { | ||
| 2123 | t = gjmp(t); | ||
| 2124 | gsym(vtop->c.i); | ||
| 2125 | } | ||
| 2126 | } | 2121 | } |
| 2127 | vtop--; | ||
| 2128 | return t; | 2122 | return t; |
| 2129 | } | 2123 | } |
| 2130 | 2124 | ||
| @@ -2200,10 +2194,8 @@ void gen_opi(int op) · 69 unmodified lines | |||
| 2200 | ALWAYS_ASSERT(FALSE); | 2194 | ALWAYS_ASSERT(FALSE); |
| 2201 | 2195 | ||
| 2202 | vtop--; | 2196 | vtop--; |
| 2203 | if (op >= TOK_ULT && op <= TOK_GT) { | 2197 | if (op >= TOK_ULT && op <= TOK_GT) |
| 2204 | vtop->r = VT_CMP; | 2198 | vset_VT_CMP(0x80); |
| 2205 | vtop->c.i = op; | ||
| 2206 | } | ||
| 2207 | break; | 2199 | break; |
| 2208 | case '-': | 2200 | case '-': |
| 2209 | case TOK_SUBC1: /* sub with carry generation */ | 2201 | case TOK_SUBC1: /* sub with carry generation */ |
| @@ -2359,7 +2351,7 @@ void gen_opf(int op) · 149 unmodified lines | |||
| 2359 | } else { | 2351 | } else { |
| 2360 | ALWAYS_ASSERT(FALSE); | 2352 | ALWAYS_ASSERT(FALSE); |
| 2361 | } | 2353 | } |
| 2362 | vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2 | 2354 | vset_VT_CMP(0x80); |
| 2363 | } else { | 2355 | } else { |
| 2364 | if (op == '+') { | 2356 | if (op == '+') { |
| 2365 | if ((ft & VT_BTYPE) == VT_DOUBLE) { | 2357 | if ((ft & VT_BTYPE) == VT_DOUBLE) { |
| @@ -261,10 +261,10 @@ ST_FUNC void load(int r, SValue *sv) · 260 unmodified lines | |||
| 261 | o(0xe8 + r); /* mov %ebp, r */ | 261 | o(0xe8 + r); /* mov %ebp, r */ |
| 262 | } | 262 | } |
| 263 | } else if (v == VT_CMP) { | 263 | } else if (v == VT_CMP) { |
| 264 | oad(0xb8 + r, 0); /* mov $0, r */ | ||
| 265 | o(0x0f); /* setxx %br */ | 264 | o(0x0f); /* setxx %br */ |
| 266 | o(fc); | 265 | o(fc); |
| 267 | o(0xc0 + r); | 266 | o(0xc0 + r); |
| 267 | o(0xc0b60f + r * 0x90000); /* movzbl %al, %eax */ | ||
| 268 | } else if (v == VT_JMP || v == VT_JMPI) { | 268 | } else if (v == VT_JMP || v == VT_JMPI) { |
| 269 | t = v & 1; | 269 | t = v & 1; |
| 270 | oad(0xb8 + r, t); /* mov $1, r */ | 270 | oad(0xb8 + r, t); /* mov $1, r */ |
| @@ -692,63 +692,39 @@ ST_FUNC void gjmp_addr(int a) · 421 unmodified lines | |||
| 692 | } | 692 | } |
| 693 | } | 693 | } |
| 694 | 694 | ||
| 695 | ST_FUNC void gtst_addr(int inv, int a) | 695 | #if 0 |
| 696 | /* generate a jump to a fixed address */ | ||
| 697 | ST_FUNC void gjmp_cond_addr(int a, int op) | ||
| 696 | { | 698 | { |
| 697 | int v = vtop->r & VT_VALMASK; | 699 | int r = a - ind - 2; |
| 698 | if (v == VT_CMP) { | 700 | if (r == (char)r) |
| 699 | inv ^= (vtop--)->c.i; | 701 | g(op - 32), g(r); |
| 700 | a -= ind + 2; | 702 | else |
| 701 | if (a == (char)a) { | 703 | g(0x0f), gjmp2(op - 16, r - 4); |
| 702 | g(inv - 32); | ||
| 703 | g(a); | ||
| 704 | } else { | ||
| 705 | g(0x0f); | ||
| 706 | oad(inv - 16, a - 4); | ||
| 707 | } | ||
| 708 | } else if ((v & ~1) == VT_JMP) { | ||
| 709 | if ((v & 1) != inv) { | ||
| 710 | gjmp_addr(a); | ||
| 711 | gsym(vtop->c.i); | ||
| 712 | } else { | ||
| 713 | gsym(vtop->c.i); | ||
| 714 | o(0x05eb); | ||
| 715 | gjmp_addr(a); | ||
| 716 | } | ||
| 717 | vtop--; | ||
| 718 | } | ||
| 719 | } | 704 | } |
| 705 | #endif | ||
| 720 | 706 | ||
| 721 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ | 707 | ST_FUNC int gjmp_append(int n, int t) |
| 722 | ST_FUNC int gtst(int inv, int t) | ||
| 723 | { | 708 | { |
| 724 | int v = vtop->r & VT_VALMASK; | 709 | void *p; |
| 725 | if (nocode_wanted) { | 710 | /* insert vtop->c jump list in t */ |
| 726 | ; | 711 | if (n) { |
| 727 | } else if (v == VT_CMP) { | 712 | uint32_t n1 = n, n2; |
| 728 | /* fast case : can jump directly since flags are set */ | 713 | while ((n2 = read32le(p = cur_text_section->data + n1))) |
| 729 | g(0x0f); | 714 | n1 = n2; |
| 730 | t = gjmp2((vtop->c.i - 16) ^ inv, t); | 715 | write32le(p, t); |
| 731 | } else if (v == VT_JMP || v == VT_JMPI) { | 716 | t = n; |
| 732 | /* && or || optimization */ | ||
| 733 | if ((v & 1) == inv) { | ||
| 734 | /* insert vtop->c jump list in t */ | ||
| 735 | uint32_t n1, n = vtop->c.i; | ||
| 736 | if (n) { | ||
| 737 | while ((n1 = read32le(cur_text_section->data + n))) | ||
| 738 | n = n1; | ||
| 739 | write32le(cur_text_section->data + n, t); | ||
| 740 | t = vtop->c.i; | ||
| 741 | } | ||
| 742 | } else { | ||
| 743 | t = gjmp(t); | ||
| 744 | gsym(vtop->c.i); | ||
| 745 | } | ||
| 746 | } | 717 | } |
| 747 | vtop--; | ||
| 748 | return t; | 718 | return t; |
| 749 | } | 719 | } |
| 750 | 720 | ||
| 751 | /* generate an integer binary operation */ | 721 | ST_FUNC int gjmp_cond(int op, int t) |
| 722 | { | ||
| 723 | g(0x0f); | ||
| 724 | t = gjmp2(op - 16, t); | ||
| 725 | return t; | ||
| 726 | } | ||
| 727 | |||
| 752 | ST_FUNC void gen_opi(int op) | 728 | ST_FUNC void gen_opi(int op) |
| 753 | { | 729 | { |
| 754 | int r, fr, opc, c; | 730 | int r, fr, opc, c; |
| @@ -766,10 +742,9 @@ ST_FUNC void gen_opi(int op) · 11 unmodified lines | |||
| 766 | c = vtop->c.i; | 742 | c = vtop->c.i; |
| 767 | if (c == (char)c) { | 743 | if (c == (char)c) { |
| 768 | /* generate inc and dec for smaller code */ | 744 | /* generate inc and dec for smaller code */ |
| 769 | if (c==1 && opc==0 && op != TOK_ADDC1) { | 745 | if ((c == 1 || c == -1) && (op == '+' || op == '-')) { |
| 770 | o (0x40 | r); // inc | 746 | opc = (c == 1) ^ (op == '+'); |
| 771 | } else if (c==1 && opc==5 && op != TOK_SUBC1) { | 747 | o (0x40 | (opc << 3) | r); // inc,dec |
| 772 | o (0x48 | r); // dec | ||
| 773 | } else { | 748 | } else { |
| 774 | o(0x83); | 749 | o(0x83); |
| 775 | o(0xc0 | (opc << 3) | r); | 750 | o(0xc0 | (opc << 3) | r); |
| @@ -787,10 +762,8 @@ ST_FUNC void gen_opi(int op) · 11 unmodified lines | |||
| 787 | o(0xc0 + r + fr * 8); | 762 | o(0xc0 + r + fr * 8); |
| 788 | } | 763 | } |
| 789 | vtop--; | 764 | vtop--; |
| 790 | if (op >= TOK_ULT && op <= TOK_GT) { | 765 | if (op >= TOK_ULT && op <= TOK_GT) |
| 791 | vtop->r = VT_CMP; | 766 | vset_VT_CMP(op); |
| 792 | vtop->c.i = op; | ||
| 793 | } | ||
| 794 | break; | 767 | break; |
| 795 | case '-': | 768 | case '-': |
| 796 | case TOK_SUBC1: /* sub with carry generation */ | 769 | case TOK_SUBC1: /* sub with carry generation */ |
| @@ -948,8 +921,7 @@ ST_FUNC void gen_opf(int op) · 151 unmodified lines | |||
| 948 | op = TOK_EQ; | 921 | op = TOK_EQ; |
| 949 | } | 922 | } |
| 950 | vtop--; | 923 | vtop--; |
| 951 | vtop->r = VT_CMP; | 924 | vset_VT_CMP(op); |
| 952 | vtop->c.i = op; | ||
| 953 | } else { | 925 | } else { |
| 954 | /* no memory reference possible for long double operations */ | 926 | /* no memory reference possible for long double operations */ |
| 955 | if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { | 927 | if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { |
| @@ -430,9 +430,15 @@ typedef struct SValue { · 429 unmodified lines | |||
| 430 | unsigned short r; /* register + flags */ | 430 | unsigned short r; /* register + flags */ |
| 431 | unsigned short r2; /* second register, used for 'long long' | 431 | unsigned short r2; /* second register, used for 'long long' |
| 432 | type. If not used, set to VT_CONST */ | 432 | type. If not used, set to VT_CONST */ |
| 433 | CValue c; /* constant, if VT_CONST */ | 433 | union { |
| 434 | struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if | 434 | struct { int jtrue, jfalse; }; /* forward jmps */ |
| 435 | result of unary() for an identifier. */ | 435 | CValue c; /* constant, if VT_CONST */ |
| 436 | }; | ||
| 437 | union { | ||
| 438 | struct { unsigned short cmp_op, cmp_r; }; /* VT_CMP operation */ | ||
| 439 | struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if */ | ||
| 440 | }; /* result of unary() for an identifier. */ | ||
| 441 | |||
| 436 | } SValue; | 442 | } SValue; |
| 437 | 443 | ||
| 438 | /* symbol attributes */ | 444 | /* symbol attributes */ |
| @@ -1322,6 +1328,7 @@ ST_FUNC ElfSym *elfsym(Sym *); · 883 unmodified lines | |||
| 1322 | ST_FUNC void update_storage(Sym *sym); | 1328 | ST_FUNC void update_storage(Sym *sym); |
| 1323 | ST_FUNC Sym *external_global_sym(int v, CType *type); | 1329 | ST_FUNC Sym *external_global_sym(int v, CType *type); |
| 1324 | ST_FUNC void vset(CType *type, int r, int v); | 1330 | ST_FUNC void vset(CType *type, int r, int v); |
| 1331 | ST_FUNC void vset_VT_CMP(int op); | ||
| 1325 | ST_FUNC void vswap(void); | 1332 | ST_FUNC void vswap(void); |
| 1326 | ST_FUNC void vpush_global_sym(CType *type, int v); | 1333 | ST_FUNC void vpush_global_sym(CType *type, int v); |
| 1327 | ST_FUNC void vrote(SValue *e, int n); | 1334 | ST_FUNC void vrote(SValue *e, int n); |
| @@ -1490,12 +1497,8 @@ ST_FUNC void gfunc_epilog(void); · 162 unmodified lines | |||
| 1490 | ST_FUNC void gen_fill_nops(int); | 1497 | ST_FUNC void gen_fill_nops(int); |
| 1491 | ST_FUNC int gjmp(int t); | 1498 | ST_FUNC int gjmp(int t); |
| 1492 | ST_FUNC void gjmp_addr(int a); | 1499 | ST_FUNC void gjmp_addr(int a); |
| 1493 | ST_FUNC int gtst(int inv, int t); | 1500 | ST_FUNC int gjmp_cond(int op, int t); |
| 1494 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | 1501 | ST_FUNC int gjmp_append(int n, int t); |
| 1495 | ST_FUNC void gtst_addr(int inv, int a); | ||
| 1496 | #else | ||
| 1497 | #define gtst_addr(inv, a) gsym_addr(gtst(inv, 0), a) | ||
| 1498 | #endif | ||
| 1499 | ST_FUNC void gen_opi(int op); | 1502 | ST_FUNC void gen_opi(int op); |
| 1500 | ST_FUNC void gen_opf(int op); | 1503 | ST_FUNC void gen_opf(int op); |
| 1501 | ST_FUNC void gen_cvt_ftoi(int t); | 1504 | ST_FUNC void gen_cvt_ftoi(int t); |
| @@ -681,13 +681,8 @@ ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep) · 680 unmodified lines | |||
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | /* ------------------------------------------------------------------------- */ | 683 | /* ------------------------------------------------------------------------- */ |
| 684 | 684 | static void vcheck_cmp(void) | |
| 685 | static void vsetc(CType *type, int r, CValue *vc) | ||
| 686 | { | 685 | { |
| 687 | int v; | ||
| 688 | |||
| 689 | if (vtop >= vstack + (VSTACK_SIZE - 1)) | ||
| 690 | tcc_error("memory full (vstack)"); | ||
| 691 | /* cannot let cpu flags if other instruction are generated. Also | 686 | /* cannot let cpu flags if other instruction are generated. Also |
| 692 | avoid leaving VT_JMP anywhere except on the top of the stack | 687 | avoid leaving VT_JMP anywhere except on the top of the stack |
| 693 | because it would complicate the code generator. | 688 | because it would complicate the code generator. |
| @@ -698,15 +693,17 @@ static void vsetc(CType *type, int r, CValue *vc) · 4 unmodified lines | |||
| 698 | as their value might still be used for real. All values | 693 | as their value might still be used for real. All values |
| 699 | we push under nocode_wanted will eventually be popped | 694 | we push under nocode_wanted will eventually be popped |
| 700 | again, so that the VT_CMP/VT_JMP value will be in vtop | 695 | again, so that the VT_CMP/VT_JMP value will be in vtop |
| 701 | when code is unsuppressed again. | 696 | when code is unsuppressed again. */ |
| 702 | 697 | ||
| 703 | Same logic below in vswap(); */ | 698 | if (vtop->r == VT_CMP && !nocode_wanted) |
| 704 | if (vtop >= vstack && !nocode_wanted) { | 699 | gv(RC_INT); |
| 705 | v = vtop->r & VT_VALMASK; | 700 | } |
| 706 | if (v == VT_CMP || (v & ~1) == VT_JMP) | ||
| 707 | gv(RC_INT); | ||
| 708 | } | ||
| 709 | 701 | ||
| 702 | static void vsetc(CType *type, int r, CValue *vc) | ||
| 703 | { | ||
| 704 | if (vtop >= vstack + (VSTACK_SIZE - 1)) | ||
| 705 | tcc_error("memory full (vstack)"); | ||
| 706 | vcheck_cmp(); | ||
| 710 | vtop++; | 707 | vtop++; |
| 711 | vtop->type = *type; | 708 | vtop->type = *type; |
| 712 | vtop->r = r; | 709 | vtop->r = r; |
| @@ -718,12 +715,8 @@ static void vsetc(CType *type, int r, CValue *vc) · 5 unmodified lines | |||
| 718 | ST_FUNC void vswap(void) | 715 | ST_FUNC void vswap(void) |
| 719 | { | 716 | { |
| 720 | SValue tmp; | 717 | SValue tmp; |
| 721 | /* cannot vswap cpu flags. See comment at vsetc() above */ | 718 | |
| 722 | if (vtop >= vstack && !nocode_wanted) { | 719 | vcheck_cmp(); |
| 723 | int v = vtop->r & VT_VALMASK; | ||
| 724 | if (v == VT_CMP || (v & ~1) == VT_JMP) | ||
| 725 | gv(RC_INT); | ||
| 726 | } | ||
| 727 | tmp = vtop[0]; | 720 | tmp = vtop[0]; |
| 728 | vtop[0] = vtop[-1]; | 721 | vtop[0] = vtop[-1]; |
| 729 | vtop[-1] = tmp; | 722 | vtop[-1] = tmp; |
| @@ -740,9 +733,10 @@ ST_FUNC void vpop(void) · 10 unmodified lines | |||
| 740 | o(0xd8dd); /* fstp %st(0) */ | 733 | o(0xd8dd); /* fstp %st(0) */ |
| 741 | } else | 734 | } else |
| 742 | #endif | 735 | #endif |
| 743 | if (v == VT_JMP || v == VT_JMPI) { | 736 | if (v == VT_CMP) { |
| 744 | /* need to put correct jump if && or || without test */ | 737 | /* need to put correct jump if && or || without test */ |
| 745 | gsym(vtop->c.i); | 738 | gsym(vtop->jtrue); |
| 739 | gsym(vtop->jfalse); | ||
| 746 | } | 740 | } |
| 747 | vtop--; | 741 | vtop--; |
| 748 | } | 742 | } |
| @@ -823,6 +817,7 @@ ST_FUNC void vrotb(int n) · 74 unmodified lines | |||
| 823 | int i; | 817 | int i; |
| 824 | SValue tmp; | 818 | SValue tmp; |
| 825 | 819 | ||
| 820 | vcheck_cmp(); | ||
| 826 | tmp = vtop[-n + 1]; | 821 | tmp = vtop[-n + 1]; |
| 827 | for(i=-n+1;i!=0;i++) | 822 | for(i=-n+1;i!=0;i++) |
| 828 | vtop[i] = vtop[i+1]; | 823 | vtop[i] = vtop[i+1]; |
| @@ -837,6 +832,7 @@ ST_FUNC void vrote(SValue *e, int n) · 8 unmodified lines | |||
| 837 | int i; | 832 | int i; |
| 838 | SValue tmp; | 833 | SValue tmp; |
| 839 | 834 | ||
| 835 | vcheck_cmp(); | ||
| 840 | tmp = *e; | 836 | tmp = *e; |
| 841 | for(i = 0;i < n - 1; i++) | 837 | for(i = 0;i < n - 1; i++) |
| 842 | e[-i] = e[-i - 1]; | 838 | e[-i] = e[-i - 1]; |
| @@ -851,6 +847,75 @@ ST_FUNC void vrott(int n) · 8 unmodified lines | |||
| 851 | vrote(vtop, n); | 847 | vrote(vtop, n); |
| 852 | } | 848 | } |
| 853 | 849 | ||
| 850 | /* ------------------------------------------------------------------------- */ | ||
| 851 | /* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */ | ||
| 852 | |||
| 853 | /* called from generators to set the result from relational ops */ | ||
| 854 | ST_FUNC void vset_VT_CMP(int op) | ||
| 855 | { | ||
| 856 | vtop->r = VT_CMP; | ||
| 857 | vtop->cmp_op = op; | ||
| 858 | vtop->jfalse = 0; | ||
| 859 | vtop->jtrue = 0; | ||
| 860 | } | ||
| 861 | |||
| 862 | /* called once before asking generators to load VT_CMP to a register */ | ||
| 863 | static void vset_VT_JMP(void) | ||
| 864 | { | ||
| 865 | int op = vtop->cmp_op; | ||
| 866 | if (vtop->jtrue || vtop->jfalse) { | ||
| 867 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ | ||
| 868 | int inv = op & (op < 2); /* small optimization */ | ||
| 869 | vseti(VT_JMP+inv, gvtst(inv, 0)); | ||
| 870 | } else { | ||
| 871 | /* otherwise convert flags (rsp. 0/1) to register */ | ||
| 872 | vtop->c.i = op; | ||
| 873 | if (op < 2) /* doesn't seem to happen */ | ||
| 874 | vtop->r = VT_CONST; | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | /* Set CPU Flags, doesn't yet jump */ | ||
| 879 | static void gvtst_set(int inv, int t) | ||
| 880 | { | ||
| 881 | int *p; | ||
| 882 | if (vtop->r != VT_CMP) { | ||
| 883 | vpushi(0); | ||
| 884 | gen_op(TOK_NE); | ||
| 885 | if (vtop->r != VT_CMP) /* must be VT_CONST then */ | ||
| 886 | vset_VT_CMP(vtop->c.i != 0); | ||
| 887 | } | ||
| 888 | p = inv ? &vtop->jfalse : &vtop->jtrue; | ||
| 889 | *p = gjmp_append(*p, t); | ||
| 890 | } | ||
| 891 | |||
| 892 | /* Generate value test | ||
| 893 | * | ||
| 894 | * Generate a test for any value (jump, comparison and integers) */ | ||
| 895 | static int gvtst(int inv, int t) | ||
| 896 | { | ||
| 897 | int op, u, x; | ||
| 898 | |||
| 899 | gvtst_set(inv, t); | ||
| 900 | |||
| 901 | t = vtop->jtrue, u = vtop->jfalse; | ||
| 902 | if (inv) | ||
| 903 | x = u, u = t, t = x; | ||
| 904 | op = vtop->cmp_op; | ||
| 905 | |||
| 906 | /* jump to the wanted target */ | ||
| 907 | if (op > 1) | ||
| 908 | t = gjmp_cond(op ^ inv, t); | ||
| 909 | else if (op != inv) | ||
| 910 | t = gjmp(t); | ||
| 911 | /* resolve complementary jumps to here */ | ||
| 912 | gsym(u); | ||
| 913 | |||
| 914 | vtop--; | ||
| 915 | return t; | ||
| 916 | } | ||
| 917 | |||
| 918 | /* ------------------------------------------------------------------------- */ | ||
| 854 | /* push a symbol value of TYPE */ | 919 | /* push a symbol value of TYPE */ |
| 855 | static inline void vpushsym(CType *type, Sym *sym) | 920 | static inline void vpushsym(CType *type, Sym *sym) |
| 856 | { | 921 | { |
| @@ -1591,6 +1656,8 @@ ST_FUNC int gv(int rc) · 734 unmodified lines | |||
| 1591 | /* restore wanted type */ | 1656 | /* restore wanted type */ |
| 1592 | vtop->type.t = t1; | 1657 | vtop->type.t = t1; |
| 1593 | } else { | 1658 | } else { |
| 1659 | if (vtop->r == VT_CMP) | ||
| 1660 | vset_VT_JMP(); | ||
| 1594 | /* one register type load */ | 1661 | /* one register type load */ |
| 1595 | load(r, vtop); | 1662 | load(r, vtop); |
| 1596 | } | 1663 | } |
| @@ -1608,13 +1675,10 @@ ST_FUNC int gv(int rc) · 11 unmodified lines | |||
| 1608 | /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ | 1675 | /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ |
| 1609 | ST_FUNC void gv2(int rc1, int rc2) | 1676 | ST_FUNC void gv2(int rc1, int rc2) |
| 1610 | { | 1677 | { |
| 1611 | int v; | ||
| 1612 | |||
| 1613 | /* generate more generic register first. But VT_JMP or VT_CMP | 1678 | /* generate more generic register first. But VT_JMP or VT_CMP |
| 1614 | values must be generated first in all cases to avoid possible | 1679 | values must be generated first in all cases to avoid possible |
| 1615 | reload errors */ | 1680 | reload errors */ |
| 1616 | v = vtop[0].r & VT_VALMASK; | 1681 | if (vtop->r != VT_CMP && rc1 <= rc2) { |
| 1617 | if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) { | ||
| 1618 | vswap(); | 1682 | vswap(); |
| 1619 | gv(rc1); | 1683 | gv(rc1); |
| 1620 | vswap(); | 1684 | vswap(); |
| @@ -1749,26 +1813,6 @@ static void gv_dup(void) · 128 unmodified lines | |||
| 1749 | } | 1813 | } |
| 1750 | } | 1814 | } |
| 1751 | 1815 | ||
| 1752 | /* Generate value test | ||
| 1753 | * | ||
| 1754 | * Generate a test for any value (jump, comparison and integers) */ | ||
| 1755 | ST_FUNC int gvtst(int inv, int t) | ||
| 1756 | { | ||
| 1757 | int v = vtop->r & VT_VALMASK; | ||
| 1758 | if (v != VT_CMP && v != VT_JMP && v != VT_JMPI) { | ||
| 1759 | vpushi(0); | ||
| 1760 | gen_op(TOK_NE); | ||
| 1761 | } | ||
| 1762 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { | ||
| 1763 | /* constant jmp optimization */ | ||
| 1764 | if ((vtop->c.i != 0) != inv) | ||
| 1765 | t = gjmp(t); | ||
| 1766 | vtop--; | ||
| 1767 | return t; | ||
| 1768 | } | ||
| 1769 | return gtst(inv, t); | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | #if PTR_SIZE == 4 | 1816 | #if PTR_SIZE == 4 |
| 1773 | /* generate CPU independent (unsigned) long long operations */ | 1817 | /* generate CPU independent (unsigned) long long operations */ |
| 1774 | static void gen_opl(int op) | 1818 | static void gen_opl(int op) |
| @@ -1974,8 +2018,8 @@ static void gen_opl(int op) · 199 unmodified lines | |||
| 1974 | a = gvtst(1, 0); | 2018 | a = gvtst(1, 0); |
| 1975 | if (op != TOK_EQ) { | 2019 | if (op != TOK_EQ) { |
| 1976 | /* generate non equal test */ | 2020 | /* generate non equal test */ |
| 1977 | vpushi(TOK_NE); | 2021 | vpushi(0); |
| 1978 | vtop->r = VT_CMP; | 2022 | vset_VT_CMP(TOK_NE); |
| 1979 | b = gvtst(0, 0); | 2023 | b = gvtst(0, 0); |
| 1980 | } | 2024 | } |
| 1981 | } | 2025 | } |
| @@ -1990,9 +2034,12 @@ static void gen_opl(int op) · 8 unmodified lines | |||
| 1990 | else if (op1 == TOK_GE) | 2034 | else if (op1 == TOK_GE) |
| 1991 | op1 = TOK_UGE; | 2035 | op1 = TOK_UGE; |
| 1992 | gen_op(op1); | 2036 | gen_op(op1); |
| 1993 | a = gvtst(1, a); | 2037 | #if 0//def TCC_TARGET_I386 |
| 1994 | gsym(b); | 2038 | if (op == TOK_NE) { gsym(b); break; } |
| 1995 | vseti(VT_JMPI, a); | 2039 | if (op == TOK_EQ) { gsym(a); break; } |
| 2040 | #endif | ||
| 2041 | gvtst_set(1, a); | ||
| 2042 | gvtst_set(0, b); | ||
| 1996 | break; | 2043 | break; |
| 1997 | } | 2044 | } |
| 1998 | } | 2045 | } |
| @@ -5001,11 +5048,12 @@ ST_FUNC void unary(void) · 3002 unmodified lines | |||
| 5001 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { | 5048 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 5002 | gen_cast_s(VT_BOOL); | 5049 | gen_cast_s(VT_BOOL); |
| 5003 | vtop->c.i = !vtop->c.i; | 5050 | vtop->c.i = !vtop->c.i; |
| 5004 | } else if ((vtop->r & VT_VALMASK) == VT_CMP) | 5051 | } else if (vtop->r == VT_CMP) { |
| 5005 | vtop->c.i ^= 1; | 5052 | vtop->cmp_op ^= 1; |
| 5006 | else { | 5053 | n = vtop->jfalse, vtop->jfalse = vtop->jtrue, vtop->jtrue = n; |
| 5007 | save_regs(1); | 5054 | } else { |
| 5008 | vseti(VT_JMP, gvtst(1, 0)); | 5055 | vpushi(0); |
| 5056 | gen_op(TOK_EQ); | ||
| 5009 | } | 5057 | } |
| 5010 | break; | 5058 | break; |
| 5011 | case '~': | 5059 | case '~': |
| @@ -5035,7 +5083,9 @@ ST_FUNC void unary(void) · 23 unmodified lines | |||
| 5035 | next(); | 5083 | next(); |
| 5036 | in_sizeof++; | 5084 | in_sizeof++; |
| 5037 | expr_type(&type, unary); /* Perform a in_sizeof = 0; */ | 5085 | expr_type(&type, unary); /* Perform a in_sizeof = 0; */ |
| 5038 | s = vtop[1].sym; /* hack: accessing previous vtop */ | 5086 | s = NULL; |
| 5087 | if (vtop[1].r & VT_SYM) | ||
| 5088 | s = vtop[1].sym; /* hack: accessing previous vtop */ | ||
| 5039 | size = type_size(&type, &align); | 5089 | size = type_size(&type, &align); |
| 5040 | if (s && s->a.aligned) | 5090 | if (s && s->a.aligned) |
| 5041 | align = 1 << (s->a.aligned - 1); | 5091 | align = 1 << (s->a.aligned - 1); |
| @@ -5653,7 +5703,7 @@ static void expr_landor(void(*e_fn)(void), int e_op, int i) · 611 unmodified lines | |||
| 5653 | gsym(t); | 5703 | gsym(t); |
| 5654 | nocode_wanted -= f; | 5704 | nocode_wanted -= f; |
| 5655 | } else { | 5705 | } else { |
| 5656 | vseti(VT_JMP + i, gvtst(i, t)); | 5706 | gvtst_set(i, t); |
| 5657 | } | 5707 | } |
| 5658 | break; | 5708 | break; |
| 5659 | } | 5709 | } |
| @@ -5696,6 +5746,16 @@ static int condition_3way(void) · 36 unmodified lines | |||
| 5696 | return c; | 5746 | return c; |
| 5697 | } | 5747 | } |
| 5698 | 5748 | ||
| 5749 | static int is_cond_bool(SValue *sv) | ||
| 5750 | { | ||
| 5751 | if ((sv->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST | ||
| 5752 | && (sv->type.t & VT_BTYPE) == VT_INT) | ||
| 5753 | return (unsigned)sv->c.i < 2; | ||
| 5754 | if (sv->r == VT_CMP) | ||
| 5755 | return 1; | ||
| 5756 | return 0; | ||
| 5757 | } | ||
| 5758 | |||
| 5699 | static void expr_cond(void) | 5759 | static void expr_cond(void) |
| 5700 | { | 5760 | { |
| 5701 | int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g; | 5761 | int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g; |
| @@ -5741,6 +5801,12 @@ static void expr_cond(void) · 39 unmodified lines | |||
| 5741 | if (!g) | 5801 | if (!g) |
| 5742 | gexpr(); | 5802 | gexpr(); |
| 5743 | 5803 | ||
| 5804 | if (c < 0 && vtop->r == VT_CMP) { | ||
| 5805 | t1 = gvtst(0, 0); | ||
| 5806 | vpushi(0); | ||
| 5807 | gvtst_set(0, t1); | ||
| 5808 | } | ||
| 5809 | |||
| 5744 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) | 5810 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) |
| 5745 | mk_pointer(&vtop->type); | 5811 | mk_pointer(&vtop->type); |
| 5746 | type1 = vtop->type; | 5812 | type1 = vtop->type; |
| @@ -5761,6 +5827,22 @@ static void expr_cond(void) · 14 unmodified lines | |||
| 5761 | skip(':'); | 5827 | skip(':'); |
| 5762 | expr_cond(); | 5828 | expr_cond(); |
| 5763 | 5829 | ||
| 5830 | if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) { | ||
| 5831 | if (sv.r == VT_CMP) { | ||
| 5832 | t1 = sv.jtrue; | ||
| 5833 | t2 = u; | ||
| 5834 | } else { | ||
| 5835 | t1 = gvtst(0, 0); | ||
| 5836 | t2 = gjmp(0); | ||
| 5837 | gsym(u); | ||
| 5838 | vpushv(&sv); | ||
| 5839 | } | ||
| 5840 | gvtst_set(0, t1); | ||
| 5841 | gvtst_set(1, t2); | ||
| 5842 | nocode_wanted = ncw_prev; | ||
| 5843 | // tcc_warning("two conditions expr_cond"); | ||
| 5844 | return; | ||
| 5845 | } | ||
| 5764 | 5846 | ||
| 5765 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) | 5847 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) |
| 5766 | mk_pointer(&vtop->type); | 5848 | mk_pointer(&vtop->type); |
| @@ -6059,12 +6141,16 @@ static int case_cmp(const void *pa, const void *pb) · 292 unmodified lines | |||
| 6059 | return a < b ? -1 : a > b; | 6141 | return a < b ? -1 : a > b; |
| 6060 | } | 6142 | } |
| 6061 | 6143 | ||
| 6144 | static void gtst_addr(int t, int a) | ||
| 6145 | { | ||
| 6146 | gsym_addr(gvtst(0, t), a); | ||
| 6147 | } | ||
| 6148 | |||
| 6062 | static void gcase(struct case_t **base, int len, int *bsym) | 6149 | static void gcase(struct case_t **base, int len, int *bsym) |
| 6063 | { | 6150 | { |
| 6064 | struct case_t *p; | 6151 | struct case_t *p; |
| 6065 | int e; | 6152 | int e; |
| 6066 | int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; | 6153 | int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; |
| 6067 | gv(RC_INT); | ||
| 6068 | while (len > 4) { | 6154 | while (len > 4) { |
| 6069 | /* binary search */ | 6155 | /* binary search */ |
| 6070 | p = base[len/2]; | 6156 | p = base[len/2]; |
| @@ -6074,7 +6160,7 @@ static void gcase(struct case_t **base, int len, int *bsym) · 3 unmodified lines | |||
| 6074 | else | 6160 | else |
| 6075 | vpushi(p->v2); | 6161 | vpushi(p->v2); |
| 6076 | gen_op(TOK_LE); | 6162 | gen_op(TOK_LE); |
| 6077 | e = gtst(1, 0); | 6163 | e = gvtst(1, 0); |
| 6078 | vdup(); | 6164 | vdup(); |
| 6079 | if (ll) | 6165 | if (ll) |
| 6080 | vpushll(p->v1); | 6166 | vpushll(p->v1); |
| @@ -6084,10 +6170,6 @@ static void gcase(struct case_t **base, int len, int *bsym) · 3 unmodified lines | |||
| 6084 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ | 6170 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ |
| 6085 | /* x < v1 */ | 6171 | /* x < v1 */ |
| 6086 | gcase(base, len/2, bsym); | 6172 | gcase(base, len/2, bsym); |
| 6087 | if (cur_switch->def_sym) | ||
| 6088 | gjmp_addr(cur_switch->def_sym); | ||
| 6089 | else | ||
| 6090 | *bsym = gjmp(*bsym); | ||
| 6091 | /* x > v2 */ | 6173 | /* x > v2 */ |
| 6092 | gsym(e); | 6174 | gsym(e); |
| 6093 | e = len/2 + 1; | 6175 | e = len/2 + 1; |
| @@ -6106,7 +6188,7 @@ static void gcase(struct case_t **base, int len, int *bsym) · 12 unmodified lines | |||
| 6106 | gtst_addr(0, p->sym); | 6188 | gtst_addr(0, p->sym); |
| 6107 | } else { | 6189 | } else { |
| 6108 | gen_op(TOK_LE); | 6190 | gen_op(TOK_LE); |
| 6109 | e = gtst(1, 0); | 6191 | e = gvtst(1, 0); |
| 6110 | vdup(); | 6192 | vdup(); |
| 6111 | if (ll) | 6193 | if (ll) |
| 6112 | vpushll(p->v1); | 6194 | vpushll(p->v1); |
| @@ -6117,6 +6199,7 @@ static void gcase(struct case_t **base, int len, int *bsym) · 4 unmodified lines | |||
| 6117 | gsym(e); | 6199 | gsym(e); |
| 6118 | } | 6200 | } |
| 6119 | } | 6201 | } |
| 6202 | *bsym = gjmp(*bsym); | ||
| 6120 | } | 6203 | } |
| 6121 | 6204 | ||
| 6122 | /* call 'func' for each __attribute__((cleanup(func))) */ | 6205 | /* call 'func' for each __attribute__((cleanup(func))) */ |
| @@ -6367,15 +6450,17 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 244 unmodified lines | |||
| 6367 | gexpr(); | 6450 | gexpr(); |
| 6368 | skip(')'); | 6451 | skip(')'); |
| 6369 | switchval = *vtop--; | 6452 | switchval = *vtop--; |
| 6370 | a = 0; | 6453 | |
| 6371 | b = gjmp(0); /* jump to first case */ | ||
| 6372 | sw.p = NULL; sw.n = 0; sw.def_sym = 0; | 6454 | sw.p = NULL; sw.n = 0; sw.def_sym = 0; |
| 6373 | saved = cur_switch; | 6455 | saved = cur_switch; |
| 6374 | cur_switch = &sw; | 6456 | cur_switch = &sw; |
| 6457 | a = 0; | ||
| 6458 | b = gjmp(0); /* jump to first case */ | ||
| 6375 | block(&a, current_cleanups, csym, ccl, 0); | 6459 | block(&a, current_cleanups, csym, ccl, 0); |
| 6376 | a = gjmp(a); /* add implicit break */ | 6460 | a = gjmp(a); /* add implicit break */ |
| 6377 | /* case lookup */ | 6461 | /* case lookup */ |
| 6378 | gsym(b); | 6462 | gsym(b); |
| 6463 | |||
| 6379 | qsort(sw.p, sw.n, sizeof(void*), case_cmp); | 6464 | qsort(sw.p, sw.n, sizeof(void*), case_cmp); |
| 6380 | for (b = 1; b < sw.n; b++) | 6465 | for (b = 1; b < sw.n; b++) |
| 6381 | if (sw.p[b - 1]->v2 >= sw.p[b]->v1) | 6466 | if (sw.p[b - 1]->v2 >= sw.p[b]->v1) |
| @@ -6385,14 +6470,17 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 3 unmodified lines | |||
| 6385 | if ((switchval.type.t & VT_BTYPE) == VT_LLONG) | 6470 | if ((switchval.type.t & VT_BTYPE) == VT_LLONG) |
| 6386 | switchval.type.t &= ~VT_UNSIGNED; | 6471 | switchval.type.t &= ~VT_UNSIGNED; |
| 6387 | vpushv(&switchval); | 6472 | vpushv(&switchval); |
| 6388 | gcase(sw.p, sw.n, &a); | 6473 | gv(RC_INT); |
| 6474 | d = 0, gcase(sw.p, sw.n, &d); | ||
| 6389 | vpop(); | 6475 | vpop(); |
| 6390 | if (sw.def_sym) | 6476 | if (sw.def_sym) |
| 6391 | gjmp_addr(sw.def_sym); | 6477 | gsym_addr(d, sw.def_sym); |
| 6392 | dynarray_reset(&sw.p, &sw.n); | 6478 | else |
| 6393 | cur_switch = saved; | 6479 | gsym(d); |
| 6394 | /* break label */ | 6480 | /* break label */ |
| 6395 | gsym(a); | 6481 | gsym(a); |
| 6482 | dynarray_reset(&sw.p, &sw.n); | ||
| 6483 | cur_switch = saved; | ||
| 6396 | 6484 | ||
| 6397 | } else if (t == TOK_CASE) { | 6485 | } else if (t == TOK_CASE) { |
| 6398 | struct case_t *cr = tcc_malloc(sizeof(struct case_t)); | 6486 | struct case_t *cr = tcc_malloc(sizeof(struct case_t)); |
| @@ -3777,6 +3777,7 @@ void math_cmp_test(void) · 3776 unmodified lines | |||
| 3777 | double one = 1.0; | 3777 | double one = 1.0; |
| 3778 | double two = 2.0; | 3778 | double two = 2.0; |
| 3779 | int comp = 0; | 3779 | int comp = 0; |
| 3780 | int v; | ||
| 3780 | #define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part) | 3781 | #define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part) |
| 3781 | 3782 | ||
| 3782 | /* This asserts that "a op b" is _not_ true, but "a iop b" is true. | 3783 | /* This asserts that "a op b" is _not_ true, but "a iop b" is true. |
| @@ -3798,7 +3799,8 @@ void math_cmp_test(void) · 15 unmodified lines | |||
| 3798 | if ((a iop b) || comp) \ | 3799 | if ((a iop b) || comp) \ |
| 3799 | ; \ | 3800 | ; \ |
| 3800 | else \ | 3801 | else \ |
| 3801 | bug (a,b,op,iop,5); | 3802 | bug (a,b,op,iop,5); \ |
| 3803 | if (v = !(a op b), !v) bug(a,b,op,iop,7); | ||
| 3802 | 3804 | ||
| 3803 | /* Equality tests. */ | 3805 | /* Equality tests. */ |
| 3804 | FCMP(nan, nan, ==, !=, 0); | 3806 | FCMP(nan, nan, ==, !=, 0); |
| @@ -471,22 +471,22 @@ void load(int r, SValue *sv) · 470 unmodified lines | |||
| 471 | orex(1,0,r,0x8d); /* lea xxx(%ebp), r */ | 471 | orex(1,0,r,0x8d); /* lea xxx(%ebp), r */ |
| 472 | gen_modrm(r, VT_LOCAL, sv->sym, fc); | 472 | gen_modrm(r, VT_LOCAL, sv->sym, fc); |
| 473 | } else if (v == VT_CMP) { | 473 | } else if (v == VT_CMP) { |
| 474 | orex(0,r,0,0); | ||
| 475 | if ((fc & ~0x100) != TOK_NE) | ||
| 476 | oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */ | ||
| 477 | else | ||
| 478 | oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */ | ||
| 479 | if (fc & 0x100) | 474 | if (fc & 0x100) |
| 480 | { | 475 | { |
| 476 | v = vtop->cmp_r; | ||
| 477 | fc &= ~0x100; | ||
| 481 | /* This was a float compare. If the parity bit is | 478 | /* This was a float compare. If the parity bit is |
| 482 | set the result was unordered, meaning false for everything | 479 | set the result was unordered, meaning false for everything |
| 483 | except TOK_NE, and true for TOK_NE. */ | 480 | except TOK_NE, and true for TOK_NE. */ |
| 484 | fc &= ~0x100; | 481 | orex(0, r, 0, 0xb0 + REG_VALUE(r)); /* mov $0/1,%al */ |
| 485 | o(0x037a + (REX_BASE(r) << 8)); | 482 | g(v ^ fc ^ (v == TOK_NE)); |
| 486 | } | 483 | o(0x037a + (REX_BASE(r) << 8)); |
| 484 | } | ||
| 487 | orex(0,r,0, 0x0f); /* setxx %br */ | 485 | orex(0,r,0, 0x0f); /* setxx %br */ |
| 488 | o(fc); | 486 | o(fc); |
| 489 | o(0xc0 + REG_VALUE(r)); | 487 | o(0xc0 + REG_VALUE(r)); |
| 488 | orex(0,r,0, 0x0f); | ||
| 489 | o(0xc0b6 + REG_VALUE(r) * 0x900); /* movzbl %al, %eax */ | ||
| 490 | } else if (v == VT_JMP || v == VT_JMPI) { | 490 | } else if (v == VT_JMP || v == VT_JMPI) { |
| 491 | t = v & 1; | 491 | t = v & 1; |
| 492 | orex(0,r,0,0); | 492 | orex(0,r,0,0); |
| @@ -1666,42 +1666,23 @@ void gjmp_addr(int a) · 1173 unmodified lines | |||
| 1666 | } | 1666 | } |
| 1667 | } | 1667 | } |
| 1668 | 1668 | ||
| 1669 | ST_FUNC void gtst_addr(int inv, int a) | 1669 | ST_FUNC int gjmp_append(int n, int t) |
| 1670 | { | 1670 | { |
| 1671 | int v = vtop->r & VT_VALMASK; | 1671 | void *p; |
| 1672 | if (v == VT_CMP) { | 1672 | /* insert vtop->c jump list in t */ |
| 1673 | inv ^= (vtop--)->c.i; | 1673 | if (n) { |
| 1674 | a -= ind + 2; | 1674 | uint32_t n1 = n, n2; |
| 1675 | if (a == (char)a) { | 1675 | while ((n2 = read32le(p = cur_text_section->data + n1))) |
| 1676 | g(inv - 32); | 1676 | n1 = n2; |
| 1677 | g(a); | 1677 | write32le(p, t); |
| 1678 | } else { | 1678 | t = n; |
| 1679 | g(0x0f); | ||
| 1680 | oad(inv - 16, a - 4); | ||
| 1681 | } | ||
| 1682 | } else if ((v & ~1) == VT_JMP) { | ||
| 1683 | if ((v & 1) != inv) { | ||
| 1684 | gjmp_addr(a); | ||
| 1685 | gsym(vtop->c.i); | ||
| 1686 | } else { | ||
| 1687 | gsym(vtop->c.i); | ||
| 1688 | o(0x05eb); | ||
| 1689 | gjmp_addr(a); | ||
| 1690 | } | ||
| 1691 | vtop--; | ||
| 1692 | } | 1679 | } |
| 1680 | return t; | ||
| 1693 | } | 1681 | } |
| 1694 | 1682 | ||
| 1695 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ | 1683 | ST_FUNC int gjmp_cond(int op, int t) |
| 1696 | ST_FUNC int gtst(int inv, int t) | ||
| 1697 | { | 1684 | { |
| 1698 | int v = vtop->r & VT_VALMASK; | 1685 | if (op & 0x100) |
| 1699 | |||
| 1700 | if (nocode_wanted) { | ||
| 1701 | ; | ||
| 1702 | } else if (v == VT_CMP) { | ||
| 1703 | /* fast case : can jump directly since flags are set */ | ||
| 1704 | if (vtop->c.i & 0x100) | ||
| 1705 | { | 1686 | { |
| 1706 | /* This was a float compare. If the parity flag is set | 1687 | /* This was a float compare. If the parity flag is set |
| 1707 | the result was unordered. For anything except != this | 1688 | the result was unordered. For anything except != this |
| @@ -1710,9 +1691,10 @@ ST_FUNC int gtst(int inv, int t) · 2 unmodified lines | |||
| 1710 | Take care about inverting the test. We need to jump | 1691 | Take care about inverting the test. We need to jump |
| 1711 | to our target if the result was unordered and test wasn't NE, | 1692 | to our target if the result was unordered and test wasn't NE, |
| 1712 | otherwise if unordered we don't want to jump. */ | 1693 | otherwise if unordered we don't want to jump. */ |
| 1713 | vtop->c.i &= ~0x100; | 1694 | int v = vtop->cmp_r; |
| 1714 | if (inv == (vtop->c.i == TOK_NE)) | 1695 | op &= ~0x100; |
| 1715 | o(0x067a); /* jp +6 */ | 1696 | if (op ^ v ^ (v != TOK_NE)) |
| 1697 | o(0x067a); /* jp +6 */ | ||
| 1716 | else | 1698 | else |
| 1717 | { | 1699 | { |
| 1718 | g(0x0f); | 1700 | g(0x0f); |
| @@ -1720,25 +1702,8 @@ ST_FUNC int gtst(int inv, int t) · 1 unmodified line | |||
| 1720 | } | 1702 | } |
| 1721 | } | 1703 | } |
| 1722 | g(0x0f); | 1704 | g(0x0f); |
| 1723 | t = gjmp2((vtop->c.i - 16) ^ inv, t); | 1705 | t = gjmp2(op - 16, t); |
| 1724 | } else if (v == VT_JMP || v == VT_JMPI) { | 1706 | return t; |
| 1725 | /* && or || optimization */ | ||
| 1726 | if ((v & 1) == inv) { | ||
| 1727 | /* insert vtop->c jump list in t */ | ||
| 1728 | uint32_t n1, n = vtop->c.i; | ||
| 1729 | if (n) { | ||
| 1730 | while ((n1 = read32le(cur_text_section->data + n))) | ||
| 1731 | n = n1; | ||
| 1732 | write32le(cur_text_section->data + n, t); | ||
| 1733 | t = vtop->c.i; | ||
| 1734 | } | ||
| 1735 | } else { | ||
| 1736 | t = gjmp(t); | ||
| 1737 | gsym(vtop->c.i); | ||
| 1738 | } | ||
| 1739 | } | ||
| 1740 | vtop--; | ||
| 1741 | return t; | ||
| 1742 | } | 1707 | } |
| 1743 | 1708 | ||
| 1744 | /* generate an integer binary operation */ | 1709 | /* generate an integer binary operation */ |
| @@ -1779,10 +1744,8 @@ void gen_opi(int op) · 34 unmodified lines | |||
| 1779 | o(0xc0 + REG_VALUE(r) + REG_VALUE(fr) * 8); | 1744 | o(0xc0 + REG_VALUE(r) + REG_VALUE(fr) * 8); |
| 1780 | } | 1745 | } |
| 1781 | vtop--; | 1746 | vtop--; |
| 1782 | if (op >= TOK_ULT && op <= TOK_GT) { | 1747 | if (op >= TOK_ULT && op <= TOK_GT) |
| 1783 | vtop->r = VT_CMP; | 1748 | vset_VT_CMP(op); |
| 1784 | vtop->c.i = op; | ||
| 1785 | } | ||
| 1786 | break; | 1749 | break; |
| 1787 | case '-': | 1750 | case '-': |
| 1788 | case TOK_SUBC1: /* sub with carry generation */ | 1751 | case TOK_SUBC1: /* sub with carry generation */ |
| @@ -1937,8 +1900,7 @@ void gen_opf(int op) · 148 unmodified lines | |||
| 1937 | op = TOK_EQ; | 1900 | op = TOK_EQ; |
| 1938 | } | 1901 | } |
| 1939 | vtop--; | 1902 | vtop--; |
| 1940 | vtop->r = VT_CMP; | 1903 | vset_VT_CMP(op); |
| 1941 | vtop->c.i = op; | ||
| 1942 | } else { | 1904 | } else { |
| 1943 | /* no memory reference possible for long double operations */ | 1905 | /* no memory reference possible for long double operations */ |
| 1944 | load(TREG_ST0, vtop); | 1906 | load(TREG_ST0, vtop); |
| @@ -2016,8 +1978,8 @@ void gen_opf(int op) · 71 unmodified lines | |||
| 2016 | } | 1978 | } |
| 2017 | 1979 | ||
| 2018 | vtop--; | 1980 | vtop--; |
| 2019 | vtop->r = VT_CMP; | 1981 | vset_VT_CMP(op | 0x100); |
| 2020 | vtop->c.i = op | 0x100; | 1982 | vtop->cmp_r = op; |
| 2021 | } else { | 1983 | } else { |
| 2022 | assert((vtop->type.t & VT_BTYPE) != VT_LDOUBLE); | 1984 | assert((vtop->type.t & VT_BTYPE) != VT_LDOUBLE); |
| 2023 | switch(op) { | 1985 | switch(op) { |