Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 160627 | Differences between
and this patch

Collapse All | Expand All

(-)qemu-0.8.2-orig/cpu-all.h (+6 lines)
Lines 339-345 Link Here
339
339
340
static inline void stq_le_p(void *ptr, uint64_t v)
340
static inline void stq_le_p(void *ptr, uint64_t v)
341
{
341
{
342
#if defined(__i386__) && __GNUC__ >= 4
343
    const union { uint64_t v; uint32_t p[2]; } x = { .v = v };
344
    ((uint32_t *)ptr)[0] = x.p[0];
345
    ((uint32_t *)ptr)[1] = x.p[1];
346
#else
342
    *(uint64_t *)ptr = v;
347
    *(uint64_t *)ptr = v;
348
#endif
343
}
349
}
344
350
345
/* float access */
351
/* float access */
(-)qemu-0.8.2-orig/cpu-exec.c (+9 lines)
Lines 685-690 Link Here
685
                              : /* no outputs */
685
                              : /* no outputs */
686
                              : "r" (gen_func)
686
                              : "r" (gen_func)
687
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
687
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
688
#elif defined(TARGET_X86_64) && defined(__i386__)
689
                asm volatile ("push %%ebx\n"
690
                              "push %%esi\n"
691
                              "push %%edi\n"
692
                              "call *%0\n"
693
                              "pop %%edi\n"
694
                              "pop %%esi\n"
695
                              "pop %%ebx\n"
696
                              : : "r" (gen_func) : "ebx", "esi", "edi");
