| 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); |
| 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 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1936 return ExtendOperand(size, rm_val, extend_type, shift_amount); | 1895 return ExtendOperand(size, rm_val, extend_type, shift_amount); |
| 1937 } | 1896 } |
| 1938 UNREACHABLE(); | 1897 UNREACHABLE(); |
| 1939 return -1; | 1898 return -1; |
| 1940 } | 1899 } |
| 1941 | 1900 |
| 1942 | 1901 |
| 1943 void Simulator::DecodeAddSubShiftExt(Instr* instr) { | 1902 void Simulator::DecodeAddSubShiftExt(Instr* instr) { |
| 1944 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); | 1903 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); |
| 1945 // also, sub, cmp, etc. | 1904 // also, sub, cmp, etc. |
| 1946 const bool subtract = instr->Bit(30) == 1; | 1905 const bool addition = (instr->Bit(30) == 0); |
| 1947 const Register rd = instr->RdField(); | 1906 const Register rd = instr->RdField(); |
| 1948 const Register rn = instr->RnField(); | 1907 const Register rn = instr->RnField(); |
| 1949 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 1908 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
| 1950 if (instr->SFField()) { | 1909 if (instr->SFField()) { |
| 1951 // 64-bit add. | 1910 // 64-bit add. |
| 1952 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1911 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| 1953 int64_t alu_out = 0; | 1912 const int64_t alu_out = rn_val + (addition ? rm_val : -rm_val); |
| 1954 if (subtract) { | |
| 1955 alu_out = rn_val - rm_val; | |
| 1956 } else { | |
| 1957 alu_out = rn_val + rm_val; | |
| 1958 } | |
| 1959 set_register(instr, rd, alu_out, instr->RdMode()); | 1913 set_register(instr, rd, alu_out, instr->RdMode()); |
| 1960 if (instr->HasS()) { | 1914 if (instr->HasS()) { |
| 1961 SetNZFlagsX(alu_out); | 1915 SetNZFlagsX(alu_out); |
| 1962 if (subtract) { | 1916 SetCFlag(CarryFromX(alu_out, rn_val, rm_val, addition)); |
| 1963 SetCFlag(!BorrowFromX(rn_val, rm_val)); | 1917 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, addition)); |
| 1964 } else { | |
| 1965 SetCFlag(CarryFromX(rn_val, rm_val)); | |
| 1966 } | |
| 1967 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, !subtract)); | |
| 1968 } | 1918 } |
| 1969 } else { | 1919 } else { |
| 1970 // 32-bit add. | 1920 // 32-bit add. |
| 1971 const int32_t rn_val = get_wregister(rn, instr->RnMode()); | 1921 const int32_t rn_val = get_wregister(rn, instr->RnMode()); |
| 1972 const int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask); | 1922 int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask); |
| 1973 int32_t alu_out = 0; | 1923 int32_t carry_in = 0; |
| 1974 if (subtract) { | 1924 if (!addition) { |
| 1975 alu_out = rn_val - rm_val32; | 1925 carry_in = 1; |
| 1976 } else { | 1926 rm_val32 = ~rm_val32; |
| 1977 alu_out = rn_val + rm_val32; | |
| 1978 } | 1927 } |
| 1928 const int32_t alu_out = rn_val + rm_val32 + carry_in; |
| 1979 set_wregister(rd, alu_out, instr->RdMode()); | 1929 set_wregister(rd, alu_out, instr->RdMode()); |
| 1980 if (instr->HasS()) { | 1930 if (instr->HasS()) { |
| 1981 SetNZFlagsW(alu_out); | 1931 SetNZFlagsW(alu_out); |
| 1982 if (subtract) { | 1932 SetCFlag(CarryFromW(rn_val, rm_val32, carry_in)); |
| 1983 SetCFlag(!BorrowFromW(rn_val, rm_val32)); | 1933 SetVFlag(OverflowFromW(rn_val, rm_val32, carry_in)); |
| 1984 } else { | 1934 } |
| 1985 SetCFlag(CarryFromW(rn_val, rm_val32)); | 1935 } |
| 1986 } | 1936 } |
| 1987 SetVFlag(OverflowFromW(alu_out, rn_val, rm_val32, !subtract)); | 1937 |
| 1938 |
| 1939 void Simulator::DecodeAddSubWithCarry(Instr* instr) { |
| 1940 // Format(instr, "adc'sf's 'rd, 'rn, 'rm"); |
| 1941 // Format(instr, "sbc'sf's 'rd, 'rn, 'rm"); |
| 1942 const bool addition = (instr->Bit(30) == 0); |
| 1943 const Register rd = instr->RdField(); |
| 1944 const Register rn = instr->RnField(); |
| 1945 const Register rm = instr->RmField(); |
| 1946 const int64_t rn_val64 = get_register(rn, R31IsZR); |
| 1947 const int32_t rn_val32 = get_wregister(rn, R31IsZR); |
| 1948 const int64_t rm_val64 = get_register(rm, R31IsZR); |
| 1949 int32_t rm_val32 = get_wregister(rm, R31IsZR); |
| 1950 const int32_t carry_in = c_flag_ ? 1 : 0; |
| 1951 if (instr->SFField()) { |
| 1952 // 64-bit add. |
| 1953 const int64_t alu_out = |
| 1954 rn_val64 + (addition ? rm_val64 : ~rm_val64) + carry_in; |
| 1955 set_register(instr, rd, alu_out, R31IsZR); |
| 1956 if (instr->HasS()) { |
| 1957 SetNZFlagsX(alu_out); |
| 1958 SetCFlag(CarryFromX(alu_out, rn_val64, rm_val64, addition)); |
| 1959 SetVFlag(OverflowFromX(alu_out, rn_val64, rm_val64, addition)); |
| 1960 } |
| 1961 } else { |
| 1962 // 32-bit add. |
| 1963 if (!addition) { |
| 1964 rm_val32 = ~rm_val32; |
| 1965 } |
| 1966 const int32_t alu_out = rn_val32 + rm_val32 + carry_in; |
| 1967 set_wregister(rd, alu_out, R31IsZR); |
| 1968 if (instr->HasS()) { |
| 1969 SetNZFlagsW(alu_out); |
| 1970 SetCFlag(CarryFromW(rn_val32, rm_val32, carry_in)); |
| 1971 SetVFlag(OverflowFromW(rn_val32, rm_val32, carry_in)); |
| 1988 } | 1972 } |
| 1989 } | 1973 } |
| 1990 } | 1974 } |
| 1991 | 1975 |
| 1992 | 1976 |
| 1993 void Simulator::DecodeLogicalShift(Instr* instr) { | 1977 void Simulator::DecodeLogicalShift(Instr* instr) { |
| 1994 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); | 1978 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); |
| 1995 const Register rd = instr->RdField(); | 1979 const Register rd = instr->RdField(); |
| 1996 const Register rn = instr->RnField(); | 1980 const Register rn = instr->RnField(); |
| 1997 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1981 const int64_t rn_val = get_register(rn, instr->RnMode()); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2264 set_register(instr, rd, result64, instr->RdMode()); | 2248 set_register(instr, rd, result64, instr->RdMode()); |
| 2265 } else { | 2249 } else { |
| 2266 set_wregister(rd, result32, instr->RdMode()); | 2250 set_wregister(rd, result32, instr->RdMode()); |
| 2267 } | 2251 } |
| 2268 } | 2252 } |
| 2269 | 2253 |
| 2270 | 2254 |
| 2271 void Simulator::DecodeDPRegister(Instr* instr) { | 2255 void Simulator::DecodeDPRegister(Instr* instr) { |
| 2272 if (instr->IsAddSubShiftExtOp()) { | 2256 if (instr->IsAddSubShiftExtOp()) { |
| 2273 DecodeAddSubShiftExt(instr); | 2257 DecodeAddSubShiftExt(instr); |
| 2258 } else if (instr->IsAddSubWithCarryOp()) { |
| 2259 DecodeAddSubWithCarry(instr); |
| 2274 } else if (instr->IsLogicalShiftOp()) { | 2260 } else if (instr->IsLogicalShiftOp()) { |
| 2275 DecodeLogicalShift(instr); | 2261 DecodeLogicalShift(instr); |
| 2276 } else if (instr->IsMiscDP2SourceOp()) { | 2262 } else if (instr->IsMiscDP2SourceOp()) { |
| 2277 DecodeMiscDP2Source(instr); | 2263 DecodeMiscDP2Source(instr); |
| 2278 } else if (instr->IsMiscDP3SourceOp()) { | 2264 } else if (instr->IsMiscDP3SourceOp()) { |
| 2279 DecodeMiscDP3Source(instr); | 2265 DecodeMiscDP3Source(instr); |
| 2280 } else if (instr->IsConditionalSelectOp()) { | 2266 } else if (instr->IsConditionalSelectOp()) { |
| 2281 DecodeConditionalSelect(instr); | 2267 DecodeConditionalSelect(instr); |
| 2282 } else { | 2268 } else { |
| 2283 UnimplementedInstruction(instr); | 2269 UnimplementedInstruction(instr); |
| (...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3153 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3139 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
| 3154 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3140 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
| 3155 buf->Longjmp(); | 3141 buf->Longjmp(); |
| 3156 } | 3142 } |
| 3157 | 3143 |
| 3158 } // namespace dart | 3144 } // namespace dart |
| 3159 | 3145 |
| 3160 #endif // !defined(HOST_ARCH_ARM64) | 3146 #endif // !defined(HOST_ARCH_ARM64) |
| 3161 | 3147 |
| 3162 #endif // defined TARGET_ARCH_ARM64 | 3148 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |