|
30 | 30 | #include "asm/assembler.inline.hpp"
|
31 | 31 | #include "code/vmreg.hpp"
|
32 | 32 | #include "metaprogramming/enableIf.hpp"
|
33 |
| -#include "nativeInst_riscv.hpp" |
34 | 33 | #include "oops/compressedOops.hpp"
|
35 | 34 | #include "utilities/powerOfTwo.hpp"
|
36 | 35 |
|
|
42 | 41 | class MacroAssembler: public Assembler {
|
43 | 42 |
|
44 | 43 | public:
|
| 44 | + |
45 | 45 | MacroAssembler(CodeBuffer* code) : Assembler(code) {}
|
46 | 46 |
|
47 | 47 | void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod);
|
48 | 48 |
|
49 | 49 | // Alignment
|
50 | 50 | int align(int modulus, int extra_offset = 0);
|
51 | 51 |
|
52 |
| - static inline void assert_alignment(address pc, int alignment = NativeInstruction::instruction_size) { |
| 52 | + static inline void assert_alignment(address pc, int alignment = MacroAssembler::instruction_size) { |
53 | 53 | assert(is_aligned(pc, alignment), "bad alignment");
|
54 | 54 | }
|
55 | 55 |
|
@@ -1232,7 +1232,7 @@ class MacroAssembler: public Assembler {
|
1232 | 1232 |
|
1233 | 1233 | address ic_call(address entry, jint method_index = 0);
|
1234 | 1234 | static int ic_check_size();
|
1235 |
| - int ic_check(int end_alignment = NativeInstruction::instruction_size); |
| 1235 | + int ic_check(int end_alignment = MacroAssembler::instruction_size); |
1236 | 1236 |
|
1237 | 1237 | // Support for memory inc/dec
|
1238 | 1238 | // n.b. increment/decrement calls with an Address destination will
|
@@ -1542,6 +1542,226 @@ class MacroAssembler: public Assembler {
|
1542 | 1542 | public:
|
1543 | 1543 | void lightweight_lock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow);
|
1544 | 1544 | void lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow);
|
| 1545 | + |
| 1546 | +public: |
| 1547 | + enum { |
| 1548 | + // Refer to function emit_trampoline_stub. |
| 1549 | + trampoline_stub_instruction_size = 3 * instruction_size + wordSize, // auipc + ld + jr + target address |
| 1550 | + trampoline_stub_data_offset = 3 * instruction_size, // auipc + ld + jr |
| 1551 | + |
| 1552 | + // movptr |
| 1553 | + movptr1_instruction_size = 6 * instruction_size, // lui, addi, slli, addi, slli, addi. See movptr1(). |
| 1554 | + movptr2_instruction_size = 5 * instruction_size, // lui, lui, slli, add, addi. See movptr2(). |
| 1555 | + load_pc_relative_instruction_size = 2 * instruction_size // auipc, ld |
| 1556 | + }; |
| 1557 | + |
| 1558 | + static bool is_load_pc_relative_at(address branch); |
| 1559 | + static bool is_li16u_at(address instr); |
| 1560 | + |
| 1561 | + static bool is_trampoline_stub_at(address addr) { |
| 1562 | + // Ensure that the stub is exactly |
| 1563 | + // ld t0, L--->auipc + ld |
| 1564 | + // jr t0 |
| 1565 | + // L: |
| 1566 | + |
| 1567 | + // judge inst + register + imm |
| 1568 | + // 1). check the instructions: auipc + ld + jalr |
| 1569 | + // 2). check if auipc[11:7] == t0 and ld[11:7] == t0 and ld[19:15] == t0 && jr[19:15] == t0 |
| 1570 | + // 3). check if the offset in ld[31:20] equals the data_offset |
| 1571 | + assert_cond(addr != nullptr); |
| 1572 | + const int instr_size = instruction_size; |
| 1573 | + if (is_auipc_at(addr) && |
| 1574 | + is_ld_at(addr + instr_size) && |
| 1575 | + is_jalr_at(addr + 2 * instr_size) && |
| 1576 | + (extract_rd(addr) == x5) && |
| 1577 | + (extract_rd(addr + instr_size) == x5) && |
| 1578 | + (extract_rs1(addr + instr_size) == x5) && |
| 1579 | + (extract_rs1(addr + 2 * instr_size) == x5) && |
| 1580 | + (Assembler::extract(Assembler::ld_instr(addr + 4), 31, 20) == trampoline_stub_data_offset)) { |
| 1581 | + return true; |
| 1582 | + } |
| 1583 | + return false; |
| 1584 | + } |
| 1585 | + |
| 1586 | + static bool is_call_at(address instr) { |
| 1587 | + if (is_jal_at(instr) || is_jalr_at(instr)) { |
| 1588 | + return true; |
| 1589 | + } |
| 1590 | + return false; |
| 1591 | + } |
| 1592 | + |
| 1593 | + static bool is_jal_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1101111; } |
| 1594 | + static bool is_jalr_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1100111 && extract_funct3(instr) == 0b000; } |
| 1595 | + static bool is_branch_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1100011; } |
| 1596 | + static bool is_ld_at(address instr) { assert_cond(instr != nullptr); return is_load_at(instr) && extract_funct3(instr) == 0b011; } |
| 1597 | + static bool is_load_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0000011; } |
| 1598 | + static bool is_float_load_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0000111; } |
| 1599 | + static bool is_auipc_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0010111; } |
| 1600 | + static bool is_jump_at(address instr) { assert_cond(instr != nullptr); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); } |
| 1601 | + static bool is_add_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0110011 && extract_funct3(instr) == 0b000; } |
| 1602 | + static bool is_addi_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; } |
| 1603 | + static bool is_addiw_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; } |
| 1604 | + static bool is_addiw_to_zr_at(address instr){ assert_cond(instr != nullptr); return is_addiw_at(instr) && extract_rd(instr) == zr; } |
| 1605 | + static bool is_lui_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0110111; } |
| 1606 | + static bool is_lui_to_zr_at(address instr) { assert_cond(instr != nullptr); return is_lui_at(instr) && extract_rd(instr) == zr; } |
| 1607 | + |
| 1608 | + static bool is_srli_at(address instr) { |
| 1609 | + assert_cond(instr != nullptr); |
| 1610 | + return extract_opcode(instr) == 0b0010011 && |
| 1611 | + extract_funct3(instr) == 0b101 && |
| 1612 | + Assembler::extract(((unsigned*)instr)[0], 31, 26) == 0b000000; |
| 1613 | + } |
| 1614 | + |
| 1615 | + static bool is_slli_shift_at(address instr, uint32_t shift) { |
| 1616 | + assert_cond(instr != nullptr); |
| 1617 | + return (extract_opcode(instr) == 0b0010011 && // opcode field |
| 1618 | + extract_funct3(instr) == 0b001 && // funct3 field, select the type of operation |
| 1619 | + Assembler::extract(Assembler::ld_instr(instr), 25, 20) == shift); // shamt field |
| 1620 | + } |
| 1621 | + |
| 1622 | + static bool is_movptr1_at(address instr); |
| 1623 | + static bool is_movptr2_at(address instr); |
| 1624 | + |
| 1625 | + static bool is_lwu_to_zr(address instr); |
| 1626 | + |
| 1627 | +private: |
| 1628 | + static Register extract_rs1(address instr); |
| 1629 | + static Register extract_rs2(address instr); |
| 1630 | + static Register extract_rd(address instr); |
| 1631 | + static uint32_t extract_opcode(address instr); |
| 1632 | + static uint32_t extract_funct3(address instr); |
| 1633 | + |
| 1634 | + // the instruction sequence of movptr is as below: |
| 1635 | + // lui |
| 1636 | + // addi |
| 1637 | + // slli |
| 1638 | + // addi |
| 1639 | + // slli |
| 1640 | + // addi/jalr/load |
| 1641 | + static bool check_movptr1_data_dependency(address instr) { |
| 1642 | + address lui = instr; |
| 1643 | + address addi1 = lui + instruction_size; |
| 1644 | + address slli1 = addi1 + instruction_size; |
| 1645 | + address addi2 = slli1 + instruction_size; |
| 1646 | + address slli2 = addi2 + instruction_size; |
| 1647 | + address last_instr = slli2 + instruction_size; |
| 1648 | + return extract_rs1(addi1) == extract_rd(lui) && |
| 1649 | + extract_rs1(addi1) == extract_rd(addi1) && |
| 1650 | + extract_rs1(slli1) == extract_rd(addi1) && |
| 1651 | + extract_rs1(slli1) == extract_rd(slli1) && |
| 1652 | + extract_rs1(addi2) == extract_rd(slli1) && |
| 1653 | + extract_rs1(addi2) == extract_rd(addi2) && |
| 1654 | + extract_rs1(slli2) == extract_rd(addi2) && |
| 1655 | + extract_rs1(slli2) == extract_rd(slli2) && |
| 1656 | + extract_rs1(last_instr) == extract_rd(slli2); |
| 1657 | + } |
| 1658 | + |
| 1659 | + // the instruction sequence of movptr2 is as below: |
| 1660 | + // lui |
| 1661 | + // lui |
| 1662 | + // slli |
| 1663 | + // add |
| 1664 | + // addi/jalr/load |
| 1665 | + static bool check_movptr2_data_dependency(address instr) { |
| 1666 | + address lui1 = instr; |
| 1667 | + address lui2 = lui1 + instruction_size; |
| 1668 | + address slli = lui2 + instruction_size; |
| 1669 | + address add = slli + instruction_size; |
| 1670 | + address last_instr = add + instruction_size; |
| 1671 | + return extract_rd(add) == extract_rd(lui2) && |
| 1672 | + extract_rs1(add) == extract_rd(lui2) && |
| 1673 | + extract_rs2(add) == extract_rd(slli) && |
| 1674 | + extract_rs1(slli) == extract_rd(lui1) && |
| 1675 | + extract_rd(slli) == extract_rd(lui1) && |
| 1676 | + extract_rs1(last_instr) == extract_rd(add); |
| 1677 | + } |
| 1678 | + |
| 1679 | + // the instruction sequence of li64 is as below: |
| 1680 | + // lui |
| 1681 | + // addi |
| 1682 | + // slli |
| 1683 | + // addi |
| 1684 | + // slli |
| 1685 | + // addi |
| 1686 | + // slli |
| 1687 | + // addi |
| 1688 | + static bool check_li64_data_dependency(address instr) { |
| 1689 | + address lui = instr; |
| 1690 | + address addi1 = lui + instruction_size; |
| 1691 | + address slli1 = addi1 + instruction_size; |
| 1692 | + address addi2 = slli1 + instruction_size; |
| 1693 | + address slli2 = addi2 + instruction_size; |
| 1694 | + address addi3 = slli2 + instruction_size; |
| 1695 | + address slli3 = addi3 + instruction_size; |
| 1696 | + address addi4 = slli3 + instruction_size; |
| 1697 | + return extract_rs1(addi1) == extract_rd(lui) && |
| 1698 | + extract_rs1(addi1) == extract_rd(addi1) && |
| 1699 | + extract_rs1(slli1) == extract_rd(addi1) && |
| 1700 | + extract_rs1(slli1) == extract_rd(slli1) && |
| 1701 | + extract_rs1(addi2) == extract_rd(slli1) && |
| 1702 | + extract_rs1(addi2) == extract_rd(addi2) && |
| 1703 | + extract_rs1(slli2) == extract_rd(addi2) && |
| 1704 | + extract_rs1(slli2) == extract_rd(slli2) && |
| 1705 | + extract_rs1(addi3) == extract_rd(slli2) && |
| 1706 | + extract_rs1(addi3) == extract_rd(addi3) && |
| 1707 | + extract_rs1(slli3) == extract_rd(addi3) && |
| 1708 | + extract_rs1(slli3) == extract_rd(slli3) && |
| 1709 | + extract_rs1(addi4) == extract_rd(slli3) && |
| 1710 | + extract_rs1(addi4) == extract_rd(addi4); |
| 1711 | + } |
| 1712 | + |
| 1713 | + // the instruction sequence of li16u is as below: |
| 1714 | + // lui |
| 1715 | + // srli |
| 1716 | + static bool check_li16u_data_dependency(address instr) { |
| 1717 | + address lui = instr; |
| 1718 | + address srli = lui + instruction_size; |
| 1719 | + |
| 1720 | + return extract_rs1(srli) == extract_rd(lui) && |
| 1721 | + extract_rs1(srli) == extract_rd(srli); |
| 1722 | + } |
| 1723 | + |
| 1724 | + // the instruction sequence of li32 is as below: |
| 1725 | + // lui |
| 1726 | + // addiw |
| 1727 | + static bool check_li32_data_dependency(address instr) { |
| 1728 | + address lui = instr; |
| 1729 | + address addiw = lui + instruction_size; |
| 1730 | + |
| 1731 | + return extract_rs1(addiw) == extract_rd(lui) && |
| 1732 | + extract_rs1(addiw) == extract_rd(addiw); |
| 1733 | + } |
| 1734 | + |
| 1735 | + // the instruction sequence of pc-relative is as below: |
| 1736 | + // auipc |
| 1737 | + // jalr/addi/load/float_load |
| 1738 | + static bool check_pc_relative_data_dependency(address instr) { |
| 1739 | + address auipc = instr; |
| 1740 | + address last_instr = auipc + instruction_size; |
| 1741 | + |
| 1742 | + return extract_rs1(last_instr) == extract_rd(auipc); |
| 1743 | + } |
| 1744 | + |
| 1745 | + // the instruction sequence of load_label is as below: |
| 1746 | + // auipc |
| 1747 | + // load |
| 1748 | + static bool check_load_pc_relative_data_dependency(address instr) { |
| 1749 | + address auipc = instr; |
| 1750 | + address load = auipc + instruction_size; |
| 1751 | + |
| 1752 | + return extract_rd(load) == extract_rd(auipc) && |
| 1753 | + extract_rs1(load) == extract_rd(load); |
| 1754 | + } |
| 1755 | + |
| 1756 | + static bool is_li32_at(address instr); |
| 1757 | + static bool is_li64_at(address instr); |
| 1758 | + static bool is_pc_relative_at(address branch); |
| 1759 | + |
| 1760 | + static bool is_membar(address addr) { |
| 1761 | + return (Bytes::get_native_u4(addr) & 0x7f) == 0b1111 && extract_funct3(addr) == 0; |
| 1762 | + } |
| 1763 | + static uint32_t get_membar_kind(address addr); |
| 1764 | + static void set_membar_kind(address addr, uint32_t order_kind); |
1545 | 1765 | };
|
1546 | 1766 |
|
1547 | 1767 | #ifdef ASSERT
|
|
0 commit comments