688
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
697
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
689
{
698
{
690
    if (!(tb->cflags & CF_CODE_COPY)) {
699
    if (!(tb->cflags & CF_CODE_COPY)) {
(-)qemu-0.8.2-orig/dyngen.c (-22 / +758 lines)
Lines 32-37 Link Here
32
32
33
#include "config-host.h"
33
#include "config-host.h"
34
34
35
//#define DEBUG_OP
36
35
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
37
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
36
   compilation */
38
   compilation */
37
#if defined(CONFIG_WIN32)
39
#if defined(CONFIG_WIN32)
Lines 1343-1348 Link Here
1343
#endif
1345
#endif
1344
1346
1345
1347
1348
#if defined(HOST_I386) || defined(HOST_X86_64)
1349
1350
/* This byte is the first byte of an instruction.  */
1351
#define FLAG_INSN     (1 << 0)
1352
/* This byte has been processed as part of an instruction.  */
1353
#define FLAG_SCANNED  (1 << 1)
1354
/* This instruction is a return instruction.  Gcc cometimes generates prefix
1355
   bytes, so may be more than one byte long.  */
1356
#define FLAG_RET      (1 << 2)
1357
/* This is either the target of a jump, or the preceeding instruction uses
1358
   a pc-relative offset.  */
1359
#define FLAG_TARGET   (1 << 3)
1360
/* This is a magic instruction that needs fixing up.  */
1361
#define FLAG_EXIT     (1 << 4)
1362
/* This instruction clobbers the stack pointer.  */
1363
/* XXX only supports push, pop, add/sub $imm,%esp  */
1364
#define FLAG_STACK    (1 << 5)
1365
#define MAX_EXITS     5
1366
1367
static void
1368
bad_opcode(const char *name, uint32_t op)
1369
{
1370
    error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
1371
}
1372
1373
/* Mark len bytes as scanned,  Returns insn_size + len.  Reports an error
1374
   if these bytes have already been scanned.  */
1375
static int
1376
eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
1377
{
1378
    while (len > 0) {
1379
        /* This should never occur in sane code.  */
1380
        if (flags[insn + insn_size] & FLAG_SCANNED)
1381
            error ("Overlapping instructions in %s", name);
1382
        flags[insn + insn_size] |= FLAG_SCANNED;
1383
        insn_size++;
1384
        len--;
1385
    }
1386
    return insn_size;
1387
}
1388
1389
static void
1390
trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
1391
                 int len)
1392
{
1393
    uint8_t *ptr;
1394
    uint8_t op;
1395
    int modrm;
1396
    int is_prefix;
1397
    int op_size;
1398
    int addr_size;
1399
    int insn_size;
1400
    int is_ret;
1401
    int is_condjmp;
1402
    int is_jmp;
1403
    int is_exit;
1404
    int is_pcrel;
1405
    int is_stack;
1406
    int immed;
1407
    int seen_rexw;
1408
    int32_t disp;
1409
1410
    ptr = start_p + insn;
1411
    /* nonzero if this insn has a ModR/M byte.  */
1412
    modrm = 1;
1413
    /* The size of the immediate value in this instruction.  */
1414
    immed = 0;
1415
    /* The operand size.  */
1416
    op_size = 4;
1417
    /* The address size */
1418
    addr_size = 4;
1419
    /* The total length of this instruction.  */
1420
    insn_size = 0;
1421
    is_prefix = 1;
1422
    is_ret = 0;
1423
    is_condjmp = 0;
1424
    is_jmp = 0;
1425
    is_exit = 0;
1426
    seen_rexw = 0;
1427
    is_pcrel = 0;
1428
    is_stack = 0;
1429
1430
    while (is_prefix) {
1431
        op = ptr[insn_size];
1432
        insn_size = eat_bytes(name, flags, insn, insn_size, 1);
1433
        is_prefix = 0;
1434
        switch (op >> 4) {
1435
        case 0:
1436
        case 1:
1437
        case 2:
1438
        case 3:
1439
            if (op == 0x0f) {
1440
                /* two-byte opcode.  */
1441
                op = ptr[insn_size];
1442
                insn_size = eat_bytes(name, flags, insn, insn_size, 1);
1443
                switch (op >> 4) {
1444
                case 0:
1445
                    if ((op & 0xf) > 3)
1446
                      modrm = 0;
1447
                    break;
1448
                case 1: /* vector move or prefetch */
1449
                case 2: /* various moves and vector compares.  */
1450
                case 4: /* cmov */
1451
                case 5: /* vector instructions */
1452
                case 6:
1453
                case 13:
1454
                case 14:
1455
                case 15:
1456
                    break;
1457
                case 7: /* mmx */
1458
                    if (op & 0x77) /* emms */
1459
                      modrm = 0;
1460
                    break;
1461
                case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
1462
                    modrm = 0;
1463
                    break;
1464
                case 8: /* long conditional jump */
1465
                    is_condjmp = 1;
1466
                    immed = op_size;
1467
                    modrm = 0;
1468
                    break;
1469
                case 9: /* setcc */
1470
                    break;
1471
                case 10:
1472
                    switch (op & 0x7) {
1473
                    case 0: /* push fs/gs */
1474
                    case 1: /* pop fs/gs */
1475
                        is_stack = 1;
1476
                    case 2: /* cpuid/rsm */
1477
                        modrm = 0;
1478
                        break;
1479
                    case 4: /* shld/shrd immediate */
1480
                        immed = 1;
1481
                        break;
1482
                    default: /* Normal instructions with a ModR/M byte.  */
1483
                        break;
1484
                    }
1485
                    break;
1486
                case 11:
1487
                    switch (op & 0xf) {
1488
                    case 10: /* bt, bts, btr, btc */
1489
                        immed = 1;
1490
                        break;
1491
                    default:
1492
                        /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
1493
                           undefined, and movsx */
1494
                        break;
1495
                    }
1496
                    break;
1497
                case 12:
1498
                    if (op & 8) {
1499
                        /* bswap */
1500
                        modrm = 0;
1501
                    } else {
1502
                        switch (op & 0x7) {
1503
                        case 2:
1504
                        case 4:
1505
                        case 5:
1506
                        case 6:
1507
                            immed = 1;
1508
                            break;
1509
                        default:
1510
                            break;
1511
                        }
1512
                    }
1513
                    break;
1514
                }
1515
            } else if ((op & 0x07) <= 0x3) {
1516
                /* General arithmentic ax.  */
1517
            } else if ((op & 0x07) <= 0x5) {
1518
                /* General arithmetic ax, immediate.  */
1519
                if (op & 0x01)
1520
                    immed = op_size;
1521
                else
1522
                    immed = 1;
1523
                modrm = 0;
1524
            } else if ((op & 0x23) == 0x22) {
1525
                /* Segment prefix.  */
1526
                is_prefix = 1;
1527
            } else {
1528
                /* Segment register push/pop or DAA/AAA/DAS/AAS.  */
1529
                modrm = 0;
1530
            }
1531
            break;
1532
1533
#if defined(HOST_X86_64)
1534
        case 4: /* rex prefix.  */
1535
            is_prefix = 1;
1536
            /* The address/operand size is actually 64-bit, but the immediate
1537
               values in the instruction are still 32-bit.  */
1538
            op_size = 4;
1539
            addr_size = 4;
1540
            if (op & 8)
1541
                seen_rexw = 1;
1542
            break;
1543
#else
1544
        case 4: /* inc/dec register.  */
1545
#endif
1546
        case 5: /* push/pop general register.  */
1547
            modrm = 0;
1548
            is_stack = 1;
1549
            break;
1550
1551
        case 6:
1552
            switch (op & 0x0f) {
1553
            case 0: /* pusha */
1554
            case 1: /* popa */
1555
                modrm = 0;
1556
                is_stack = 1;
1557
                break;
1558
            case 2: /* bound */
1559
            case 3: /* arpl */
1560
                break;
1561
            case 4: /* FS */
1562
            case 5: /* GS */
1563
                is_prefix = 1;
1564
                break;
1565
            case 6: /* opcode size prefix.  */
1566
                op_size = 2;
1567
                is_prefix = 1;
1568
                break;
1569
            case 7: /* Address size prefix.  */
1570
                addr_size = 2;
1571
                is_prefix = 1;
1572
                break;
1573
            case 8: /* push immediate */
1574
                immed = op_size;
1575
                modrm = 0;
1576
                is_stack = 1;
1577
                break;
1578
            case 10: /* push 8-bit immediate */
1579
                immed = 1;
1580
                modrm = 0;
1581
                is_stack = 1;
1582
                break;
1583
            case 9: /* imul immediate */
1584
                immed = op_size;
1585
                break;
1586
            case 11: /* imul 8-bit immediate */
1587
                immed = 1;
1588
                break;
1589
            case 12: /* insb */
1590
            case 13: /* insw */
1591
            case 14: /* outsb */
1592
            case 15: /* outsw */
1593
                modrm = 0;
1594
                break;
1595
            }
1596
            break;
1597
1598
        case 7: /* Short conditional jump.  */
1599
            is_condjmp = 1;
1600
            immed = 1;
1601
            modrm = 0;
1602
            break;
1603
          
1604
        case 8:
1605
            if ((op & 0xf) <= 3) {
1606
                /* arithmetic immediate.  */
1607
                if ((op & 3) == 1)
1608
                    immed = op_size;
1609
                else
1610
                    immed = 1;
1611
                if (op == 0x81 || op == 0x83) {
1612
                    /* add, sub */
1613
                    op = ptr[insn_size];
1614
                    switch ((op >> 3) & 7) {
1615
                    case 0:
1616
                    case 5:
1617
                        is_stack = (op & 7) == 4;
1618
                        break;
1619
                    }
1620
                }
1621
            }
1622
            else if ((op & 0xf) == 0xf) {
1623
                /* pop general.  */
1624
                is_stack = 1;
1625
            }
1626
            /* else test, xchg, mov, lea.  */
1627
            break;
1628
1629
        case 9:
1630
            /* Various single-byte opcodes with no modrm byte.  */
1631
            modrm = 0;
1632
            if (op == 10) {
1633
                /* Call */
1634
                immed = 4;
1635
            }
1636
            break;
1637
1638
        case 10:
1639
            switch ((op & 0xe) >> 1) {
1640
            case 0: /* mov absoliute immediate.  */
1641
            case 1:
1642
                if (seen_rexw)
1643
                    immed = 8;
1644
                else
1645
                    immed = addr_size;
1646
                break;
1647
            case 4: /* test immediate.  */
1648
                if (op & 1)
1649
                    immed = op_size;
1650
                else
1651
                    immed = 1;
1652
                break;
1653
            default: /* Various string ops.  */
1654
                break;
1655
            }
1656
            modrm = 0;
1657
            break;
1658
1659
        case 11: /* move immediate to register */
1660
            if (op & 8) {
1661
                if (seen_rexw)
1662
                    immed = 8;
1663
                else
1664
                    immed = op_size;
1665
            } else {
1666
                immed = 1;
1667
            }
1668
            modrm = 0;
1669
            break;
1670
1671
          case 12:
1672
            switch (op & 0xf) {
1673
            case 0: /* shift immediate */
1674
            case 1:
1675
                immed = 1;
1676
                break;
1677
            case 2: /* ret immediate */
1678
                immed = 2;
1679
                modrm = 0;
1680
                bad_opcode(name, op);
1681
                break;
1682
            case 3: /* ret */
1683
                modrm = 0;
1684
                is_ret = 1;
1685
            case 4: /* les */
1686
            case 5: /* lds */
1687
                break;
1688
            case 6: /* mov immediate byte */
1689
                immed = 1;
1690
                break;
1691
            case 7: /* mov immediate */
1692
                immed = op_size;
1693
                break;
1694
            case 8: /* enter */
1695
                /* TODO: Is this right?  */
1696
                immed = 3;
1697
                modrm = 0;
1698
                break;
1699
            case 10: /* retf immediate */
1700
                immed = 2;
1701
                modrm = 0;
1702
                bad_opcode(name, op);
1703
                break;
1704
            case 13: /* int */
1705
                immed = 1;
1706
                modrm = 0;
1707
                break;
1708
            case 11: /* retf */
1709
            case 15: /* iret */
1710
                modrm = 0;
1711
                bad_opcode(name, op);
1712
                break;
1713
            default: /* leave, int3 or into */
1714
                modrm = 0;
1715
                break;
1716
            }
1717
            break;
1718
1719
        case 13:
1720
            if ((op & 0xf) >= 8) {
1721
                /* Coprocessor escape.  For our purposes this is just a normal
1722
                   instruction with a ModR/M byte.  */
1723
            } else if ((op & 0xf) >= 4) {
1724
                /* AAM, AAD or XLAT */
1725
                modrm = 0;
1726
            }
1727
            /* else shift instruction */
1728
            break;
1729
1730
        case 14:
1731
            switch ((op & 0xc) >> 2) {
1732
            case 0: /* loop or jcxz */
1733
                is_condjmp = 1;
1734
                immed = 1;
1735
                break;
1736
            case 1: /* in/out immed */
1737
                immed = 1;
1738
                break;
1739
            case 2: /* call or jmp */
1740
                switch (op & 3) {
1741
                case 0: /* call */
1742
                    immed = op_size;
1743
                    break;
1744
                case 1: /* long jump */
1745
                    immed = 4;
1746
                    is_jmp = 1;
1747
                    break;
1748
                case 2: /* far jmp */
1749
                    bad_opcode(name, op);
1750
                    break;
1751
                case 3: /* short jmp */
1752
                    immed = 1;
1753
                    is_jmp = 1;
1754
                    break;
1755
                }
1756
                break;
1757
            case 3: /* in/out register */
1758
                break;
1759
            }
1760
            modrm = 0;
1761
            break;
1762
1763
        case 15:
1764
            switch ((op & 0xe) >> 1) {
1765
            case 0:
1766
            case 1:
1767
                is_prefix = 1;
1768
                break;
1769
            case 2:
1770
            case 4:
1771
            case 5:
1772
            case 6:
1773
                modrm = 0;
1774
                /* Some privileged insns are used as markers.  */
1775
                switch (op) {
1776
                case 0xf4: /* hlt: Exit translation block.  */
1777
                    is_exit = 1;
1778
                    break;
1779
                case 0xfa: /* cli: Jump to label.  */
1780
                    is_exit = 1;
1781
                    immed = 4;
1782
                    break;
1783
                case 0xfb: /* sti: TB patch jump.  */
1784
                    /* Mark the insn for patching, but continue sscanning.  */
1785
                    flags[insn] |= FLAG_EXIT;
1786
                    immed = 4;
1787
                    break;
1788
                }
1789
                break;
1790
            case 3: /* unary grp3 */
1791
                if ((ptr[insn_size] & 0x38) == 0) {
1792
                    if (op == 0xf7)
1793
                        immed = op_size;
1794
                    else
1795
                        immed = 1; /* test immediate */
1796
                }
1797
                break;
1798
            case 7: /* inc/dec grp4/5 */
1799
                /* TODO: This includes indirect jumps.  We should fail if we
1800
                   encounter one of these. */
1801
                break;
1802
            }
1803
            break;
1804
        }
1805
    }
1806
1807
    if (modrm) {
1808
        if (addr_size != 4)
1809
            error("16-bit addressing mode used in %s", name);
1810
1811
        disp = 0;
1812
        modrm = ptr[insn_size];
1813
        insn_size = eat_bytes(name, flags, insn, insn_size, 1);
1814
        modrm &= 0xc7;
1815
        switch ((modrm & 0xc0) >> 6) {
1816
        case 0:
1817
            if (modrm == 5)
1818
              disp = 4;
1819
            break;
1820
        case 1:
1821
            disp = 1;
1822
            break;
1823
        case 2:
1824
            disp = 4;
1825
            break;
1826
        }
1827
        if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
1828
            /* SIB byte */
1829
            if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
1830
                disp = 4;
1831
                is_pcrel = 1;
1832
            }
1833
            insn_size = eat_bytes(name, flags, insn, insn_size, 1);
1834
        }
1835
        insn_size = eat_bytes(name, flags, insn, insn_size, disp);
1836
    }
1837
    insn_size = eat_bytes(name, flags, insn, insn_size, immed);
1838
    if (is_condjmp || is_jmp) {
1839
        if (immed == 1) {
1840
            disp = (int8_t)*(ptr + insn_size - 1);
1841
        } else {
1842
            disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
1843
                   | (((int32_t)*(ptr + insn_size - 2)) << 16)
1844
                   | (((int32_t)*(ptr + insn_size - 3)) << 8)
1845
                   | *(ptr + insn_size - 4);
1846
        }
1847
        disp += insn_size;
1848
        /* Jumps to external symbols point to the address of the offset
1849
           before relocation.  */
1850
        /* ??? These are probably a tailcall.  We could fix them up by
1851
           replacing them with jmp to EOB + call, but it's easier to just
1852
           prevent the compiler generating them.  */
1853
        if (disp == 1)
1854
            error("Unconditional jump (sibcall?) in %s", name);
1855
        disp += insn;
1856
        if (disp < 0 || disp > len)
1857
            error("Jump outside instruction in %s", name);
1858
1859
        if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
1860
            error("Overlapping instructions in %s", name);
1861
1862
        flags[disp] |= (FLAG_INSN | FLAG_TARGET);
1863
        is_pcrel = 1; 
1864
    }
1865
    if (is_pcrel) {
1866
        /* Mark the following insn as a jump target.  This will stop
1867
           this instruction being moved.  */
1868
        flags[insn + insn_size] |= FLAG_TARGET;
1869
    }
1870
    if (is_ret)
1871
      flags[insn] |= FLAG_RET;
1872
1873
    if (is_exit)
1874
      flags[insn] |= FLAG_EXIT;
1875
1876
    if (is_stack)
1877
      flags[insn] |= FLAG_STACK;
1878
1879
    if (!(is_jmp || is_ret || is_exit))
1880
      flags[insn + insn_size] |= FLAG_INSN;
1881
}
1882
1883
/* Scan a function body.  Returns the position of the return sequence.
1884
   Sets *patch_bytes to the number of bytes that need to be copied from that
1885
   location.  If no patching is required (ie. the return is the last insn)
1886
   *patch_bytes will be set to -1.  *plen is the number of code bytes to copy.
1887
 */
1888
static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
1889
                         int *patch_bytes, int *exit_addrs)
