Changeset 62371 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Jul 20, 2016 5:18:10 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
r62338 r62371 5 5 6 6 /* 7 * Copyright (C) 2011-201 5Oracle Corporation7 * Copyright (C) 2011-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 23 23 #include <VBox/vmm/vm.h> 24 24 #include <iprt/x86.h> 25 #ifdef RT_ARCH_X86 26 # include <iprt/uint128.h> 27 #endif 25 28 26 29 … … 1130 1133 /* multiplication and division */ 1131 1134 1135 1136 1132 1137 IEM_DECL_IMPL_DEF(int, iemAImpl_mul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags)) 1133 1138 { 1134 AssertFailed(); 1139 RTUINT128U Result; 1140 RTUInt128MulU64ByU64(&Result, *pu64RAX, u64Factor); 1141 *pu64RAX = Result.s.Lo; 1142 *pu64RDX = Result.s.Hi; 1143 /** @todo research the undefined MUL flags. */ 1144 return 0; 1145 } 1146 1147 1148 IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags)) 1149 { 1150 /** @todo Testcase: IMUL 1 operand */ 1151 RTUINT128U Result; 1152 *pfEFlags &= ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF); 1153 if ((int64_t)*pu64RAX >= 0) 1154 { 1155 if ((int64_t)*pu64RDX >= 0) 1156 { 1157 RTUInt128MulU64ByU64(&Result, *pu64RAX, *pu64RDX); 1158 *pu64RAX = Result.s.Lo; 1159 *pu64RDX = Result.s.Hi; 1160 if (Result.s.Hi != 0 || Result.s.Lo >= UINT64_C(0x8000000000000000)) 1161 *pfEFlags |= X86_EFL_CF | X86_EFL_OF; 1162 } 1163 else 1164 { 1165 RTUInt128MulU64ByU64(&Result, *pu64RAX, UINT64_C(0) - *pu64RDX); 1166 if (Result.s.Hi != 0 || Result.s.Lo > UINT64_C(0x8000000000000000)) 1167 *pfEFlags |= X86_EFL_CF | X86_EFL_OF; 1168 *pu64RAX = UINT64_C(0) - Result.s.Lo; 1169 *pu64RDX = UINT64_C(0) - Result.s.Hi; 1170 } 1171 } 1172 else 1173 { 1174 if ((int64_t)*pu64RDX >= 0) 1175 { 1176 RTUInt128MulU64ByU64(&Result, UINT64_C(0) - *pu64RAX, *pu64RDX); 1177 if (Result.s.Hi != 0 || Result.s.Lo > UINT64_C(0x8000000000000000)) 1178 *pfEFlags |= X86_EFL_CF | X86_EFL_OF; 1179 *pu64RAX = UINT64_C(0) - Result.s.Lo; 1180 *pu64RDX = UINT64_C(0) - Result.s.Hi; 1181 } 1182 else 1183 { 1184 RTUInt128MulU64ByU64(&Result, UINT64_C(0) - *pu64RAX, UINT64_C(0) - *pu64RDX); 1185 if (Result.s.Hi != 0 || Result.s.Lo >= UINT64_C(0x8000000000000000)) 1186 *pfEFlags |= X86_EFL_CF | X86_EFL_OF; 1187 *pu64RAX = Result.s.Lo; 1188 *pu64RDX = Result.s.Hi; 1189 } 1190 } 1191 if (*pu64RAX & RT_BIT_64(63)) 1192 *pfEFlags |= X86_EFL_SF; 1193 1194 /** @todo research the undefined IMUL flags. */ 1195 return 0; 1196 } 1197 1198 1199 IEM_DECL_IMPL_DEF(void, iemAImpl_imul_two_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags)) 1200 { 1201 /** @todo Testcase: IMUL 2 and 3 operands. */ 1202 uint64_t u64Ign; 1203 iemAImpl_imul_u64(puDst, &u64Ign, uSrc, pfEFlags); 1204 } 1205 1206 1207 1208 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags)) 1209 { 1210 if ( u64Divisor != 0 1211 && *pu64RDX < u64Divisor) 1212 { 1213 RTUINT128U Dividend; 1214 Dividend.s.Lo = *pu64RAX; 1215 Dividend.s.Hi = *pu64RDX; 1216 1217 RTUINT128U Divisor; 1218 Divisor.s.Lo = u64Divisor; 1219 Divisor.s.Hi = 0; 1220 1221 RTUINT128U Remainder; 1222 RTUINT128U Quotient; 1223 RTUInt128DivRem(&Quotient, &Remainder, &Dividend, &Divisor); 1224 Assert(Quotient.s.Hi == 0); 1225 Assert(Remainder.s.Hi == 0); 1226 1227 *pu64RAX = Quotient.s.Lo; 1228 *pu64RDX = Remainder.s.Lo; 1229 /** @todo research the undefined DIV flags. */ 1230 return 0; 1231 1232 } 1233 /* #DE */ 1135 1234 return VERR_IEM_ASPECT_NOT_IMPLEMENTED; 1136 1235 } 1137 1236 1138 1237 1139 IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags))1140 {1141 AssertFailed();1142 return VERR_IEM_ASPECT_NOT_IMPLEMENTED;1143 }1144 1145 1146 IEM_DECL_IMPL_DEF(void, iemAImpl_imul_two_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))1147 {1148 AssertFailed();1149 }1150 1151 1152 1153 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))1154 {1155 AssertFailed();1156 return VERR_IEM_ASPECT_NOT_IMPLEMENTED;1157 }1158 1159 1160 1238 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags)) 1161 1239 { 1162 AssertFailed(); 1240 if (u64Divisor != 0) 1241 { 1242 /* 1243 * Convert to unsigned division. 1244 */ 1245 RTUINT128U Dividend; 1246 Dividend.s.Hi = 0; 1247 if ((int64_t)*pu64RDX >= 0) 1248 { 1249 Dividend.s.Lo = *pu64RAX; 1250 Dividend.s.Hi = *pu64RDX; 1251 } 1252 else 1253 { 1254 Dividend.s.Lo = UINT64_C(0) - *pu64RAX; 1255 Dividend.s.Hi = UINT64_C(0) - *pu64RDX; 1256 } 1257 1258 RTUINT128U Divisor; 1259 Divisor.s.Hi = 0; 1260 if ((int64_t)u64Divisor >= 0) 1261 Divisor.s.Lo = u64Divisor; 1262 else 1263 Divisor.s.Lo = UINT64_C(0) - u64Divisor; 1264 1265 RTUINT128U Remainder; 1266 RTUINT128U Quotient; 1267 RTUInt128DivRem(&Quotient, &Remainder, &Dividend, &Divisor); 1268 1269 /* 1270 * Setup the result, checking for overflows. 1271 */ 1272 if ((int64_t)u64Divisor >= 0) 1273 { 1274 if ((int64_t)*pu64RDX >= 0) 1275 { 1276 /* Positive divisor, positive dividend => result positive. */ 1277 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint64_t)INT64_MAX) 1278 { 1279 *pu64RAX = Quotient.s.Lo; 1280 *pu64RDX = Remainder.s.Lo; 1281 return 0; 1282 } 1283 } 1284 else 1285 { 1286 /* Positive divisor, positive dividend => result negative. */ 1287 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= UINT64_C(0x8000000000000000)) 1288 { 1289 *pu64RAX = UINT64_C(0) - Quotient.s.Lo; 1290 *pu64RDX = UINT64_C(0) - Remainder.s.Lo; 1291 return 0; 1292 } 1293 } 1294 } 1295 else 1296 { 1297 if ((int64_t)*pu64RDX >= 0) 1298 { 1299 /* Negative divisor, positive dividend => negative quotient, positive remainder. */ 1300 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= UINT64_C(0x8000000000000000)) 1301 { 1302 *pu64RAX = UINT64_C(0) - Quotient.s.Lo; 1303 *pu64RDX = Remainder.s.Lo; 1304 return 0; 1305 } 1306 } 1307 else 1308 { 1309 /* Negative divisor, negative dividend => positive quotient, negative remainder. */ 1310 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint64_t)INT64_MAX) 1311 { 1312 *pu64RAX = Quotient.s.Lo; 1313 *pu64RDX = UINT64_C(0) - Remainder.s.Lo; 1314 return 0; 1315 } 1316 } 1317 } 1318 } 1319 /* #DE */ 1163 1320 return VERR_IEM_ASPECT_NOT_IMPLEMENTED; 1164 1321 }
Note:
See TracChangeset
for help on using the changeset viewer.