| @@ -1648,18 +1648,115 @@ static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int toke · 1647 unmodified lines |
| 1648 | 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 | 1740 | // Not standalone. |
| 1652 | 1741 | static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s1, int token, uint8_t coprocessor, uint8_t CRd) { |
| 1653 | 1742 | uint8_t opcode1 = 0; |
| 1654 | 1743 | uint8_t opcode2 = 0; |
| 1655 | 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 | 1749 | operands[0] = CRd; |
| 1659 | 1750 | |
| 1660 | | − parse_operand(s1, &operand); |
| 1661 | | − if (operand.type != OP_IM8 && operand.type != OP_IM8N) { |
| 1662 | | − expect("Immediate value"); |
| 1751 | + if (tok == '#' || tok == '$') { |
| 1752 | + next(); |
| 1753 | + if (tok == '-') { |
| 1754 | + op_minus = 1; |
| 1755 | + next(); |
| 1756 | + } |
| 1757 | + immediate_value = vmov_parse_immediate_value(); |
| 1758 | + } else { |
| 1759 | + expect("'#'"); |
| 1663 | 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 | 1766 | case TOK_ASM_vcmpeq_f64: |
| 1670 | 1767 | opcode2 = 2; |
| 1671 | 1768 | operands[1] = 5; |
| 1672 | | − if (operand.e.v) { |
| 1769 | + if (immediate_value) { |
| 1673 | 1770 | expect("Immediate value 0"); |
| 1674 | 1771 | return; |
| 1675 | 1772 | } |
| @@ -1678,11 +1775,22 @@ static void asm_floating_point_immediate_data_processing_opcode_tail(TCCState *s · 2 unmodified lines |
| 1678 | 1775 | case TOK_ASM_vcmpeeq_f64: |
| 1679 | 1776 | opcode2 = 6; |
| 1680 | 1777 | operands[1] = 5; |
| 1681 | | − if (operand.e.v) { |
| 1778 | + if (immediate_value) { |
| 1682 | 1779 | expect("Immediate value 0"); |
| 1683 | 1780 | return; |
| 1684 | 1781 | } |
| 1685 | 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 | 1794 | default: |
| 1687 | 1795 | expect("known floating point with immediate instruction"); |
| 1688 | 1796 | return; |
| @@ -1749,6 +1857,7 @@ static void asm_floating_point_data_processing_opcode(TCCState *s1, int token) { · 60 unmodified lines |
| 1749 | 1857 | case TOK_ASM_vsqrteq_f64: |
| 1750 | 1858 | case TOK_ASM_vcmpeq_f64: |
| 1751 | 1859 | case TOK_ASM_vcmpeeq_f64: |
| 1860 | + case TOK_ASM_vmoveq_f64: |
| 1752 | 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 | 1990 | operands[1] = 4; |
| 1882 | 1991 | operand_1_register = 0; |
| 1883 | 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 | 2000 | // TODO: vcvt; vcvtr |
| 1885 | 2001 | default: |
| 1886 | 2002 | expect("known floating point instruction"); |
| @@ -2284,6 +2400,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 397 unmodified lines |
| 2284 | 2400 | case TOK_ASM_vsqrteq_f32: |
| 2285 | 2401 | case TOK_ASM_vcmpeq_f32: |
| 2286 | 2402 | case TOK_ASM_vcmpeeq_f32: |
| 2403 | + case TOK_ASM_vmoveq_f32: |
| 2287 | 2404 | case TOK_ASM_vmlaeq_f64: |
| 2288 | 2405 | case TOK_ASM_vmlseq_f64: |
| 2289 | 2406 | case TOK_ASM_vnmlseq_f64: |
| @@ -2298,6 +2415,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 8 unmodified lines |
| 2298 | 2415 | case TOK_ASM_vsqrteq_f64: |
| 2299 | 2416 | case TOK_ASM_vcmpeq_f64: |
| 2300 | 2417 | case TOK_ASM_vcmpeeq_f64: |
| 2418 | + case TOK_ASM_vmoveq_f64: |
| 2301 | 2419 | asm_floating_point_data_processing_opcode(s1, token); |
| 2302 | 2420 | return; |
| 2303 | 2421 | |