OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 static_cast<int32_t>(0xffffffff)}; | 406 static_cast<int32_t>(0xffffffff)}; |
407 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); | 407 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); |
408 } | 408 } |
409 | 409 |
410 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... } | 410 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... } |
411 #define FOR_INPUTS(ctype, itype, var, test_vector) \ | 411 #define FOR_INPUTS(ctype, itype, var, test_vector) \ |
412 std::vector<ctype> var##_vec = test_vector(); \ | 412 std::vector<ctype> var##_vec = test_vector(); \ |
413 for (std::vector<ctype>::iterator var = var##_vec.begin(); \ | 413 for (std::vector<ctype>::iterator var = var##_vec.begin(); \ |
414 var != var##_vec.end(); ++var) | 414 var != var##_vec.end(); ++var) |
415 | 415 |
| 416 #define FOR_INPUTS2(ctype, itype, var, var2, test_vector) \ |
| 417 std::vector<ctype> var##_vec = test_vector(); \ |
| 418 std::vector<ctype>::iterator var; \ |
| 419 std::vector<ctype>::reverse_iterator var2; \ |
| 420 for (var = var##_vec.begin(), var2 = var##_vec.rbegin(); \ |
| 421 var != var##_vec.end(); ++var, ++var2) |
| 422 |
416 #define FOR_ENUM_INPUTS(var, type, test_vector) \ | 423 #define FOR_ENUM_INPUTS(var, type, test_vector) \ |
417 FOR_INPUTS(enum type, type, var, test_vector) | 424 FOR_INPUTS(enum type, type, var, test_vector) |
418 #define FOR_STRUCT_INPUTS(var, type, test_vector) \ | 425 #define FOR_STRUCT_INPUTS(var, type, test_vector) \ |
419 FOR_INPUTS(struct type, type, var, test_vector) | 426 FOR_INPUTS(struct type, type, var, test_vector) |
420 #define FOR_UINT32_INPUTS(var, test_vector) \ | 427 #define FOR_UINT32_INPUTS(var, test_vector) \ |
421 FOR_INPUTS(uint32_t, uint32, var, test_vector) | 428 FOR_INPUTS(uint32_t, uint32, var, test_vector) |
422 #define FOR_INT32_INPUTS(var, test_vector) \ | 429 #define FOR_INT32_INPUTS(var, test_vector) \ |
423 FOR_INPUTS(int32_t, int32, var, test_vector) | 430 FOR_INPUTS(int32_t, int32, var, test_vector) |
| 431 #define FOR_INT32_INPUTS2(var, var2, test_vector) \ |
| 432 FOR_INPUTS2(int32_t, int32, var, var2, test_vector) |
| 433 |
| 434 #define FOR_UINT64_INPUTS(var, test_vector) \ |
| 435 FOR_INPUTS(uint64_t, uint32, var, test_vector) |
424 | 436 |
425 template <typename RET_TYPE, typename IN_TYPE, typename Func> | 437 template <typename RET_TYPE, typename IN_TYPE, typename Func> |
426 RET_TYPE run_Cvt(IN_TYPE x, Func GenerateConvertInstructionFunc) { | 438 RET_TYPE run_Cvt(IN_TYPE x, Func GenerateConvertInstructionFunc) { |
427 typedef RET_TYPE (*F_CVT)(IN_TYPE x0, int x1, int x2, int x3, int x4); | 439 typedef RET_TYPE (*F_CVT)(IN_TYPE x0, int x1, int x2, int x3, int x4); |
428 | 440 |
429 Isolate* isolate = CcTest::i_isolate(); | 441 Isolate* isolate = CcTest::i_isolate(); |
430 HandleScope scope(isolate); | 442 HandleScope scope(isolate); |
431 MacroAssembler assm(isolate, nullptr, 0, | 443 MacroAssembler assm(isolate, nullptr, 0, |
432 v8::internal::CodeObjectRequired::kYes); | 444 v8::internal::CodeObjectRequired::kYes); |
433 MacroAssembler* masm = &assm; | 445 MacroAssembler* masm = &assm; |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 | 924 |
913 CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0); | 925 CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0); |
914 | 926 |
915 CHECK_EQ(0, memcmp(&test.c, &outputsdmin[i], sizeof(test.c))); | 927 CHECK_EQ(0, memcmp(&test.c, &outputsdmin[i], sizeof(test.c))); |
916 CHECK_EQ(0, memcmp(&test.d, &outputsdmax[i], sizeof(test.d))); | 928 CHECK_EQ(0, memcmp(&test.d, &outputsdmax[i], sizeof(test.d))); |
917 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g))); | 929 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g))); |
918 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h))); | 930 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h))); |
919 } | 931 } |
920 } | 932 } |
921 | 933 |
| 934 template <typename IN_TYPE, typename Func> |
| 935 bool run_Unaligned(char* memory_buffer, int32_t in_offset, int32_t out_offset, |
| 936 IN_TYPE value, Func GenerateUnalignedInstructionFunc) { |
| 937 typedef int32_t (*F_CVT)(char* x0, int x1, int x2, int x3, int x4); |
| 938 |
| 939 Isolate* isolate = CcTest::i_isolate(); |
| 940 HandleScope scope(isolate); |
| 941 MacroAssembler assm(isolate, nullptr, 0, |
| 942 v8::internal::CodeObjectRequired::kYes); |
| 943 MacroAssembler* masm = &assm; |
| 944 IN_TYPE res; |
| 945 |
| 946 GenerateUnalignedInstructionFunc(masm, in_offset, out_offset); |
| 947 __ jr(ra); |
| 948 __ nop(); |
| 949 |
| 950 CodeDesc desc; |
| 951 assm.GetCode(&desc); |
| 952 Handle<Code> code = isolate->factory()->NewCode( |
| 953 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 954 |
| 955 F_CVT f = FUNCTION_CAST<F_CVT>(code->entry()); |
| 956 |
| 957 MemCopy(memory_buffer + in_offset, &value, sizeof(IN_TYPE)); |
| 958 CALL_GENERATED_CODE(isolate, f, memory_buffer, 0, 0, 0, 0); |
| 959 MemCopy(&res, memory_buffer + out_offset, sizeof(IN_TYPE)); |
| 960 |
| 961 return res == value; |
| 962 } |
| 963 |
| 964 static const std::vector<uint64_t> unsigned_test_values() { |
| 965 static const uint64_t kValues[] = { |
| 966 0x2180f18a06384414, 0x000a714532102277, 0xbc1acccf180649f0, |
| 967 0x8000000080008000, 0x0000000000000001, 0xffffffffffffffff, |
| 968 }; |
| 969 return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]); |
| 970 } |
| 971 |
| 972 static const std::vector<int32_t> unsigned_test_offset() { |
| 973 static const int32_t kValues[] = {// value, offset |
| 974 -132 * KB, -21 * KB, 0, 19 * KB, 135 * KB}; |
| 975 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); |
| 976 } |
| 977 |
| 978 static const std::vector<int32_t> unsigned_test_offset_increment() { |
| 979 static const int32_t kValues[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; |
| 980 return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]); |
| 981 } |
| 982 |
| 983 TEST(Ulh) { |
| 984 CcTest::InitializeVM(); |
| 985 |
| 986 static const int kBufferSize = 300 * KB; |
| 987 char memory_buffer[kBufferSize]; |
| 988 char* buffer_middle = memory_buffer + (kBufferSize / 2); |
| 989 |
| 990 FOR_UINT64_INPUTS(i, unsigned_test_values) { |
| 991 FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) { |
| 992 FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) { |
| 993 uint16_t value = static_cast<uint64_t>(*i & 0xFFFF); |
| 994 int32_t in_offset = *j1 + *k1; |
| 995 int32_t out_offset = *j2 + *k2; |
| 996 |
| 997 CHECK_EQ(true, run_Unaligned<uint16_t>( |
| 998 buffer_middle, in_offset, out_offset, value, |
| 999 [](MacroAssembler* masm, int32_t in_offset, |
| 1000 int32_t out_offset) { |
| 1001 __ Ulh(v0, MemOperand(a0, in_offset)); |
| 1002 __ Ush(v0, MemOperand(a0, out_offset), v0); |
| 1003 })); |
| 1004 CHECK_EQ(true, run_Unaligned<uint16_t>( |
| 1005 buffer_middle, in_offset, out_offset, value, |
| 1006 [](MacroAssembler* masm, int32_t in_offset, |
| 1007 int32_t out_offset) { |
| 1008 __ mov(t0, a0); |
| 1009 __ Ulh(a0, MemOperand(a0, in_offset)); |
| 1010 __ Ush(a0, MemOperand(t0, out_offset), v0); |
| 1011 })); |
| 1012 CHECK_EQ(true, run_Unaligned<uint16_t>( |
| 1013 buffer_middle, in_offset, out_offset, value, |
| 1014 [](MacroAssembler* masm, int32_t in_offset, |
| 1015 int32_t out_offset) { |
| 1016 __ mov(t0, a0); |
| 1017 __ Ulhu(a0, MemOperand(a0, in_offset)); |
| 1018 __ Ush(a0, MemOperand(t0, out_offset), t1); |
| 1019 })); |
| 1020 CHECK_EQ(true, run_Unaligned<uint16_t>( |
| 1021 buffer_middle, in_offset, out_offset, value, |
| 1022 [](MacroAssembler* masm, int32_t in_offset, |
| 1023 int32_t out_offset) { |
| 1024 __ Ulhu(v0, MemOperand(a0, in_offset)); |
| 1025 __ Ush(v0, MemOperand(a0, out_offset), t1); |
| 1026 })); |
| 1027 } |
| 1028 } |
| 1029 } |
| 1030 } |
| 1031 |
| 1032 TEST(Ulh_bitextension) { |
| 1033 CcTest::InitializeVM(); |
| 1034 |
| 1035 static const int kBufferSize = 300 * KB; |
| 1036 char memory_buffer[kBufferSize]; |
| 1037 char* buffer_middle = memory_buffer + (kBufferSize / 2); |
| 1038 |
| 1039 FOR_UINT64_INPUTS(i, unsigned_test_values) { |
| 1040 FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) { |
| 1041 FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) { |
| 1042 uint16_t value = static_cast<uint64_t>(*i & 0xFFFF); |
| 1043 int32_t in_offset = *j1 + *k1; |
| 1044 int32_t out_offset = *j2 + *k2; |
| 1045 |
| 1046 CHECK_EQ(true, run_Unaligned<uint16_t>( |
| 1047 buffer_middle, in_offset, out_offset, value, |
| 1048 [](MacroAssembler* masm, int32_t in_offset, |
| 1049 int32_t out_offset) { |
| 1050 Label success, fail, end, different; |
| 1051 __ Ulh(t0, MemOperand(a0, in_offset)); |
| 1052 __ Ulhu(t1, MemOperand(a0, in_offset)); |
| 1053 __ Branch(&different, ne, t0, Operand(t1)); |
| 1054 |
| 1055 // If signed and unsigned values are same, check |
| 1056 // the upper bits to see if they are zero |
| 1057 __ sra(t0, t0, 15); |
| 1058 __ Branch(&success, eq, t0, Operand(zero_reg)); |
| 1059 __ Branch(&fail); |
| 1060 |
| 1061 // If signed and unsigned values are different, |
| 1062 // check that the upper bits are complementary |
| 1063 __ bind(&different); |
| 1064 __ sra(t1, t1, 15); |
| 1065 __ Branch(&fail, ne, t1, Operand(1)); |
| 1066 __ sra(t0, t0, 15); |
| 1067 __ addiu(t0, t0, 1); |
| 1068 __ Branch(&fail, ne, t0, Operand(zero_reg)); |
| 1069 // Fall through to success |
| 1070 |
| 1071 __ bind(&success); |
| 1072 __ Ulh(t0, MemOperand(a0, in_offset)); |
| 1073 __ Ush(t0, MemOperand(a0, out_offset), v0); |
| 1074 __ Branch(&end); |
| 1075 __ bind(&fail); |
| 1076 __ Ush(zero_reg, MemOperand(a0, out_offset), v0); |
| 1077 __ bind(&end); |
| 1078 })); |
| 1079 } |
| 1080 } |
| 1081 } |
| 1082 } |
| 1083 |
| 1084 TEST(Ulw) { |
| 1085 CcTest::InitializeVM(); |
| 1086 |
| 1087 static const int kBufferSize = 300 * KB; |
| 1088 char memory_buffer[kBufferSize]; |
| 1089 char* buffer_middle = memory_buffer + (kBufferSize / 2); |
| 1090 |
| 1091 FOR_UINT64_INPUTS(i, unsigned_test_values) { |
| 1092 FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) { |
| 1093 FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) { |
| 1094 uint32_t value = static_cast<uint32_t>(*i & 0xFFFFFFFF); |
| 1095 int32_t in_offset = *j1 + *k1; |
| 1096 int32_t out_offset = *j2 + *k2; |
| 1097 |
| 1098 CHECK_EQ(true, run_Unaligned<uint32_t>( |
| 1099 buffer_middle, in_offset, out_offset, value, |
| 1100 [](MacroAssembler* masm, int32_t in_offset, |
| 1101 int32_t out_offset) { |
| 1102 __ Ulw(v0, MemOperand(a0, in_offset)); |
| 1103 __ Usw(v0, MemOperand(a0, out_offset)); |
| 1104 })); |
| 1105 CHECK_EQ(true, |
| 1106 run_Unaligned<uint32_t>( |
| 1107 buffer_middle, in_offset, out_offset, (uint32_t)value, |
| 1108 [](MacroAssembler* masm, int32_t in_offset, |
| 1109 int32_t out_offset) { |
| 1110 __ mov(t0, a0); |
| 1111 __ Ulw(a0, MemOperand(a0, in_offset)); |
| 1112 __ Usw(a0, MemOperand(t0, out_offset)); |
| 1113 })); |
| 1114 } |
| 1115 } |
| 1116 } |
| 1117 } |
| 1118 |
| 1119 TEST(Ulwc1) { |
| 1120 CcTest::InitializeVM(); |
| 1121 |
| 1122 static const int kBufferSize = 300 * KB; |
| 1123 char memory_buffer[kBufferSize]; |
| 1124 char* buffer_middle = memory_buffer + (kBufferSize / 2); |
| 1125 |
| 1126 FOR_UINT64_INPUTS(i, unsigned_test_values) { |
| 1127 FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) { |
| 1128 FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) { |
| 1129 float value = static_cast<float>(*i & 0xFFFFFFFF); |
| 1130 int32_t in_offset = *j1 + *k1; |
| 1131 int32_t out_offset = *j2 + *k2; |
| 1132 |
| 1133 CHECK_EQ(true, run_Unaligned<float>( |
| 1134 buffer_middle, in_offset, out_offset, value, |
| 1135 [](MacroAssembler* masm, int32_t in_offset, |
| 1136 int32_t out_offset) { |
| 1137 __ Ulwc1(f0, MemOperand(a0, in_offset), t0); |
| 1138 __ Uswc1(f0, MemOperand(a0, out_offset), t0); |
| 1139 })); |
| 1140 } |
| 1141 } |
| 1142 } |
| 1143 } |
| 1144 |
| 1145 TEST(Uldc1) { |
| 1146 CcTest::InitializeVM(); |
| 1147 |
| 1148 static const int kBufferSize = 300 * KB; |
| 1149 char memory_buffer[kBufferSize]; |
| 1150 char* buffer_middle = memory_buffer + (kBufferSize / 2); |
| 1151 |
| 1152 FOR_UINT64_INPUTS(i, unsigned_test_values) { |
| 1153 FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) { |
| 1154 FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) { |
| 1155 double value = static_cast<double>(*i); |
| 1156 int32_t in_offset = *j1 + *k1; |
| 1157 int32_t out_offset = *j2 + *k2; |
| 1158 |
| 1159 CHECK_EQ(true, run_Unaligned<double>( |
| 1160 buffer_middle, in_offset, out_offset, value, |
| 1161 [](MacroAssembler* masm, int32_t in_offset, |
| 1162 int32_t out_offset) { |
| 1163 __ Uldc1(f0, MemOperand(a0, in_offset), t0); |
| 1164 __ Usdc1(f0, MemOperand(a0, out_offset), t0); |
| 1165 })); |
| 1166 } |
| 1167 } |
| 1168 } |
| 1169 } |
| 1170 |
922 #undef __ | 1171 #undef __ |
OLD | NEW |