OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 6039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6050 TEST(maddf_msubf_d) { | 6050 TEST(maddf_msubf_d) { |
6051 if (kArchVariant != kMips64r6) return; | 6051 if (kArchVariant != kMips64r6) return; |
6052 helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) { | 6052 helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) { |
6053 __ maddf_d(f4, f6, f8); | 6053 __ maddf_d(f4, f6, f8); |
6054 __ Sdc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add))); | 6054 __ Sdc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add))); |
6055 __ msubf_d(f16, f6, f8); | 6055 __ msubf_d(f16, f6, f8); |
6056 __ Sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub))); | 6056 __ Sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub))); |
6057 }); | 6057 }); |
6058 } | 6058 } |
6059 | 6059 |
| 6060 uint64_t run_Subu(uint64_t imm, int32_t num_instr) { |
| 6061 Isolate* isolate = CcTest::i_isolate(); |
| 6062 HandleScope scope(isolate); |
| 6063 |
| 6064 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
| 6065 |
| 6066 Label code_start; |
| 6067 __ bind(&code_start); |
| 6068 __ Subu(v0, zero_reg, Operand(imm)); |
| 6069 CHECK_EQ(assm.SizeOfCodeGeneratedSince(&code_start), |
| 6070 num_instr * Assembler::kInstrSize); |
| 6071 __ jr(ra); |
| 6072 __ nop(); |
| 6073 |
| 6074 CodeDesc desc; |
| 6075 assm.GetCode(&desc); |
| 6076 Handle<Code> code = isolate->factory()->NewCode( |
| 6077 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 6078 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 6079 |
| 6080 uint64_t res = reinterpret_cast<uint64_t>( |
| 6081 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); |
| 6082 |
| 6083 return res; |
| 6084 } |
| 6085 |
| 6086 TEST(Subu) { |
| 6087 CcTest::InitializeVM(); |
| 6088 |
| 6089 // Test Subu macro-instruction for min_int16 and max_int16 border cases. |
| 6090 // For subtracting int16 immediate values we use addiu. |
| 6091 |
| 6092 struct TestCaseSubu { |
| 6093 uint64_t imm; |
| 6094 uint64_t expected_res; |
| 6095 int32_t num_instr; |
| 6096 }; |
| 6097 |
| 6098 // We call Subu(v0, zero_reg, imm) to test cases listed below. |
| 6099 // 0 - imm = expected_res |
| 6100 struct TestCaseSubu tc[] = { |
| 6101 // imm, expected_res, num_instr |
| 6102 {0xffffffffffff8000, 0x8000, 2}, // min_int16 |
| 6103 // Generates ori + addu |
| 6104 // We can't have just addiu because -min_int16 > max_int16 so use |
| 6105 // register. We can load min_int16 to at register with addiu and then |
| 6106 // subtract at with subu, but now we use ori + addu because -min_int16 can |
| 6107 // be loaded using ori. |
| 6108 {0x8000, 0xffffffffffff8000, 1}, // max_int16 + 1 |
| 6109 // Generates addiu |
| 6110 // max_int16 + 1 is not int16 but -(max_int16 + 1) is, just use addiu. |
| 6111 {0xffffffffffff7fff, 0x8001, 2}, // min_int16 - 1 |
| 6112 // Generates ori + addu |
| 6113 // To load this value to at we need two instructions and another one to |
| 6114 // subtract, lui + ori + subu. But we can load -value to at using just |
| 6115 // ori and then add at register with addu. |
| 6116 {0x8001, 0xffffffffffff7fff, 2}, // max_int16 + 2 |
| 6117 // Generates ori + subu |
| 6118 // Not int16 but is uint16, load value to at with ori and subtract with |
| 6119 // subu. |
| 6120 {0x00010000, 0xffffffffffff0000, 2}, |
| 6121 // Generates lui + subu |
| 6122 // Load value using lui to at and subtract with subu. |
| 6123 {0x00010001, 0xfffffffffffeffff, 3}, |
| 6124 // Generates lui + ori + subu |
| 6125 // We have to generate three instructions in this case. |
| 6126 }; |
| 6127 |
| 6128 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseSubu); |
| 6129 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 6130 CHECK_EQ(tc[i].expected_res, run_Subu(tc[i].imm, tc[i].num_instr)); |
| 6131 } |
| 6132 } |
| 6133 |
| 6134 uint64_t run_li(uint64_t imm, int32_t num_instr) { |
| 6135 Isolate* isolate = CcTest::i_isolate(); |
| 6136 HandleScope scope(isolate); |
| 6137 |
| 6138 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
| 6139 |
| 6140 Label code_start; |
| 6141 __ bind(&code_start); |
| 6142 __ li(v0, Operand(imm)); |
| 6143 CHECK_EQ(assm.SizeOfCodeGeneratedSince(&code_start), |
| 6144 num_instr * Assembler::kInstrSize); |
| 6145 __ jr(ra); |
| 6146 __ nop(); |
| 6147 |
| 6148 CodeDesc desc; |
| 6149 assm.GetCode(&desc); |
| 6150 Handle<Code> code = isolate->factory()->NewCode( |
| 6151 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 6152 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 6153 |
| 6154 uint64_t res = reinterpret_cast<uint64_t>( |
| 6155 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); |
| 6156 |
| 6157 return res; |
| 6158 } |
| 6159 |
| 6160 TEST(li) { |
| 6161 CcTest::InitializeVM(); |
| 6162 |
| 6163 // Test li macro-instruction for border cases. |
| 6164 |
| 6165 struct TestCase_li { |
| 6166 uint64_t imm; |
| 6167 int32_t r2_num_instr; |
| 6168 int32_t r6_num_instr; |
| 6169 }; |
| 6170 |
| 6171 // We call li(v0, imm) to test cases listed below. |
| 6172 struct TestCase_li tc[] = { |
| 6173 // imm, r2_num_instr, r6_num_instr |
| 6174 {0xffffffffffff8000, 1, 1}, // min_int16 |
| 6175 // Generates daddiu |
| 6176 // This is int16 value and we can load it using just daddiu. |
| 6177 {0x8000, 1, 1}, // max_int16 + 1 |
| 6178 // Generates ori |
| 6179 // max_int16 + 1 is not int16 but is uint16, just use ori. |
| 6180 {0xffffffffffff7fff, 2, 2}, // min_int16 - 1 |
| 6181 // Generates lui + ori |
| 6182 // We load int32 value using lui + ori. |
| 6183 {0x8001, 1, 1}, // max_int16 + 2 |
| 6184 // Generates ori |
| 6185 // Also an uint16 value, use ori. |
| 6186 {0x00010000, 1, 1}, // max_uint16 + 1 |
| 6187 // Generates lui |
| 6188 // Low 16 bits are 0, load value using lui. |
| 6189 {0x00010001, 2, 2}, // max_uint16 + 2 |
| 6190 // Generates lui + ori |
| 6191 // We have to generate two instructions in this case. |
| 6192 {0x00000000ffffffff, 2, 2}, // max_uint32 |
| 6193 // r2 - daddiu + dsrl32 |
| 6194 // r6 - daddiu + dahi |
| 6195 {0x00000000fffffffe, 3, 2}, // max_uint32 - 1 |
| 6196 // r2 - lui + ori + dsll |
| 6197 // r6 - daddiu + dahi |
| 6198 {0x00ffff000000fffe, 3, 3}, |
| 6199 // ori + dsll32 + ori |
| 6200 {0x00000001fffffffe, 4, 2}, // max_uint32 << 1 |
| 6201 // r2 - lui + ori + dsll + ori |
| 6202 // r6 - daddiu + dahi |
| 6203 {0x0000fffffffffffe, 5, 2}, // max_uint48 - 1 |
| 6204 // r2 - ori + dsll + ori + dsll + ori |
| 6205 // r6 - daddiu + dati |
| 6206 {0xffffffff00000000, 2, 2}, // max_uint32 << 32 |
| 6207 // r2 - daddiu + dsll32 |
| 6208 // r6 - ori + dahi |
| 6209 // We need ori to clear register before loading value using dahi. |
| 6210 {0xffffffff80000000, 1, 1}, // min_int32 |
| 6211 // lui |
| 6212 {0x0000000080000000, 2, 2}, // max_int32 + 1 |
| 6213 // r2 - ori + dsll |
| 6214 // r6 - lui + dahi |
| 6215 {0x0000800000000000, 2, 2}, |
| 6216 // ori + dsll32 |
| 6217 {0xffff800000000000, 2, 2}, |
| 6218 // r2 - daddiu + dsll32 |
| 6219 // r6 - ori + dahi |
| 6220 {0xffff80000000ffff, 3, 2}, |
| 6221 // r2 - daddiu + dsll32 + ori |
| 6222 // r6 - ori + dahi |
| 6223 {0xffffff123000ffff, 3, 3}, |
| 6224 // daddiu + dsll + ori |
| 6225 {0xffff00000000ffff, 3, 2}, |
| 6226 // r2 - daddiu + dsll32 + ori |
| 6227 // r6 - ori + dati |
| 6228 {0xffff8000ffff0000, 3, 2}, |
| 6229 // r2 - lui + ori + dsll |
| 6230 // r6 - lui + dahi |
| 6231 {0x1234ffff80000000, 3, 2}, |
| 6232 // r2 - lui + ori + dsll |
| 6233 // r6 - lui + dati |
| 6234 {0x1234ffff80010000, 5, 2}, |
| 6235 // r2 - lui + ori + dsll + ori + dsll |
| 6236 // r6 - lui + dati |
| 6237 {0xffff8000ffff8000, 2, 2}, |
| 6238 // r2 - daddiu + dinsu |
| 6239 // r6 - daddiu + dahi |
| 6240 {0xffff0000ffff8000, 5, 3}, |
| 6241 // r2 - lui + dsll + ori + dsll + ori |
| 6242 // r6 - daddiu + dahi + dati |
| 6243 {0x8000000080000000, 2, 2}, |
| 6244 // lui + dinsu |
| 6245 {0xabcd0000abcd0000, 2, 2}, |
| 6246 // lui + dinsu |
| 6247 {0x8000800080008000, 3, 3}, |
| 6248 // lui + ori + dinsu |
| 6249 {0xabcd1234abcd1234, 3, 3}, |
| 6250 // lui + ori + dinsu |
| 6251 {0xffff800080008000, 4, 3}, |
| 6252 // r2 - lui + ori + dsll + ori |
| 6253 // r6 - lui + ori + dahi |
| 6254 {0xffffabcd, 3, 2}, |
| 6255 // r2 - ori + dsll + ori |
| 6256 // r6 - daddiu + dahi |
| 6257 {0x1ffffabcd, 4, 2}, |
| 6258 // r2 - lui + ori + dsll + ori |
| 6259 // r6 - daddiu + dahi |
| 6260 {0xffffffffabcd, 5, 2}, |
| 6261 // r2 - ori + dsll + ori + dsll + ori |
| 6262 // r6 - daddiu + dati |
| 6263 {0x1ffffffffabcd, 6, 2}, |
| 6264 // r2 - lui + ori + dsll + ori + dsll + ori |
| 6265 // r6 - daddiu + dati |
| 6266 {0xffff7fff80010000, 5, 2}, |
| 6267 // r2 - lui + ori + dsll + ori + dsll |
| 6268 // r6 - lui + dahi |
| 6269 // Here lui sets high 32 bits to 1 so dahi can be used to get target |
| 6270 // value. |
| 6271 {0x00007fff7fff0000, 3, 2}, |
| 6272 // r2 - lui + ori + dsll |
| 6273 // r6 - lui + dahi |
| 6274 // High 32 bits are not set so dahi can be used to get target value. |
| 6275 {0xffff7fff7fff0000, 5, 3}, |
| 6276 // r2 - lui + ori + dsll + ori + dsll |
| 6277 // r6 - lui + dahi + dati |
| 6278 // High 32 bits are not set so just dahi can't be used to get target |
| 6279 // value. |
| 6280 {0x00007fff80010000, 3, 3}, |
| 6281 // r2 - lui + ori + dsll |
| 6282 // r6 - lui + ori + dsll |
| 6283 // High 32 bits are set so just dahi can't be used to get target value. |
| 6284 }; |
| 6285 |
| 6286 size_t nr_test_cases = sizeof(tc) / sizeof(TestCase_li); |
| 6287 for (size_t i = 0; i < nr_test_cases; ++i) { |
| 6288 if (kArchVariant == kMips64r2) { |
| 6289 CHECK_EQ(tc[i].imm, run_li(tc[i].imm, tc[i].r2_num_instr)); |
| 6290 } else { |
| 6291 CHECK_EQ(tc[i].imm, run_li(tc[i].imm, tc[i].r6_num_instr)); |
| 6292 } |
| 6293 } |
| 6294 } |
| 6295 |
6060 uint64_t run_Dins(uint64_t imm, uint64_t source, uint16_t pos, uint16_t size) { | 6296 uint64_t run_Dins(uint64_t imm, uint64_t source, uint16_t pos, uint16_t size) { |
6061 Isolate* isolate = CcTest::i_isolate(); | 6297 Isolate* isolate = CcTest::i_isolate(); |
6062 HandleScope scope(isolate); | 6298 HandleScope scope(isolate); |
6063 | 6299 |
6064 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); | 6300 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
6065 | 6301 |
6066 __ li(v0, imm); | 6302 __ li(v0, imm); |
6067 __ li(t0, source); | 6303 __ li(t0, source); |
6068 __ Dins(v0, t0, pos, size); | 6304 __ Dins(v0, t0, pos, size); |
6069 __ jr(ra); | 6305 __ jr(ra); |
(...skipping 21 matching lines...) Expand all Loading... |
6091 uint64_t source; | 6327 uint64_t source; |
6092 uint16_t pos; | 6328 uint16_t pos; |
6093 uint16_t size; | 6329 uint16_t size; |
6094 uint64_t expected_res; | 6330 uint64_t expected_res; |
6095 }; | 6331 }; |
6096 | 6332 |
6097 // We load imm to v0 and source to t0 and then call | 6333 // We load imm to v0 and source to t0 and then call |
6098 // Dins(v0, t0, pos, size) to test cases listed below. | 6334 // Dins(v0, t0, pos, size) to test cases listed below. |
6099 struct TestCaseDins tc[] = { | 6335 struct TestCaseDins tc[] = { |
6100 // imm, source, pos, size, expected_res | 6336 // imm, source, pos, size, expected_res |
6101 {0x5555555555555555, 0x1ABCDEF01, 31, 1, 0x55555555D5555555}, | 6337 {0x5555555555555555, 0x1abcdef01, 31, 1, 0x55555555d5555555}, |
6102 {0x5555555555555555, 0x1ABCDEF02, 30, 2, 0x5555555595555555}, | 6338 {0x5555555555555555, 0x1abcdef02, 30, 2, 0x5555555595555555}, |
6103 {0x201234567, 0x1FABCDEFF, 0, 32, 0x2FABCDEFF}, | 6339 {0x201234567, 0x1fabcdeff, 0, 32, 0x2fabcdeff}, |
6104 {0x201234567, 0x7FABCDEFF, 31, 2, 0x381234567}, | 6340 {0x201234567, 0x7fabcdeff, 31, 2, 0x381234567}, |
6105 {0x800000000, 0x7FABCDEFF, 0, 33, 0x9FABCDEFF}, | 6341 {0x800000000, 0x7fabcdeff, 0, 33, 0x9fabcdeff}, |
6106 {0x1234, 0xABCDABCDABCDABCD, 0, 64, 0xABCDABCDABCDABCD}, | 6342 {0x1234, 0xabcdabcdabcdabcd, 0, 64, 0xabcdabcdabcdabcd}, |
6107 {0xABCD, 0xABCEABCF, 32, 1, 0x10000ABCD}, | 6343 {0xabcd, 0xabceabcf, 32, 1, 0x10000abcd}, |
6108 {0xABCD, 0xABCEABCF, 63, 1, 0x800000000000ABCD}, | 6344 {0xabcd, 0xabceabcf, 63, 1, 0x800000000000abcd}, |
6109 {0xABCD, 0xABC1ABC2ABC3ABC4, 32, 32, 0xABC3ABC40000ABCD}, | 6345 {0x10000abcd, 0xabc1abc2abc3abc4, 32, 32, 0xabc3abc40000abcd}, |
6110 }; | 6346 }; |
6111 | 6347 |
6112 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDins); | 6348 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDins); |
6113 for (size_t i = 0; i < nr_test_cases; ++i) { | 6349 for (size_t i = 0; i < nr_test_cases; ++i) { |
6114 CHECK_EQ(tc[i].expected_res, | 6350 CHECK_EQ(tc[i].expected_res, |
6115 run_Dins(tc[i].imm, tc[i].source, tc[i].pos, tc[i].size)); | 6351 run_Dins(tc[i].imm, tc[i].source, tc[i].pos, tc[i].size)); |
6116 } | 6352 } |
6117 } | 6353 } |
6118 | 6354 |
6119 #undef __ | 6355 #undef __ |
OLD | NEW |