1890
{
1891
    char *flags;
1892
    int more;
1893
    int insn;
1894
    int retpos;
1895
    int bytes;
1896
    int num_exits;
1897
    int len;
1898
    int last_insn;
1899
    int stack_clobbered;
1900
1901
    len = *plen;
1902
    flags = malloc(len + 1);
1903
    memset(flags, 0, len + 1);
1904
    flags[0] |= FLAG_INSN;
1905
    more = 1;
1906
    while (more) {
1907
        more = 0;
1908
        for (insn = 0; insn < len; insn++) {
1909
            if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
1910
                trace_i386_insn(name, start_p, flags, insn, len);
1911
                more = 1;
1912
            }
1913
        }
1914
    }
1915
1916
    /* Strip any unused code at the end of the function.  */
1917
    while (len > 0 && flags[len - 1] == 0)
1918
      len--;
1919
1920
    retpos = -1;
1921
    num_exits = 0;
1922
    last_insn = 0;
1923
    stack_clobbered = 0;
1924
    for (insn = 0; insn < len; insn++) {
1925
        if (flags[insn] & FLAG_RET) {
1926
            /* ??? In theory it should be possible to handle multiple return
1927
               points.  In practice it's not worth the effort.  */
1928
            if (retpos != -1)
1929
                error("Multiple return instructions in %s", name);
1930
            retpos = insn;
1931
        }
1932
        if (flags[insn] & FLAG_EXIT) {
1933
            if (stack_clobbered)
1934
                error("Stack clobbered in %s", name);
1935
            if (num_exits == MAX_EXITS)
1936
                error("Too many block exits in %s", name);
1937
            exit_addrs[num_exits] = insn;
1938
            num_exits++;
1939
        }
1940
        if (flags[insn] & FLAG_INSN)
1941
            last_insn = insn;
1942
        if (flags[insn] & FLAG_STACK)
1943
            stack_clobbered = 1;
1944
    }
1945
1946
    exit_addrs[num_exits] = -1;
1947
    if (retpos == -1) {
1948
        if (num_exits == 0) {
1949
            error ("No return instruction found in %s", name);
1950
        } else {
1951
            retpos = len;
1952
            last_insn = len;
1953
        }
1954
    }
1955
    
1956
    /* If the return instruction is the last instruction we can just 
1957
       remove it.  */
1958
    if (retpos == last_insn)
1959
        *patch_bytes = -1;
1960
    else
1961
        *patch_bytes = 0;
1962
1963
    /* Back up over any nop instructions.  */
1964
    while (retpos > 0
1965
           && (flags[retpos] & FLAG_TARGET) == 0
1966
           && (flags[retpos - 1] & FLAG_INSN) != 0
1967
           && start_p[retpos - 1] == 0x90) {
1968
        retpos--;
1969
    }
1970
1971
    if (*patch_bytes == -1) {
1972
        *plen = retpos;
1973
        free (flags);
1974
        return retpos;
1975
    }
1976
    *plen = len;
1977
1978
    /* The ret is in the middle of the function.  Find four more bytes that
1979
       so the ret can be replaced by a jmp. */
1980
    /* ??? Use a short jump where possible. */
1981
    bytes = 4;
1982
    insn = retpos + 1;
