Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <setjmp.h> | 5 #include <setjmp.h> |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #if defined(TARGET_ARCH_ARM64) | 9 #if defined(TARGET_ARCH_ARM64) |
| 10 | 10 |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 932 } | 932 } |
| 933 | 933 |
| 934 | 934 |
| 935 // Calculate and set the Negative and Zero flags. | 935 // Calculate and set the Negative and Zero flags. |
| 936 void Simulator::SetNZFlagsW(int32_t val) { | 936 void Simulator::SetNZFlagsW(int32_t val) { |
| 937 n_flag_ = (val < 0); | 937 n_flag_ = (val < 0); |
| 938 z_flag_ = (val == 0); | 938 z_flag_ = (val == 0); |
| 939 } | 939 } |
| 940 | 940 |
| 941 | 941 |
| 942 // Calculate C flag value for additions. | 942 // Calculate C flag value for additions (and subtractions with adjusted args). |
| 943 bool Simulator::CarryFromW(int32_t left, int32_t right) { | 943 bool Simulator::CarryFromW(int32_t left, int32_t right, int32_t carry) { |
| 944 uint32_t uleft = static_cast<uint32_t>(left); | 944 uint64_t uleft = static_cast<uint32_t>(left); |
| 945 uint32_t uright = static_cast<uint32_t>(right); | 945 uint64_t uright = static_cast<uint32_t>(right); |
| 946 uint32_t urest = 0xffffffffU - uleft; | 946 uint64_t ucarry = static_cast<uint32_t>(carry); |
| 947 | 947 return ((uleft + uright + ucarry) >> 32) != 0; |
| 948 return (uright > urest); | |
| 949 } | 948 } |
| 950 | 949 |
| 951 | 950 |
| 952 // Calculate C flag value for subtractions. | 951 // Calculate V flag value for additions (and subtractions with adjusted args). |
| 953 bool Simulator::BorrowFromW(int32_t left, int32_t right) { | 952 bool Simulator::OverflowFromW(int32_t left, int32_t right, int32_t carry) { |
| 954 uint32_t uleft = static_cast<uint32_t>(left); | 953 int64_t result = static_cast<int64_t>(left) + right + carry; |
| 955 uint32_t uright = static_cast<uint32_t>(right); | 954 return (result >> 31) != (result >> 32); |
|
zra
2014/10/07 16:27:50
This is much nicer =)
| |
| 956 | |
| 957 return (uright > uleft); | |
| 958 } | |
| 959 | |
| 960 | |
| 961 // Calculate V flag value for additions and subtractions. | |
| 962 bool Simulator::OverflowFromW(int32_t alu_out, | |
| 963 int32_t left, int32_t right, bool addition) { | |
| 964 bool overflow; | |
| 965 if (addition) { | |
| 966 // operands have the same sign | |
| 967 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) | |
| 968 // and operands and result have different sign | |
| 969 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 970 } else { | |
| 971 // operands have different signs | |
| 972 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) | |
| 973 // and first operand and result have different signs | |
| 974 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 975 } | |
| 976 return overflow; | |
| 977 } | 955 } |
| 978 | 956 |
| 979 | 957 |
| 980 // Calculate and set the Negative and Zero flags. | 958 // Calculate and set the Negative and Zero flags. |
| 981 void Simulator::SetNZFlagsX(int64_t val) { | 959 void Simulator::SetNZFlagsX(int64_t val) { |
| 982 n_flag_ = (val < 0); | 960 n_flag_ = (val < 0); |
| 983 z_flag_ = (val == 0); | 961 z_flag_ = (val == 0); |
| 984 } | 962 } |
| 985 | 963 |
| 986 | 964 |
| 987 // Calculate C flag value for additions. | 965 // Calculate C flag value for additions and subtractions. |
| 988 bool Simulator::CarryFromX(int64_t left, int64_t right) { | 966 bool Simulator::CarryFromX(int64_t alu_out, |
| 989 uint64_t uleft = static_cast<uint64_t>(left); | 967 int64_t left, int64_t right, bool addition) { |
| 990 uint64_t uright = static_cast<uint64_t>(right); | 968 if (addition) { |
| 991 uint64_t urest = 0xffffffffffffffffULL - uleft; | 969 return (((left & right) | ((left | right) & ~alu_out)) >> 63) != 0; |
| 992 | 970 } else { |
| 993 return (uright > urest); | 971 return (((~left & right) | ((~left | right) & alu_out)) >> 63) == 0; |
| 994 } | 972 } |
| 995 | |
| 996 | |
| 997 // Calculate C flag value for subtractions. | |
| 998 bool Simulator::BorrowFromX(int64_t left, int64_t right) { | |
| 999 uint64_t uleft = static_cast<uint64_t>(left); | |
| 1000 uint64_t uright = static_cast<uint64_t>(right); | |
| 1001 | |
| 1002 return (uright > uleft); | |
| 1003 } | 973 } |
| 1004 | 974 |
| 1005 | 975 |
| 1006 // Calculate V flag value for additions and subtractions. | 976 // Calculate V flag value for additions and subtractions. |
| 1007 bool Simulator::OverflowFromX(int64_t alu_out, | 977 bool Simulator::OverflowFromX(int64_t alu_out, |
| 1008 int64_t left, int64_t right, bool addition) { | 978 int64_t left, int64_t right, bool addition) { |
| 1009 bool overflow; | |
| 1010 if (addition) { | 979 if (addition) { |
| 1011 // operands have the same sign | 980 return (((alu_out ^ left) & (alu_out ^ right)) >> 63) != 0; |
| 1012 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) | |
| 1013 // and operands and result have different sign | |
| 1014 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 1015 } else { | 981 } else { |
| 1016 // operands have different signs | 982 return (((left ^ right) & (alu_out ^ left)) >> 63) != 0; |
| 1017 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) | |
| 1018 // and first operand and result have different signs | |
| 1019 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 1020 } | 983 } |
| 1021 return overflow; | |
| 1022 } | 984 } |
| 1023 | 985 |
| 1024 | 986 |
| 1025 // Set the Carry flag. | 987 // Set the Carry flag. |
| 1026 void Simulator::SetCFlag(bool val) { | 988 void Simulator::SetCFlag(bool val) { |
| 1027 c_flag_ = val; | 989 c_flag_ = val; |
| 1028 } | 990 } |
| 1029 | 991 |
| 1030 | 992 |
| 1031 // Set the oVerflow flag. | 993 // Set the oVerflow flag. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1072 UnimplementedInstruction(instr); | 1034 UnimplementedInstruction(instr); |
| 1073 } | 1035 } |
| 1074 } else { | 1036 } else { |
| 1075 // Dest is 32 bits, but shift is more than 32. | 1037 // Dest is 32 bits, but shift is more than 32. |
| 1076 UnimplementedInstruction(instr); | 1038 UnimplementedInstruction(instr); |
| 1077 } | 1039 } |
| 1078 } | 1040 } |
| 1079 | 1041 |
| 1080 | 1042 |
| 1081 void Simulator::DecodeAddSubImm(Instr* instr) { | 1043 void Simulator::DecodeAddSubImm(Instr* instr) { |
| 1082 bool addition = (instr->Bit(30) == 0); | 1044 const bool addition = (instr->Bit(30) == 0); |
| 1083 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s"); | 1045 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s"); |
| 1084 // Format(instr, "subi'sf's 'rd, 'rn, 'imm12s"); | 1046 // Format(instr, "subi'sf's 'rd, 'rn, 'imm12s"); |
| 1085 const Register rd = instr->RdField(); | 1047 const Register rd = instr->RdField(); |
| 1086 const Register rn = instr->RnField(); | 1048 const Register rn = instr->RnField(); |
| 1087 const uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12) | 1049 uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12) |
| 1088 : (instr->Imm12Field()); | 1050 : (instr->Imm12Field()); |
| 1089 if (instr->SFField()) { | 1051 if (instr->SFField()) { |
| 1090 // 64-bit add. | 1052 // 64-bit add. |
| 1091 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1053 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 1092 const int64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm); | 1054 const int64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm); |
| 1093 set_register(instr, rd, alu_out, instr->RdMode()); | 1055 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1094 if (instr->HasS()) { | 1056 if (instr->HasS()) { |
| 1095 SetNZFlagsX(alu_out); | 1057 SetNZFlagsX(alu_out); |
| 1096 if (addition) { | 1058 SetCFlag(CarryFromX(alu_out, rn_val, imm, addition)); |
| 1097 SetCFlag(CarryFromX(rn_val, imm)); | |
| 1098 } else { | |
| 1099 SetCFlag(!BorrowFromX(rn_val, imm)); | |
| 1100 } | |
| 1101 SetVFlag(OverflowFromX(alu_out, rn_val, imm, addition)); | 1059 SetVFlag(OverflowFromX(alu_out, rn_val, imm, addition)); |
| 1102 } | 1060 } |
| 1103 } else { | 1061 } else { |
| 1104 // 32-bit add. | 1062 // 32-bit add. |
| 1105 const int32_t rn_val = get_wregister(rn, instr->RnMode()); | 1063 const int32_t rn_val = get_wregister(rn, instr->RnMode()); |
| 1106 const int32_t alu_out = addition ? (rn_val + imm) : (rn_val - imm); | 1064 int32_t carry_in = 0; |
| 1065 if (!addition) { | |
| 1066 carry_in = 1; | |
| 1067 imm = ~imm; | |
| 1068 } | |
| 1069 const int32_t alu_out = rn_val + imm + carry_in; | |
| 1107 set_wregister(rd, alu_out, instr->RdMode()); | 1070 set_wregister(rd, alu_out, instr->RdMode()); |
| 1108 if (instr->HasS()) { | 1071 if (instr->HasS()) { |
| 1109 SetNZFlagsW(alu_out); | 1072 SetNZFlagsW(alu_out); |
| 1110 if (addition) { | 1073 SetCFlag(CarryFromW(rn_val, imm, carry_in)); |
| 1111 SetCFlag(CarryFromW(rn_val, imm)); | 1074 SetVFlag(OverflowFromW(rn_val, imm, carry_in)); |
| 1112 } else { | |
| 1113 SetCFlag(!BorrowFromW(rn_val, imm)); | |
| 1114 } | |
| 1115 SetVFlag(OverflowFromW(alu_out, rn_val, imm, addition)); | |
| 1116 } | 1075 } |
| 1117 } | 1076 } |
| 1118 } | 1077 } |
| 1119 | 1078 |
| 1120 | 1079 |
| 1121 void Simulator::DecodeLogicalImm(Instr* instr) { | 1080 void Simulator::DecodeLogicalImm(Instr* instr) { |
| 1122 const int op = instr->Bits(29, 2); | 1081 const int op = instr->Bits(29, 2); |
| 1123 const bool set_flags = op == 3; | 1082 const bool set_flags = op == 3; |
| 1124 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0)) | 1083 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0)) |
| 1125 ? kWRegSizeInBits : kXRegSizeInBits; | 1084 ? kWRegSizeInBits : kXRegSizeInBits; |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1840 return ExtendOperand(size, rm_val, extend_type, shift_amount); | 1799 return ExtendOperand(size, rm_val, extend_type, shift_amount); |
| 1841 } | 1800 } |
| 1842 UNREACHABLE(); | 1801 UNREACHABLE(); |
| 1843 return -1; | 1802 return -1; |
| 1844 } | 1803 } |
| 1845 | 1804 |
| 1846 | 1805 |
| 1847 void Simulator::DecodeAddSubShiftExt(Instr* instr) { | 1806 void Simulator::DecodeAddSubShiftExt(Instr* instr) { |
| 1848 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); | 1807 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); |
| 1849 // also, sub, cmp, etc. | 1808 // also, sub, cmp, etc. |
| 1850 const bool subtract = instr->Bit(30) == 1; | 1809 const bool addition = (instr->Bit(30) == 0); |
| 1851 const Register rd = instr->RdField(); | 1810 const Register rd = instr->RdField(); |
| 1852 const Register rn = instr->RnField(); | 1811 const Register rn = instr->RnField(); |
| 1853 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 1812 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
| 1854 if (instr->SFField()) { | 1813 if (instr->SFField()) { |
| 1855 // 64-bit add. | 1814 // 64-bit add. |
| 1856 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1815 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 1857 int64_t alu_out = 0; | 1816 const int64_t alu_out = rn_val + (addition ? rm_val : -rm_val); |
| 1858 if (subtract) { | |
| 1859 alu_out = rn_val - rm_val; | |
| 1860 } else { | |
| 1861 alu_out = rn_val + rm_val; | |
| 1862 } | |
| 1863 set_register(instr, rd, alu_out, instr->RdMode()); | 1817 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1864 if (instr->HasS()) { | 1818 if (instr->HasS()) { |
| 1865 SetNZFlagsX(alu_out); | 1819 SetNZFlagsX(alu_out); |
| 1866 if (subtract) { | 1820 SetCFlag(CarryFromX(alu_out, rn_val, rm_val, addition)); |
| 1867 SetCFlag(!BorrowFromX(rn_val, rm_val)); | 1821 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, addition)); |
| 1868 } else { | |
| 1869 SetCFlag(CarryFromX(rn_val, rm_val)); | |
| 1870 } | |
| 1871 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, !subtract)); | |
| 1872 } | 1822 } |
| 1873 } else { | 1823 } else { |
| 1874 // 32-bit add. | 1824 // 32-bit add. |
| 1875 const int32_t rn_val = get_wregister(rn, instr->RnMode()); | 1825 const int32_t rn_val = get_wregister(rn, instr->RnMode()); |
| 1876 const int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask); | 1826 int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask); |
| 1877 int32_t alu_out = 0; | 1827 int32_t carry_in = 0; |
| 1878 if (subtract) { | 1828 if (!addition) { |
| 1879 alu_out = rn_val - rm_val32; | 1829 carry_in = 1; |
| 1880 } else { | 1830 rm_val32 = ~rm_val32; |
| 1881 alu_out = rn_val + rm_val32; | |
| 1882 } | 1831 } |
| 1832 const int32_t alu_out = rn_val + rm_val32 + carry_in; | |
| 1883 set_wregister(rd, alu_out, instr->RdMode()); | 1833 set_wregister(rd, alu_out, instr->RdMode()); |
| 1884 if (instr->HasS()) { | 1834 if (instr->HasS()) { |
| 1885 SetNZFlagsW(alu_out); | 1835 SetNZFlagsW(alu_out); |
| 1886 if (subtract) { | 1836 SetCFlag(CarryFromW(rn_val, rm_val32, carry_in)); |
| 1887 SetCFlag(!BorrowFromW(rn_val, rm_val32)); | 1837 SetVFlag(OverflowFromW(rn_val, rm_val32, carry_in)); |
| 1888 } else { | 1838 } |
| 1889 SetCFlag(CarryFromW(rn_val, rm_val32)); | 1839 } |
| 1890 } | 1840 } |
| 1891 SetVFlag(OverflowFromW(alu_out, rn_val, rm_val32, !subtract)); | 1841 |
| 1842 | |
| 1843 void Simulator::DecodeAddSubWithCarry(Instr* instr) { | |
| 1844 // Format(instr, "adc'sf's 'rd, 'rn, 'rm"); | |
| 1845 // Format(instr, "sbc'sf's 'rd, 'rn, 'rm"); | |
| 1846 const bool addition = (instr->Bit(30) == 0); | |
| 1847 const Register rd = instr->RdField(); | |
| 1848 const Register rn = instr->RnField(); | |
| 1849 const Register rm = instr->RmField(); | |
| 1850 const int64_t rn_val64 = get_register(rn, R31IsZR); | |
| 1851 const int32_t rn_val32 = get_wregister(rn, R31IsZR); | |
| 1852 const int64_t rm_val64 = get_register(rm, R31IsZR); | |
| 1853 int32_t rm_val32 = get_wregister(rm, R31IsZR); | |
| 1854 const int32_t carry_in = c_flag_ ? 1 : 0; | |
| 1855 if (instr->SFField()) { | |
| 1856 // 64-bit add. | |
| 1857 const int64_t alu_out = | |
| 1858 rn_val64 + (addition ? rm_val64 : ~rm_val64) + carry_in; | |
| 1859 set_register(instr, rd, alu_out, R31IsZR); | |
| 1860 if (instr->HasS()) { | |
| 1861 SetNZFlagsX(alu_out); | |
| 1862 SetCFlag(CarryFromX(alu_out, rn_val64, rm_val64, addition)); | |
| 1863 SetVFlag(OverflowFromX(alu_out, rn_val64, rm_val64, addition)); | |
| 1864 } | |
| 1865 } else { | |
| 1866 // 32-bit add. | |
| 1867 if (!addition) { | |
| 1868 rm_val32 = ~rm_val32; | |
| 1869 } | |
| 1870 const int32_t alu_out = rn_val32 + rm_val32 + carry_in; | |
| 1871 set_wregister(rd, alu_out, R31IsZR); | |
| 1872 if (instr->HasS()) { | |
| 1873 SetNZFlagsW(alu_out); | |
| 1874 SetCFlag(CarryFromW(rn_val32, rm_val32, carry_in)); | |
| 1875 SetVFlag(OverflowFromW(rn_val32, rm_val32, carry_in)); | |
| 1892 } | 1876 } |
| 1893 } | 1877 } |
| 1894 } | 1878 } |
| 1895 | 1879 |
| 1896 | 1880 |
| 1897 void Simulator::DecodeLogicalShift(Instr* instr) { | 1881 void Simulator::DecodeLogicalShift(Instr* instr) { |
| 1898 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); | 1882 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); |
| 1899 const Register rd = instr->RdField(); | 1883 const Register rd = instr->RdField(); |
| 1900 const Register rn = instr->RnField(); | 1884 const Register rn = instr->RnField(); |
| 1901 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1885 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2168 set_register(instr, rd, result64, instr->RdMode()); | 2152 set_register(instr, rd, result64, instr->RdMode()); |
| 2169 } else { | 2153 } else { |
| 2170 set_wregister(rd, result32, instr->RdMode()); | 2154 set_wregister(rd, result32, instr->RdMode()); |
| 2171 } | 2155 } |
| 2172 } | 2156 } |
| 2173 | 2157 |
| 2174 | 2158 |
| 2175 void Simulator::DecodeDPRegister(Instr* instr) { | 2159 void Simulator::DecodeDPRegister(Instr* instr) { |
| 2176 if (instr->IsAddSubShiftExtOp()) { | 2160 if (instr->IsAddSubShiftExtOp()) { |
| 2177 DecodeAddSubShiftExt(instr); | 2161 DecodeAddSubShiftExt(instr); |
| 2162 } else if (instr->IsAddSubWithCarryOp()) { | |
| 2163 DecodeAddSubWithCarry(instr); | |
| 2178 } else if (instr->IsLogicalShiftOp()) { | 2164 } else if (instr->IsLogicalShiftOp()) { |
| 2179 DecodeLogicalShift(instr); | 2165 DecodeLogicalShift(instr); |
| 2180 } else if (instr->IsMiscDP2SourceOp()) { | 2166 } else if (instr->IsMiscDP2SourceOp()) { |
| 2181 DecodeMiscDP2Source(instr); | 2167 DecodeMiscDP2Source(instr); |
| 2182 } else if (instr->IsMiscDP3SourceOp()) { | 2168 } else if (instr->IsMiscDP3SourceOp()) { |
| 2183 DecodeMiscDP3Source(instr); | 2169 DecodeMiscDP3Source(instr); |
| 2184 } else if (instr->IsConditionalSelectOp()) { | 2170 } else if (instr->IsConditionalSelectOp()) { |
| 2185 DecodeConditionalSelect(instr); | 2171 DecodeConditionalSelect(instr); |
| 2186 } else { | 2172 } else { |
| 2187 UnimplementedInstruction(instr); | 2173 UnimplementedInstruction(instr); |
| (...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3057 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3043 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
| 3058 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3044 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
| 3059 buf->Longjmp(); | 3045 buf->Longjmp(); |
| 3060 } | 3046 } |
| 3061 | 3047 |
| 3062 } // namespace dart | 3048 } // namespace dart |
| 3063 | 3049 |
| 3064 #endif // !defined(HOST_ARCH_ARM64) | 3050 #endif // !defined(HOST_ARCH_ARM64) |
| 3065 | 3051 |
| 3066 #endif // defined TARGET_ARCH_ARM64 | 3052 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |