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

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);
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
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
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
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
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
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