1983
    /* We can clobber everything up to the next jump target.  */
1984
    while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
1985
        insn++;
1986
        bytes--;
1987
    }
1988
    if (bytes > 0) {
1989
        /* ???: Strip out nop blocks.  */
1990
        /* We can't do the replacement without clobbering anything important.
1991
           Copy preceeding instructions(s) to give us some space.  */
1992
        while (retpos > 0) {
1993
            /* If this byte is the target of a jmp we can't move it.  */
1994
            if (flags[retpos] & FLAG_TARGET)
1995
                break;
1996
1997
            (*patch_bytes)++;
1998
            bytes--;
1999
            retpos--;
2000
2001
            /* Break out of the loop if we have enough space and this is either 
2002
               the first byte of an instruction or a pad byte.  */
2003
            if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
2004
                && bytes <= 0) {
2005
                break;
2006
            }
2007
        }
2008
    }
2009
2010
    if (bytes > 0)
2011
        error("Unable to replace ret with jmp in %s\n", name);
2012
2013
    free(flags);
2014
    return retpos;
2015
}
2016
2017
#endif
2018
1346
#define MAX_ARGS 3
2019
#define MAX_ARGS 3
1347
2020
1348
/* generate op code */
2021
/* generate op code */
Lines 1356-1361 Link Here
1356
    uint8_t args_present[MAX_ARGS];
2029
    uint8_t args_present[MAX_ARGS];
1357
    const char *sym_name, *p;
2030
    const char *sym_name, *p;
1358
    EXE_RELOC *rel;
2031
    EXE_RELOC *rel;
2032
#if defined(HOST_I386) || defined(HOST_X86_64)
2033
    int patch_bytes;
2034
    int retpos;
2035
    int exit_addrs[MAX_EXITS];
