Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: runtime/vm/simulator_arm64.cc

Issue 630093004: Fix 32-bit and 64-bit carry out calculation in arm64 simulator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698