diff options
author | Paul Mackerras <paulus@samba.org> | 2014-09-02 00:35:09 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2014-09-25 09:14:52 -0400 |
commit | c9f6f4ed95d47e3319dedaf8cc31d744ac67fe6f (patch) | |
tree | 9cd74368175420a8af4197833b4e8b598010856d /arch/powerpc/lib | |
parent | cf87c3f6b64791ce5d4c7e591c915065d31a162d (diff) |
powerpc: Implement emulation of string loads and stores
The size field of the op.type word is now the total number of bytes
to be loaded or stored.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/lib')
-rw-r--r-- | arch/powerpc/lib/sstep.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 209a506f8517..54651fc2d412 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -1433,11 +1433,24 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, | |||
1433 | break; | 1433 | break; |
1434 | 1434 | ||
1435 | #endif | 1435 | #endif |
1436 | case 533: /* lswx */ | ||
1437 | op->type = MKOP(LOAD_MULTI, 0, regs->xer & 0x7f); | ||
1438 | break; | ||
1436 | 1439 | ||
1437 | case 534: /* lwbrx */ | 1440 | case 534: /* lwbrx */ |
1438 | op->type = MKOP(LOAD, BYTEREV, 4); | 1441 | op->type = MKOP(LOAD, BYTEREV, 4); |
1439 | break; | 1442 | break; |
1440 | 1443 | ||
1444 | case 597: /* lswi */ | ||
1445 | if (rb == 0) | ||
1446 | rb = 32; /* # bytes to load */ | ||
1447 | op->type = MKOP(LOAD_MULTI, 0, rb); | ||
1448 | op->ea = 0; | ||
1449 | if (ra) | ||
1450 | op->ea = truncate_if_32bit(regs->msr, | ||
1451 | regs->gpr[ra]); | ||
1452 | break; | ||
1453 | |||
1441 | #ifdef CONFIG_PPC_FPU | 1454 | #ifdef CONFIG_PPC_FPU |
1442 | case 535: /* lfsx */ | 1455 | case 535: /* lfsx */ |
1443 | case 567: /* lfsux */ | 1456 | case 567: /* lfsux */ |
@@ -1475,11 +1488,25 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, | |||
1475 | break; | 1488 | break; |
1476 | 1489 | ||
1477 | #endif | 1490 | #endif |
1491 | case 661: /* stswx */ | ||
1492 | op->type = MKOP(STORE_MULTI, 0, regs->xer & 0x7f); | ||
1493 | break; | ||
1494 | |||
1478 | case 662: /* stwbrx */ | 1495 | case 662: /* stwbrx */ |
1479 | op->type = MKOP(STORE, BYTEREV, 4); | 1496 | op->type = MKOP(STORE, BYTEREV, 4); |
1480 | op->val = byterev_4(regs->gpr[rd]); | 1497 | op->val = byterev_4(regs->gpr[rd]); |
1481 | break; | 1498 | break; |
1482 | 1499 | ||
1500 | case 725: | ||
1501 | if (rb == 0) | ||
1502 | rb = 32; /* # bytes to store */ | ||
1503 | op->type = MKOP(STORE_MULTI, 0, rb); | ||
1504 | op->ea = 0; | ||
1505 | if (ra) | ||
1506 | op->ea = truncate_if_32bit(regs->msr, | ||
1507 | regs->gpr[ra]); | ||
1508 | break; | ||
1509 | |||
1483 | case 790: /* lhbrx */ | 1510 | case 790: /* lhbrx */ |
1484 | op->type = MKOP(LOAD, BYTEREV, 2); | 1511 | op->type = MKOP(LOAD, BYTEREV, 2); |
1485 | break; | 1512 | break; |
@@ -1553,15 +1580,14 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, | |||
1553 | break; | 1580 | break; |
1554 | 1581 | ||
1555 | case 46: /* lmw */ | 1582 | case 46: /* lmw */ |
1556 | ra = (instr >> 16) & 0x1f; | ||
1557 | if (ra >= rd) | 1583 | if (ra >= rd) |
1558 | break; /* invalid form, ra in range to load */ | 1584 | break; /* invalid form, ra in range to load */ |
1559 | op->type = MKOP(LOAD_MULTI, 0, 4); | 1585 | op->type = MKOP(LOAD_MULTI, 0, 4 * (32 - rd)); |
1560 | op->ea = dform_ea(instr, regs); | 1586 | op->ea = dform_ea(instr, regs); |
1561 | break; | 1587 | break; |
1562 | 1588 | ||
1563 | case 47: /* stmw */ | 1589 | case 47: /* stmw */ |
1564 | op->type = MKOP(STORE_MULTI, 0, 4); | 1590 | op->type = MKOP(STORE_MULTI, 0, 4 * (32 - rd)); |
1565 | op->ea = dform_ea(instr, regs); | 1591 | op->ea = dform_ea(instr, regs); |
1566 | break; | 1592 | break; |
1567 | 1593 | ||
@@ -1744,7 +1770,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1744 | int r, err, size; | 1770 | int r, err, size; |
1745 | unsigned long val; | 1771 | unsigned long val; |
1746 | unsigned int cr; | 1772 | unsigned int cr; |
1747 | int rd; | 1773 | int i, rd, nb; |
1748 | 1774 | ||
1749 | r = analyse_instr(&op, regs, instr); | 1775 | r = analyse_instr(&op, regs, instr); |
1750 | if (r != 0) | 1776 | if (r != 0) |
@@ -1866,12 +1892,18 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1866 | if (regs->msr & MSR_LE) | 1892 | if (regs->msr & MSR_LE) |
1867 | return 0; | 1893 | return 0; |
1868 | rd = op.reg; | 1894 | rd = op.reg; |
1869 | do { | 1895 | for (i = 0; i < size; i += 4) { |
1870 | err = read_mem(®s->gpr[rd], op.ea, 4, regs); | 1896 | nb = size - i; |
1897 | if (nb > 4) | ||
1898 | nb = 4; | ||
1899 | err = read_mem(®s->gpr[rd], op.ea, nb, regs); | ||
1871 | if (err) | 1900 | if (err) |
1872 | return 0; | 1901 | return 0; |
1902 | if (nb < 4) /* left-justify last bytes */ | ||
1903 | regs->gpr[rd] <<= 32 - 8 * nb; | ||
1873 | op.ea += 4; | 1904 | op.ea += 4; |
1874 | } while (++rd < 32); | 1905 | ++rd; |
1906 | } | ||
1875 | goto instr_done; | 1907 | goto instr_done; |
1876 | 1908 | ||
1877 | case STORE: | 1909 | case STORE: |
@@ -1914,12 +1946,19 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1914 | if (regs->msr & MSR_LE) | 1946 | if (regs->msr & MSR_LE) |
1915 | return 0; | 1947 | return 0; |
1916 | rd = op.reg; | 1948 | rd = op.reg; |
1917 | do { | 1949 | for (i = 0; i < size; i += 4) { |
1918 | err = write_mem(regs->gpr[rd], op.ea, 4, regs); | 1950 | val = regs->gpr[rd]; |
1951 | nb = size - i; | ||
1952 | if (nb > 4) | ||
1953 | nb = 4; | ||
1954 | else | ||
1955 | val >>= 32 - 8 * nb; | ||
1956 | err = write_mem(val, op.ea, nb, regs); | ||
1919 | if (err) | 1957 | if (err) |
1920 | return 0; | 1958 | return 0; |
1921 | op.ea += 4; | 1959 | op.ea += 4; |
1922 | } while (++rd < 32); | 1960 | ++rd; |
1961 | } | ||
1923 | goto instr_done; | 1962 | goto instr_done; |
1924 | 1963 | ||
1925 | case MFMSR: | 1964 | case MFMSR: |