2036
#endif
1359
2037
1360
    /* Compute exact size excluding prologue and epilogue instructions.
2038
    /* Compute exact size excluding prologue and epilogue instructions.
1361
     * Increment start_offset to skip epilogue instructions, then compute
2039
     * Increment start_offset to skip epilogue instructions, then compute
Lines 1366-1398 Link Here
1366
    p_end = p_start + size;
2044
    p_end = p_start + size;
1367
    start_offset = offset;
2045
    start_offset = offset;
1368
#if defined(HOST_I386) || defined(HOST_X86_64)
2046
#if defined(HOST_I386) || defined(HOST_X86_64)
1369
#ifdef CONFIG_FORMAT_COFF
1370
    {
1371
        uint8_t *p;
1372
        p = p_end - 1;
1373
        if (p == p_start)
1374
            error("empty code for %s", name);
1375
        while (*p != 0xc3) {
1376
            p--;
1377
            if (p <= p_start)
1378
                error("ret or jmp expected at the end of %s", name);
1379
        }
1380
        copy_size = p - p_start;
1381
    }
1382
#else
1383
    {
2047
    {
1384
        int len;
2048
        int len;
1385
        len = p_end - p_start;
2049
        len = p_end - p_start;
1386
        if (len == 0)
2050
        retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
1387
            error("empty code for %s", name);
1388
        if (p_end[-1] == 0xc3) {
1389
            len--;
1390
        } else {
1391
            error("ret or jmp expected at the end of %s", name);
1392
        }
1393
        copy_size = len;
2051
        copy_size = len;
1394
    }
2052
    }
1395
#endif    
1396
#elif defined(HOST_PPC)
2053
#elif defined(HOST_PPC)
1397
    {
2054
    {
1398
        uint8_t *p;
2055
        uint8_t *p;
Lines 1596-1601 Link Here
1596
    }
2253
    }
1597
2254
1598
    if (gen_switch == 2) {
2255
    if (gen_switch == 2) {
2256
#if defined(HOST_I386) || defined(HOST_X86_64)
2257
        if (patch_bytes != -1)
2258
            copy_size += patch_bytes;
2259
#ifdef DEBUG_OP
2260
        copy_size += 2;
2261
#endif
2262
#endif
1599
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
2263
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1600
    } else if (gen_switch == 1) {
2264
    } else if (gen_switch == 1) {
1601
2265
Lines 1800-1806 Link Here
1800
#error unsupport object format
2464
#error unsupport object format
1801
#endif
2465
#endif
1802
                }
2466
                }
2467
               }
2468
                /* Replace the marker instructions with the actual opcodes.  */
2469
                for (i = 0; exit_addrs[i] != -1; i++) {
2470
                    int op;
2471
                    switch (p_start[exit_addrs[i]])
2472
                      {
2473
                      case 0xf4: op = 0xc3; break; /* hlt -> ret */
2474
                      case 0xfa: op = 0xe9; break; /* cli -> jmp */
2475
                      case 0xfb: op = 0xe9; break; /* sti -> jmp */
2476
                      default: error("Internal error");
2477
                      }
2478
                    fprintf(outfile, 
2479
                            "    *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
2480
                            exit_addrs[i], op);
1803
                }
2481
                }
2482
                /* Fix up the return instruction.  */
2483
                if (patch_bytes != -1) {
2484
                    if (patch_bytes) {
2485
                        fprintf(outfile, "    memcpy(gen_code_ptr + %d,"
2486
                                "gen_code_ptr + %d, %d);\n",
2487
                                copy_size, retpos, patch_bytes);
2488
                    }
2489
                    fprintf(outfile,
2490
                            "    *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
2491
                            retpos);
2492
                    fprintf(outfile,
2493
                            "    *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
2494
                            retpos + 1, copy_size - (retpos + 5));
2495
                    
2496
                    copy_size += patch_bytes;
2497
                }
2498
#ifdef DEBUG_OP
2499
                fprintf(outfile,
2500
                        "    *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
2501
                        copy_size);
2502
                copy_size += 2;
2503
#endif
1804
            }
2504
            }
1805
#elif defined(HOST_X86_64)
2505
#elif defined(HOST_X86_64)
1806
            {
2506
            {
Lines 1834-1839 Link Here
1834
                    }
2534
                    }
1835
                }
2535
                }
1836
                }
2536
                }
2537
                /* Replace the marker instructions with the actual opcodes.  */
2538
                for (i = 0; exit_addrs[i] != -1; i++) {
2539
                    int op;
2540
                    switch (p_start[exit_addrs[i]])
2541
                      {
2542
                      case 0xf4: op = 0xc3; break; /* hlt -> ret */
2543
                      case 0xfa: op = 0xe9; break; /* cli -> jmp */
2544
                      case 0xfb: op = 0xe9; break; /* sti -> jmp */
2545
                      default: error("Internal error");
2546
                      }
2547
                    fprintf(outfile, 
2548
                            "    *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
2549
                            exit_addrs[i], op);
2550
                }
2551
                /* Fix up the return instruction.  */
