| 1788 | } |
| 1789 | |
| 1790 | size_t ArmCommonArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, |
| 1791 | uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) |
| 1792 | { |
| 1793 | switch (op) |
| 1794 | { |
| 1795 | case LLIL_SBB: |
| 1796 | switch (flag) |
| 1797 | { |
| 1798 | case IL_FLAG_C: |
| 1799 | // Copied from arm64 |
| 1800 | // r u< a || (r == a && flag_c) |
| 1801 | return il.Or(0, |
| 1802 | il.CompareUnsignedLessThan(size, |
| 1803 | il.GetExprForRegisterOrConstantOperation(op, size, operands, operandCount), |
| 1804 | il.GetExprForRegisterOrConstant(operands[0], size)), |
| 1805 | il.And(0, |
| 1806 | il.CompareEqual(size, |
| 1807 | il.GetExprForRegisterOrConstantOperation(op, size, operands, operandCount), |
| 1808 | il.GetExprForRegisterOrConstant(operands[0], size)), |
| 1809 | il.Flag(IL_FLAG_C))); |
| 1810 | case IL_FLAG_V: |
| 1811 | return il.CompareEqual(0, |
| 1812 | il.CompareSignedLessThan(size, |
| 1813 | il.GetExprForRegisterOrConstantOperation(op, size, operands, operandCount), |
| 1814 | il.GetExprForRegisterOrConstant(operands[0], size)), |
| 1815 | il.CompareEqual(size, |
| 1816 | il.GetExprForRegisterOrConstant(operands[0], size), |
| 1817 | il.Const(size, 0))); |
| 1818 | } |
| 1819 | break; |
| 1820 | case LLIL_LSR: |
| 1821 | switch (flag) |
| 1822 | { |
| 1823 | case IL_FLAG_C: |
| 1824 | /* |
| 1825 | * The last bit spilled out of the register by the shift lands in the carry flag. |
| 1826 | * For example, `((u32)1) >> 1` sets the carry flag, `((u32)2) >> 1` clears it. |
| 1827 | * We can simplify this to a bit test: `x & (1 << (shift_amt - 1))` |
| 1828 | */ |
| 1829 | return il.TestBit(0, |
| 1830 | il.GetExprForRegisterOrConstant(operands[0], size), |
| 1831 | il.Sub(size, il.GetExprForRegisterOrConstant(operands[1], size), il.Const(size, 1))); |
| 1832 | } |
| 1833 | break; |
| 1834 | case LLIL_LSL: |
| 1835 | switch (flag) |
| 1836 | { |
| 1837 | case IL_FLAG_C: |
| 1838 | /* |
| 1839 | * Just like the carry flag for LSR, this is the last bit spilled out of the register. |
| 1840 | * Also equivalent to a bit test, just indexing from the most significant bit rather |
| 1841 | * than the least. |
| 1842 | */ |
| 1843 | return il.TestBit(0, |
| 1844 | il.GetExprForRegisterOrConstant(operands[0], size), |
| 1845 | il.Sub(size, il.Const(size, 8 * size), il.GetExprForRegisterOrConstant(operands[1], size))); |
| 1846 | } |
| 1847 | default: |
nothing calls this directly
no test coverage detected