| @@ -1648,18 +1648,115 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 1647 unmodified lines |
| 1648 | asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, first_regset_register, &ops[0], &offset, 0, preincrement, op0_exclam, extra_register_bit, load); | 1648 | asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, first_regset_register, &ops[0], &offset, 0, preincrement, op0_exclam, extra_register_bit, load); |
| 1649 | } | 1649 | } |
| 1650 | | 1650 | |
| | 1651 | #define VMOV_FRACTIONAL_DIGITS 7 |
| | 1652 | #define VMOV_ONE 10000000 /* pow(10, VMOV_FRACTIONAL_DIGITS) */ |
| | 1653 | |
| | 1654 | static uint32_t vmov_parse_fractional_part(const char* s) |
| | 1655 | { |
| | 1656 | uint32_t result = 0; |
| | 1657 | int i; |
| | 1658 | for (i = 0; i < VMOV_FRACTIONAL_DIGITS; ++i) { |
| | 1659 | char c = *s; |
| | 1660 | result *= 10; |
| | 1661 | if (c >= '0' && c <= '9') { |
| | 1662 | result += (c - '0'); |
| | 1663 | ++s; |
| | 1664 | } |
| | 1665 | } |
| | 1666 | if (*s) |
| | 1667 | expect("decimal numeral"); |
| | 1668 | return result; |
| | 1669 | } |
| | 1670 | |
| | 1671 | static int vmov_linear_approx_index(uint32_t beginning, uint32_t end, uint32_t value) |
| | 1672 | { |
| | 1673 | int i; |
| | 1674 | uint32_t k; |
| | 1675 | uint32_t xvalue; |
| | 1676 | |
| | 1677 | k = (end - beginning)/16; |
| | 1678 | for (xvalue = beginning, i = 0; i < 16; ++i, xvalue += k) { |
| | 1679 | if (value == xvalue) |
| | 1680 | return i; |
| | 1681 | } |
| | 1682 | //assert(0); |
| | 1683 | return -1; |
| | 1684 | } |
| | 1685 | |
| | 1686 | static uint32_t vmov_parse_immediate_value() { |
| | 1687 | uint32_t value; |
| | 1688 | unsigned long integral_value; |
| | 1689 | const char *p; |
| | 1690 | |
| | 1691 | if (tok != TOK_PPNUM) { |
| | 1692 | expect("immediate value"); |
| | 1693 | return 0; |
| | 1694 | } |
| | 1695 | p = tokc.str.data; |
| | 1696 | errno = 0; |
| | 1697 | integral_value = strtoul(p, (char **)&p, 0); |
| | 1698 | |
| | 1699 | if (errno || integral_value >= 32) { |
| | 1700 | tcc_error("invalid floating-point immediate value"); |
| | 1701 | return 0; |
| | 1702 | } |
| | 1703 | |
| | 1704 | value = (uint32_t) integral_value * VMOV_ONE; |
| | 1705 | if (*p == '.') { |
| | 1706 | ++p; |
| | 1707 | value += vmov_parse_fractional_part(p); |
| | 1708 | } |
| | 1709 | next(); |
| | 1710 | return value; |
| | 1711 | } |
| | 1712 | |
| | 1713 | static uint8_t vmov_encode_immediate_value(uint32_t value) |
| | 1714 | { |
| | 1715 | uint32_t limit; |
| | 1716 | uint32_t end = 0; |
| | 1717 | uint32_t beginning = 0; |
| | 1718 | int r = -1; |
| | 1719 | int n; |
| | 1720 | int i; |
| | 1721 | |
| | 1722 | limit = 32 * VMOV_ONE; |
| | 1723 | for (i = 0; i < 8; ++i) { |
| | 1724 | if (value < limit) { |
| | 1725 | end = limit; |
| | 1726 | limit >>= 1; |
| | 1727 | beginning = limit; |
| | 1728 | r = i; |
| | 1729 | } else |
| | 1730 | limit >>= 1; |
| | 1731 | } |
| | 1732 | if (r == -1 || value < beginning || value > end) { |
| | 1733 | tcc_error("invalid decimal number for vmov: %d", value); |
| | 1734 | return 0; |
| | 1735 | } |
| | 1736 | n = vmov_linear_approx_index(beginning, end, value); |
| | 1737 | return n | (((3 - r) & 0x7) << 4); |
| | 1738 | } |
| | 1739 | |
| 1651 | // Not standalone. | 1740 | // Not standalone. |
| 1652 | static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s1, int token, uint8_t coprocessor, uint8_t CRd) { | 1741 | static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s1, int token, uint8_t coprocessor, uint8_t CRd) { |
| 1653 | uint8_t opcode1 = 0; | 1742 | uint8_t opcode1 = 0; |
| 1654 | uint8_t opcode2 = 0; | 1743 | uint8_t opcode2 = 0; |
| 1655 | uint8_t operands[3] = {0, 0, 0}; | 1744 | uint8_t operands[3] = {0, 0, 0}; |
| 1656 | Operand operand; | 1745 | uint32_t immediate_value = 0; |
| | 1746 | int op_minus = 0; |
| | 1747 | uint8_t code; |
| 1657 | | 1748 | |
| 1658 | operands[0] = CRd; | 1749 | operands[0] = CRd; |
| 1659 | | 1750 | |
| 1660 | parse_operand(s1, &operand); | 1751 | if (tok == '#' || tok == '$') { |
| 1661 | if (operand.type != OP_IM8 && operand.type != OP_IM8N) { | 1752 | next(); |
| 1662 | expect("Immediate value"); | 1753 | if (tok == '-') { |
| | 1754 | op_minus = 1; |
| | 1755 | next(); |
| | 1756 | } |
| | 1757 | immediate_value = vmov_parse_immediate_value(); |
| | 1758 | } else { |
| | 1759 | expect("'#'"); |
| 1663 | return; | 1760 | return; |
| 1664 | } | 1761 | } |
| 1665 | | 1762 | |
| @@ -1669,7 +1766,7 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 3 unmodified lines |
| 1669 | case TOK_ASM_vcmpeq_f64: | 1766 | case TOK_ASM_vcmpeq_f64: |
| 1670 | opcode2 = 2; | 1767 | opcode2 = 2; |
| 1671 | operands[1] = 5; | 1768 | operands[1] = 5; |
| 1672 | if (operand.e.v) { | 1769 | if (immediate_value) { |
| 1673 | expect("Immediate value 0"); | 1770 | expect("Immediate value 0"); |
| 1674 | return; | 1771 | return; |
| 1675 | } | 1772 | } |
| @@ -1678,11 +1775,22 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 2 unmodified lines |
| 1678 | case TOK_ASM_vcmpeeq_f64: | 1775 | case TOK_ASM_vcmpeeq_f64: |
| 1679 | opcode2 = 6; | 1776 | opcode2 = 6; |
| 1680 | operands[1] = 5; | 1777 | operands[1] = 5; |
| 1681 | if (operand.e.v) { | 1778 | if (immediate_value) { |
| 1682 | expect("Immediate value 0"); | 1779 | expect("Immediate value 0"); |
| 1683 | return; | 1780 | return; |
| 1684 | } | 1781 | } |
| 1685 | break; | 1782 | break; |
| | 1783 | case TOK_ASM_vmoveq_f32: |
| | 1784 | case TOK_ASM_vmoveq_f64: |
| | 1785 | opcode2 = 0; |
| | 1786 | if (op_minus) |
| | 1787 | operands[1] = 0x8; |
| | 1788 | else |
| | 1789 | operands[1] = 0x0; |
| | 1790 | code = vmov_encode_immediate_value(immediate_value); |
| | 1791 | operands[1] |= code >> 4; |
| | 1792 | operands[2] = code & 0xF; |
| | 1793 | break; |
| 1686 | default: | 1794 | default: |
| 1687 | expect("known floating point with immediate instruction"); | 1795 | expect("known floating point with immediate instruction"); |
| 1688 | return; | 1796 | return; |
| @@ -1749,6 +1857,7 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 60 unmodified lines |
| 1749 | case TOK_ASM_vsqrteq_f64: | 1857 | case TOK_ASM_vsqrteq_f64: |
| 1750 | case TOK_ASM_vcmpeq_f64: | 1858 | case TOK_ASM_vcmpeq_f64: |
| 1751 | case TOK_ASM_vcmpeeq_f64: | 1859 | case TOK_ASM_vcmpeeq_f64: |
| | 1860 | case TOK_ASM_vmoveq_f64: |
| 1752 | coprocessor = CP_DOUBLE_PRECISION_FLOAT; | 1861 | coprocessor = CP_DOUBLE_PRECISION_FLOAT; |
| 1753 | } | 1862 | } |
| 1754 | | 1863 | |
| @@ -1881,6 +1990,13 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 126 unmodified lines |
| 1881 | operands[1] = 4; | 1990 | operands[1] = 4; |
| 1882 | operand_1_register = 0; | 1991 | operand_1_register = 0; |
| 1883 | break; | 1992 | break; |
| | 1993 | case TOK_ASM_vmoveq_f32: |
| | 1994 | case TOK_ASM_vmoveq_f64: |
| | 1995 | opcode1 = 11; // "Other" instruction |
| | 1996 | opcode2 = 2; |
| | 1997 | operands[1] = 0; |
| | 1998 | operand_1_register = 0; |
| | 1999 | break; |
| 1884 | // TODO: vcvt; vcvtr | 2000 | // TODO: vcvt; vcvtr |
| 1885 | default: | 2001 | default: |
| 1886 | expect("known floating point instruction"); | 2002 | expect("known floating point instruction"); |
| @@ -2284,6 +2400,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 397 unmodified lines |
| 2284 | case TOK_ASM_vsqrteq_f32: | 2400 | case TOK_ASM_vsqrteq_f32: |
| 2285 | case TOK_ASM_vcmpeq_f32: | 2401 | case TOK_ASM_vcmpeq_f32: |
| 2286 | case TOK_ASM_vcmpeeq_f32: | 2402 | case TOK_ASM_vcmpeeq_f32: |
| | 2403 | case TOK_ASM_vmoveq_f32: |
| 2287 | case TOK_ASM_vmlaeq_f64: | 2404 | case TOK_ASM_vmlaeq_f64: |
| 2288 | case TOK_ASM_vmlseq_f64: | 2405 | case TOK_ASM_vmlseq_f64: |
| 2289 | case TOK_ASM_vnmlseq_f64: | 2406 | case TOK_ASM_vnmlseq_f64: |
| @@ -2298,6 +2415,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 8 unmodified lines |
| 2298 | case TOK_ASM_vsqrteq_f64: | 2415 | case TOK_ASM_vsqrteq_f64: |
| 2299 | case TOK_ASM_vcmpeq_f64: | 2416 | case TOK_ASM_vcmpeq_f64: |
| 2300 | case TOK_ASM_vcmpeeq_f64: | 2417 | case TOK_ASM_vcmpeeq_f64: |
| | 2418 | case TOK_ASM_vmoveq_f64: |
| 2301 | asm_floating_point_data_processing_opcode(s1, token); | 2419 | asm_floating_point_data_processing_opcode(s1, token); |
| 2302 | return; | 2420 | return; |
| 2303 | | 2421 | |