2552
                if (patch_bytes != -1) {
2553
                    if (patch_bytes) {
2554
                        fprintf(outfile, "    memcpy(gen_code_ptr + %d,"
2555
                                "gen_code_ptr + %d, %d);\n",
2556
                                copy_size, retpos, patch_bytes);
2557
                    }
2558
                    fprintf(outfile,
2559
                            "    *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
2560
                            retpos);
2561
                    fprintf(outfile,
2562
                            "    *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
2563
                            retpos + 1, copy_size - (retpos + 5));
2564
                    
2565
                    copy_size += patch_bytes;
2566
                }
2567
#ifdef DEBUG_OP
2568
                fprintf(outfile,
2569
                        "    *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
2570
                        copy_size);
2571
                copy_size += 2;
2572
#endif
1837
            }
2573
            }
1838
#elif defined(HOST_PPC)
2574
#elif defined(HOST_PPC)
1839
            {
2575
            {
(-)qemu-0.8.2-orig/dyngen-exec.h (-4 / +16 lines)
Lines 188-194 Link Here
188
#endif
188
#endif
189
189
190
/* force GCC to generate only one epilog at the end of the function */
190
/* force GCC to generate only one epilog at the end of the function */
191
#if defined(__i386__) || defined(__x86_64__)
192
/* Also add 4 bytes of padding so that we can replace the ret with a jmp.  */
193
#define FORCE_RET() asm volatile ("nop;nop;nop;nop");
194
#else
191
#define FORCE_RET() asm volatile ("");
195
#define FORCE_RET() asm volatile ("");
196
#endif
192
197
193
#ifndef OPPROTO
198
#ifndef OPPROTO
194
#define OPPROTO
199
#define OPPROTO
Lines 238-249 Link Here
238
#endif
243
#endif
239
244
240
#ifdef __i386__
245
#ifdef __i386__
241
#define EXIT_TB() asm volatile ("ret")
246
/* Dyngen will replace hlt instructions with a ret instruction.  Inserting a
242
#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
247
   ret directly would confuse dyngen.  */
248
#define EXIT_TB() asm volatile ("hlt")
249
/* Dyngen will replace cli with 0x9e (jmp). 
250
   We generate the offset manually.  */
251
#define GOTO_LABEL_PARAM(n) \
252
  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
243
#endif
253
#endif
244
#ifdef __x86_64__
254
#ifdef __x86_64__
245
#define EXIT_TB() asm volatile ("ret")
255
/* The same as i386.  */
246
#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
256
#define EXIT_TB() asm volatile ("hlt")
257
#define GOTO_LABEL_PARAM(n) \
258
  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
247
#endif
259
#endif
248
#ifdef __powerpc__
260
#ifdef __powerpc__
249
#define EXIT_TB() asm volatile ("blr")
261
#define EXIT_TB() asm volatile ("blr")
(-)qemu-0.8.2-orig/exec-all.h (-2 / +3 lines)
Lines 316-329 Link Here
316
316
317
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
317
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
318
318
319
/* we patch the jump instruction directly */
319
/* we patch the jump instruction directly.  Use sti in place of the actual
320
   jmp instruction so that dyngen can patch in the correct result.  */
320
#define GOTO_TB(opname, tbparam, n)\
321
#define GOTO_TB(opname, tbparam, n)\
321
do {\
322
do {\
322
    asm volatile (".section .data\n"\
323
    asm volatile (".section .data\n"\
323
		  ASM_OP_LABEL_NAME(n, opname) ":\n"\
324
		  ASM_OP_LABEL_NAME(n, opname) ":\n"\
324
		  ".long 1f\n"\
325
		  ".long 1f\n"\
325
		  ASM_PREVIOUS_SECTION \
326
		  ASM_PREVIOUS_SECTION \
326
                  "jmp " ASM_NAME(__op_jmp) #n "\n"\
327
                  "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
327
		  "1:\n");\
328
		  "1:\n");\
328
} while (0)
329
} while (0)
329
330
(-)qemu-0.8.2-orig/Makefile.target (+4 lines)
Lines 73-78 Link Here
73
else
73
else
74
OP_CFLAGS+= -malign-functions=0
74
OP_CFLAGS+= -malign-functions=0
75
endif
75
endif
76
ifeq ($(TARGET_ARCH), x86_64)
77
# XXX globally save %ebx, %esi, %edi on entry to generated function
78
OP_CFLAGS+= -fcall-used-ebx -fcall-used-esi -fcall-used-edi
79
endif
76
80
77
ifdef TARGET_GPROF
81
ifdef TARGET_GPROF
78
USE_I386_LD=y
82
USE_I386_LD=y
(-)qemu-0.8.2-orig/softmmu_header.h (-8 / +7 lines)
Lines 108-114 Link Here
108
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
108
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
109
109
110
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
110
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
111
    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
111
    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU) && (__GNUC__ < 4)
112
112
113
#define CPU_TLB_ENTRY_BITS 4
113
#define CPU_TLB_ENTRY_BITS 4
114
114
Lines 150-156 Link Here
150
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
150
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
151
                  "i" (CPU_MEM_INDEX),
151
                  "i" (CPU_MEM_INDEX),
152
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
152
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
153
                  : "%eax", "%ecx", "%edx", "memory", "cc");
