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 24 matching lines...) Expand all Loading... |
35 #include "src/macro-assembler.h" | 35 #include "src/macro-assembler.h" |
36 #include "src/mips64/macro-assembler-mips64.h" | 36 #include "src/mips64/macro-assembler-mips64.h" |
37 #include "src/mips64/simulator-mips64.h" | 37 #include "src/mips64/simulator-mips64.h" |
38 | 38 |
39 | 39 |
40 using namespace v8::internal; | 40 using namespace v8::internal; |
41 | 41 |
42 typedef void* (*F)(int64_t x, int64_t y, int p2, int p3, int p4); | 42 typedef void* (*F)(int64_t x, int64_t y, int p2, int p3, int p4); |
43 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); | 43 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); | 44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| 45 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); |
45 | 46 |
46 #define __ masm-> | 47 #define __ masm-> |
47 | 48 |
48 TEST(BYTESWAP) { | 49 TEST(BYTESWAP) { |
49 DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2); | 50 DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2); |
50 CcTest::InitializeVM(); | 51 CcTest::InitializeVM(); |
51 Isolate* isolate = CcTest::i_isolate(); | 52 Isolate* isolate = CcTest::i_isolate(); |
52 HandleScope scope(isolate); | 53 HandleScope scope(isolate); |
53 | 54 |
54 struct T { | 55 struct T { |
(...skipping 1451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 | 1507 |
1507 Label handle_mind_nan, handle_maxd_nan, handle_mins_nan, handle_maxs_nan; | 1508 Label handle_mind_nan, handle_maxd_nan, handle_mins_nan, handle_maxs_nan; |
1508 Label back_mind_nan, back_maxd_nan, back_mins_nan, back_maxs_nan; | 1509 Label back_mind_nan, back_maxd_nan, back_mins_nan, back_maxs_nan; |
1509 | 1510 |
1510 __ push(s6); | 1511 __ push(s6); |
1511 __ InitializeRootRegister(); | 1512 __ InitializeRootRegister(); |
1512 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); | 1513 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); |
1513 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); | 1514 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); |
1514 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); | 1515 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); |
1515 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); | 1516 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); |
1516 __ MinNaNCheck_d(f10, f4, f8, &handle_mind_nan); | 1517 __ Float64Min(f10, f4, f8, &handle_mind_nan); |
1517 __ bind(&back_mind_nan); | 1518 __ bind(&back_mind_nan); |
1518 __ MaxNaNCheck_d(f12, f4, f8, &handle_maxd_nan); | 1519 __ Float64Max(f12, f4, f8, &handle_maxd_nan); |
1519 __ bind(&back_maxd_nan); | 1520 __ bind(&back_maxd_nan); |
1520 __ MinNaNCheck_s(f14, f2, f6, &handle_mins_nan); | 1521 __ Float32Min(f14, f2, f6, &handle_mins_nan); |
1521 __ bind(&back_mins_nan); | 1522 __ bind(&back_mins_nan); |
1522 __ MaxNaNCheck_s(f16, f2, f6, &handle_maxs_nan); | 1523 __ Float32Max(f16, f2, f6, &handle_maxs_nan); |
1523 __ bind(&back_maxs_nan); | 1524 __ bind(&back_maxs_nan); |
1524 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); | 1525 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); |
1525 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); | 1526 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); |
1526 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); | 1527 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); |
1527 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); | 1528 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); |
1528 __ pop(s6); | 1529 __ pop(s6); |
1529 __ jr(ra); | 1530 __ jr(ra); |
1530 __ nop(); | 1531 __ nop(); |
1531 | 1532 |
1532 handle_dnan(f10, &handle_mind_nan, &back_mind_nan); | 1533 handle_dnan(f10, &handle_mind_nan, &back_mind_nan); |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1960 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_1)); | 1961 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_1)); |
1961 | 1962 |
1962 auto fn_2 = [](MacroAssembler* masm, uint64_t imm) { | 1963 auto fn_2 = [](MacroAssembler* masm, uint64_t imm) { |
1963 __ Sltu(v0, a0, a1); | 1964 __ Sltu(v0, a0, a1); |
1964 }; | 1965 }; |
1965 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_2)); | 1966 CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_2)); |
1966 } | 1967 } |
1967 } | 1968 } |
1968 } | 1969 } |
1969 | 1970 |
| 1971 template <typename T, typename Inputs, typename Results> |
| 1972 static ::F4 GenerateMacroFloat32MinMax(MacroAssembler* masm) { |
| 1973 T a = T::from_code(4); // f4 |
| 1974 T b = T::from_code(6); // f6 |
| 1975 T c = T::from_code(8); // f8 |
| 1976 |
| 1977 Label ool_min_abc, ool_min_aab, ool_min_aba; |
| 1978 Label ool_max_abc, ool_max_aab, ool_max_aba; |
| 1979 |
| 1980 Label done_min_abc, done_min_aab, done_min_aba; |
| 1981 Label done_max_abc, done_max_aab, done_max_aba; |
| 1982 |
| 1983 #define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ |
| 1984 __ lwc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ |
| 1985 __ lwc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ |
| 1986 __ fminmax(res, x, y, &ool); \ |
| 1987 __ bind(&done); \ |
| 1988 __ swc1(a, MemOperand(a1, offsetof(Results, res_field))) |
| 1989 |
| 1990 // a = min(b, c); |
| 1991 FLOAT_MIN_MAX(Float32Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); |
| 1992 // a = min(a, b); |
| 1993 FLOAT_MIN_MAX(Float32Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); |
| 1994 // a = min(b, a); |
| 1995 FLOAT_MIN_MAX(Float32Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); |
| 1996 |
| 1997 // a = max(b, c); |
| 1998 FLOAT_MIN_MAX(Float32Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); |
| 1999 // a = max(a, b); |
| 2000 FLOAT_MIN_MAX(Float32Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); |
| 2001 // a = max(b, a); |
| 2002 FLOAT_MIN_MAX(Float32Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); |
| 2003 |
| 2004 #undef FLOAT_MIN_MAX |
| 2005 |
| 2006 __ jr(ra); |
| 2007 __ nop(); |
| 2008 |
| 2009 // Generate out-of-line cases. |
| 2010 __ bind(&ool_min_abc); |
| 2011 __ Float32MinOutOfLine(a, b, c); |
| 2012 __ b(&done_min_abc); |
| 2013 |
| 2014 __ bind(&ool_min_aab); |
| 2015 __ Float32MinOutOfLine(a, a, b); |
| 2016 __ b(&done_min_aab); |
| 2017 |
| 2018 __ bind(&ool_min_aba); |
| 2019 __ Float32MinOutOfLine(a, b, a); |
| 2020 __ b(&done_min_aba); |
| 2021 |
| 2022 __ bind(&ool_max_abc); |
| 2023 __ Float32MaxOutOfLine(a, b, c); |
| 2024 __ b(&done_max_abc); |
| 2025 |
| 2026 __ bind(&ool_max_aab); |
| 2027 __ Float32MaxOutOfLine(a, a, b); |
| 2028 __ b(&done_max_aab); |
| 2029 |
| 2030 __ bind(&ool_max_aba); |
| 2031 __ Float32MaxOutOfLine(a, b, a); |
| 2032 __ b(&done_max_aba); |
| 2033 |
| 2034 CodeDesc desc; |
| 2035 masm->GetCode(&desc); |
| 2036 Handle<Code> code = masm->isolate()->factory()->NewCode( |
| 2037 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2038 #ifdef DEBUG |
| 2039 OFStream os(stdout); |
| 2040 code->Print(os); |
| 2041 #endif |
| 2042 return FUNCTION_CAST<::F4>(code->entry()); |
| 2043 } |
| 2044 |
| 2045 TEST(macro_float_minmax_f32) { |
| 2046 // Test the Float32Min and Float32Max macros. |
| 2047 CcTest::InitializeVM(); |
| 2048 Isolate* isolate = CcTest::i_isolate(); |
| 2049 HandleScope scope(isolate); |
| 2050 |
| 2051 MacroAssembler assembler(isolate, NULL, 0, |
| 2052 v8::internal::CodeObjectRequired::kYes); |
| 2053 MacroAssembler* masm = &assembler; |
| 2054 |
| 2055 struct Inputs { |
| 2056 float src1_; |
| 2057 float src2_; |
| 2058 }; |
| 2059 |
| 2060 struct Results { |
| 2061 // Check all register aliasing possibilities in order to exercise all |
| 2062 // code-paths in the macro assembler. |
| 2063 float min_abc_; |
| 2064 float min_aab_; |
| 2065 float min_aba_; |
| 2066 float max_abc_; |
| 2067 float max_aab_; |
| 2068 float max_aba_; |
| 2069 }; |
| 2070 |
| 2071 ::F4 f = GenerateMacroFloat32MinMax<FPURegister, Inputs, Results>(masm); |
| 2072 Object* dummy = nullptr; |
| 2073 USE(dummy); |
| 2074 |
| 2075 #define CHECK_MINMAX(src1, src2, min, max) \ |
| 2076 do { \ |
| 2077 Inputs inputs = {src1, src2}; \ |
| 2078 Results results; \ |
| 2079 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ |
| 2080 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \ |
| 2081 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \ |
| 2082 CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \ |
| 2083 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \ |
| 2084 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \ |
| 2085 CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \ |
| 2086 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ |
| 2087 } while (0) |
| 2088 |
| 2089 float nan_a = std::numeric_limits<float>::quiet_NaN(); |
| 2090 float nan_b = std::numeric_limits<float>::quiet_NaN(); |
| 2091 |
| 2092 CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f); |
| 2093 CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f); |
| 2094 CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f); |
| 2095 CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f); |
| 2096 CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f); |
| 2097 CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f); |
| 2098 CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f); |
| 2099 CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f); |
| 2100 |
| 2101 CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f); |
| 2102 CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f); |
| 2103 CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f); |
| 2104 CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f); |
| 2105 |
| 2106 CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a); |
| 2107 CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a); |
| 2108 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); |
| 2109 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); |
| 2110 |
| 2111 #undef CHECK_MINMAX |
| 2112 } |
| 2113 |
| 2114 template <typename T, typename Inputs, typename Results> |
| 2115 static ::F4 GenerateMacroFloat64MinMax(MacroAssembler* masm) { |
| 2116 T a = T::from_code(4); // f4 |
| 2117 T b = T::from_code(6); // f6 |
| 2118 T c = T::from_code(8); // f8 |
| 2119 |
| 2120 Label ool_min_abc, ool_min_aab, ool_min_aba; |
| 2121 Label ool_max_abc, ool_max_aab, ool_max_aba; |
| 2122 |
| 2123 Label done_min_abc, done_min_aab, done_min_aba; |
| 2124 Label done_max_abc, done_max_aab, done_max_aba; |
| 2125 |
| 2126 #define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ |
| 2127 __ ldc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ |
| 2128 __ ldc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ |
| 2129 __ fminmax(res, x, y, &ool); \ |
| 2130 __ bind(&done); \ |
| 2131 __ sdc1(a, MemOperand(a1, offsetof(Results, res_field))) |
| 2132 |
| 2133 // a = min(b, c); |
| 2134 FLOAT_MIN_MAX(Float64Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); |
| 2135 // a = min(a, b); |
| 2136 FLOAT_MIN_MAX(Float64Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); |
| 2137 // a = min(b, a); |
| 2138 FLOAT_MIN_MAX(Float64Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); |
| 2139 |
| 2140 // a = max(b, c); |
| 2141 FLOAT_MIN_MAX(Float64Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); |
| 2142 // a = max(a, b); |
| 2143 FLOAT_MIN_MAX(Float64Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); |
| 2144 // a = max(b, a); |
| 2145 FLOAT_MIN_MAX(Float64Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); |
| 2146 |
| 2147 #undef FLOAT_MIN_MAX |
| 2148 |
| 2149 __ jr(ra); |
| 2150 __ nop(); |
| 2151 |
| 2152 // Generate out-of-line cases. |
| 2153 __ bind(&ool_min_abc); |
| 2154 __ Float64MinOutOfLine(a, b, c); |
| 2155 __ b(&done_min_abc); |
| 2156 |
| 2157 __ bind(&ool_min_aab); |
| 2158 __ Float64MinOutOfLine(a, a, b); |
| 2159 __ b(&done_min_aab); |
| 2160 |
| 2161 __ bind(&ool_min_aba); |
| 2162 __ Float64MinOutOfLine(a, b, a); |
| 2163 __ b(&done_min_aba); |
| 2164 |
| 2165 __ bind(&ool_max_abc); |
| 2166 __ Float64MaxOutOfLine(a, b, c); |
| 2167 __ b(&done_max_abc); |
| 2168 |
| 2169 __ bind(&ool_max_aab); |
| 2170 __ Float64MaxOutOfLine(a, a, b); |
| 2171 __ b(&done_max_aab); |
| 2172 |
| 2173 __ bind(&ool_max_aba); |
| 2174 __ Float64MaxOutOfLine(a, b, a); |
| 2175 __ b(&done_max_aba); |
| 2176 |
| 2177 CodeDesc desc; |
| 2178 masm->GetCode(&desc); |
| 2179 Handle<Code> code = masm->isolate()->factory()->NewCode( |
| 2180 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2181 #ifdef DEBUG |
| 2182 OFStream os(stdout); |
| 2183 code->Print(os); |
| 2184 #endif |
| 2185 return FUNCTION_CAST<::F4>(code->entry()); |
| 2186 } |
| 2187 |
| 2188 TEST(macro_float_minmax_f64) { |
| 2189 // Test the Float64Min and Float64Max macros. |
| 2190 CcTest::InitializeVM(); |
| 2191 Isolate* isolate = CcTest::i_isolate(); |
| 2192 HandleScope scope(isolate); |
| 2193 |
| 2194 MacroAssembler assembler(isolate, NULL, 0, |
| 2195 v8::internal::CodeObjectRequired::kYes); |
| 2196 MacroAssembler* masm = &assembler; |
| 2197 |
| 2198 struct Inputs { |
| 2199 double src1_; |
| 2200 double src2_; |
| 2201 }; |
| 2202 |
| 2203 struct Results { |
| 2204 // Check all register aliasing possibilities in order to exercise all |
| 2205 // code-paths in the macro assembler. |
| 2206 double min_abc_; |
| 2207 double min_aab_; |
| 2208 double min_aba_; |
| 2209 double max_abc_; |
| 2210 double max_aab_; |
| 2211 double max_aba_; |
| 2212 }; |
| 2213 |
| 2214 ::F4 f = GenerateMacroFloat64MinMax<DoubleRegister, Inputs, Results>(masm); |
| 2215 Object* dummy = nullptr; |
| 2216 USE(dummy); |
| 2217 |
| 2218 #define CHECK_MINMAX(src1, src2, min, max) \ |
| 2219 do { \ |
| 2220 Inputs inputs = {src1, src2}; \ |
| 2221 Results results; \ |
| 2222 dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ |
| 2223 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \ |
| 2224 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \ |
| 2225 CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \ |
| 2226 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \ |
| 2227 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \ |
| 2228 CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \ |
| 2229 /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ |
| 2230 } while (0) |
| 2231 |
| 2232 double nan_a = std::numeric_limits<double>::quiet_NaN(); |
| 2233 double nan_b = std::numeric_limits<double>::quiet_NaN(); |
| 2234 |
| 2235 CHECK_MINMAX(1.0, -1.0, -1.0, 1.0); |
| 2236 CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0); |
| 2237 CHECK_MINMAX(0.0, -1.0, -1.0, 0.0); |
| 2238 CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0); |
| 2239 CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0); |
| 2240 CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0); |
| 2241 CHECK_MINMAX(0.0, 1.0, 0.0, 1.0); |
| 2242 CHECK_MINMAX(1.0, 0.0, 0.0, 1.0); |
| 2243 |
| 2244 CHECK_MINMAX(0.0, 0.0, 0.0, 0.0); |
| 2245 CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0); |
| 2246 CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0); |
| 2247 CHECK_MINMAX(0.0, -0.0, -0.0, 0.0); |
| 2248 |
| 2249 CHECK_MINMAX(0.0, nan_a, nan_a, nan_a); |
| 2250 CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a); |
| 2251 CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); |
| 2252 CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); |
| 2253 |
| 2254 #undef CHECK_MINMAX |
| 2255 } |
| 2256 |
1970 #undef __ | 2257 #undef __ |
OLD | NEW |