153
                  : "%eax", "%edx", "memory", "cc");
154
    return res;
154
    return res;
155
}
155
}
156
156
Lines 197-209 Link Here
197
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
197
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
198
                  "i" (CPU_MEM_INDEX),
198
                  "i" (CPU_MEM_INDEX),
199
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
199
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
200
                  : "%eax", "%ecx", "%edx", "memory", "cc");
200
                  : "%eax", "%edx", "memory", "cc");
201
    return res;
201
    return res;
202
}
202
}
203
#endif
203
#endif
204
204
205
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
205
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE val)
206
{
206
{
207
    RES_TYPE v = val;
207
    asm volatile ("movl %0, %%edx\n"
208
    asm volatile ("movl %0, %%edx\n"
208
                  "movl %0, %%eax\n"
209
                  "movl %0, %%eax\n"
209
                  "shrl %3, %%edx\n"
210
                  "shrl %3, %%edx\n"
Lines 240-255 Link Here
240
                  "2:\n"
241
                  "2:\n"
241
                  : 
242
                  : 
242
                  : "r" (ptr), 
243
                  : "r" (ptr), 
243
/* NOTE: 'q' would be needed as constraint, but we could not use it
244
                  "q" (v), 
244
   with T1 ! */
245
                  "r" (v), 
246
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), 
245
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), 
247
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), 
246
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), 
248
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
247
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
249
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
248
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
250
                  "i" (CPU_MEM_INDEX),
249
                  "i" (CPU_MEM_INDEX),
251
                  "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
250
                  "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
252
                  : "%eax", "%ecx", "%edx", "memory", "cc");
251
                  : "%eax", "%edx", "memory", "cc");
253
}
252
}
254
253
255
#else
254
#else
(-)qemu-0.8.2-orig/target-i386/helper.c (+7 lines)
Lines 3152-3159 Link Here
3152
        nb_xmm_regs = 8 << data64;
3152
        nb_xmm_regs = 8 << data64;
3153
        addr = ptr + 0xa0;
3153
        addr = ptr + 0xa0;
3154
        for(i = 0; i < nb_xmm_regs; i++) {
3154
        for(i = 0; i < nb_xmm_regs; i++) {
3155
#if defined(__i386__) && __GNUC__ >= 4
3156
            env->xmm_regs[i].XMM_L(0) = ldl(addr);
3157
            env->xmm_regs[i].XMM_L(1) = ldl(addr + 4);
3158
            env->xmm_regs[i].XMM_L(2) = ldl(addr + 8);
3159
            env->xmm_regs[i].XMM_L(3) = ldl(addr + 12);
3160
#else
3155
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
3161
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
3156
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
3162
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
3163
#endif
3157
            addr += 16;
3164
            addr += 16;
3158
        }
3165
        }
3159
    }
3166
    }
(-)qemu-0.8.2-orig/target-i386/ops_sse.h (-1 / +7 lines)
Lines 34-39 Link Here
34
#define Q(n) XMM_Q(n)
34
#define Q(n) XMM_Q(n)
35
#define SUFFIX _xmm
35
#define SUFFIX _xmm
36
#endif
36
#endif
37
#if defined(__i386__) && __GNUC__ >= 4
38
#define RegCopy(d, s) __builtin_memcpy(&(d), &(s), sizeof(d))
39
#endif
40
#ifndef RegCopy
41
#define RegCopy(d, s) d = s
42
#endif
37
43
38
void OPPROTO glue(op_psrlw, SUFFIX)(void)
44
void OPPROTO glue(op_psrlw, SUFFIX)(void)
39
{
45
{
Lines 570-576 Link Here
570
    r.W(1) = s->W((order >> 2) & 3);
576
    r.W(1) = s->W((order >> 2) & 3);
571
    r.W(2) = s->W((order >> 4) & 3);
577
    r.W(2) = s->W((order >> 4) & 3);
572
    r.W(3) = s->W((order >> 6) & 3);
578
    r.W(3) = s->W((order >> 6) & 3);
573
    *d = r;
579
    RegCopy(*d, r);
574
}
580
}
575
#else
581
#else
576
void OPPROTO op_shufps(void)
582
void OPPROTO op_shufps(void)
(-)qemu-0.8.2-orig/target-ppc/exec.h (-5 / +1 lines)
Lines 37-47 Link Here
37
#define FT1 (env->ft1)
37
#define FT1 (env->ft1)
38
#define FT2 (env->ft2)
38
#define FT2 (env->ft2)
39
39
40
#if defined (DEBUG_OP)
40
#define RETURN() FORCE_RET()
41
#define RETURN() __asm__ __volatile__("nop");
42
#else
43
#define RETURN() __asm__ __volatile__("");
44
#endif
45
41
46
#include "cpu.h"
42
#include "cpu.h"
47
#include "exec-all.h"
43
#include "exec-all.h"

Return to bug 160627