| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 printf("Expected %.17f (0x%016" PRIx64 ")\t " | 91 printf("Expected %.17f (0x%016" PRIx64 ")\t " |
| 92 "Found %.17f (0x%016" PRIx64 ")\n", | 92 "Found %.17f (0x%016" PRIx64 ")\n", |
| 93 expected, double_to_rawbits(expected), | 93 expected, double_to_rawbits(expected), |
| 94 result, double_to_rawbits(result)); | 94 result, double_to_rawbits(result)); |
| 95 } | 95 } |
| 96 return false; | 96 return false; |
| 97 } | 97 } |
| 98 | 98 |
| 99 | 99 |
| 100 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg) { | 100 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg) { |
| 101 DCHECK(reg.Is32Bits()); | 101 CHECK(reg.Is32Bits()); |
| 102 // Retrieve the corresponding X register so we can check that the upper part | 102 // Retrieve the corresponding X register so we can check that the upper part |
| 103 // was properly cleared. | 103 // was properly cleared. |
| 104 int64_t result_x = core->xreg(reg.code()); | 104 int64_t result_x = core->xreg(reg.code()); |
| 105 if ((result_x & 0xffffffff00000000L) != 0) { | 105 if ((result_x & 0xffffffff00000000L) != 0) { |
| 106 printf("Expected 0x%08" PRIx32 "\t Found 0x%016" PRIx64 "\n", | 106 printf("Expected 0x%08" PRIx32 "\t Found 0x%016" PRIx64 "\n", |
| 107 expected, result_x); | 107 expected, result_x); |
| 108 return false; | 108 return false; |
| 109 } | 109 } |
| 110 uint32_t result_w = core->wreg(reg.code()); | 110 uint32_t result_w = core->wreg(reg.code()); |
| 111 return Equal32(expected, core, result_w); | 111 return Equal32(expected, core, result_w); |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 bool Equal64(uint64_t expected, | 115 bool Equal64(uint64_t expected, |
| 116 const RegisterDump* core, | 116 const RegisterDump* core, |
| 117 const Register& reg) { | 117 const Register& reg) { |
| 118 DCHECK(reg.Is64Bits()); | 118 CHECK(reg.Is64Bits()); |
| 119 uint64_t result = core->xreg(reg.code()); | 119 uint64_t result = core->xreg(reg.code()); |
| 120 return Equal64(expected, core, result); | 120 return Equal64(expected, core, result); |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 bool EqualFP32(float expected, | 124 bool EqualFP32(float expected, |
| 125 const RegisterDump* core, | 125 const RegisterDump* core, |
| 126 const FPRegister& fpreg) { | 126 const FPRegister& fpreg) { |
| 127 DCHECK(fpreg.Is32Bits()); | 127 CHECK(fpreg.Is32Bits()); |
| 128 // Retrieve the corresponding D register so we can check that the upper part | 128 // Retrieve the corresponding D register so we can check that the upper part |
| 129 // was properly cleared. | 129 // was properly cleared. |
| 130 uint64_t result_64 = core->dreg_bits(fpreg.code()); | 130 uint64_t result_64 = core->dreg_bits(fpreg.code()); |
| 131 if ((result_64 & 0xffffffff00000000L) != 0) { | 131 if ((result_64 & 0xffffffff00000000L) != 0) { |
| 132 printf("Expected 0x%08" PRIx32 " (%f)\t Found 0x%016" PRIx64 "\n", | 132 printf("Expected 0x%08" PRIx32 " (%f)\t Found 0x%016" PRIx64 "\n", |
| 133 float_to_rawbits(expected), expected, result_64); | 133 float_to_rawbits(expected), expected, result_64); |
| 134 return false; | 134 return false; |
| 135 } | 135 } |
| 136 | 136 |
| 137 return EqualFP32(expected, core, core->sreg(fpreg.code())); | 137 return EqualFP32(expected, core, core->sreg(fpreg.code())); |
| 138 } | 138 } |
| 139 | 139 |
| 140 | 140 |
| 141 bool EqualFP64(double expected, | 141 bool EqualFP64(double expected, |
| 142 const RegisterDump* core, | 142 const RegisterDump* core, |
| 143 const FPRegister& fpreg) { | 143 const FPRegister& fpreg) { |
| 144 DCHECK(fpreg.Is64Bits()); | 144 CHECK(fpreg.Is64Bits()); |
| 145 return EqualFP64(expected, core, core->dreg(fpreg.code())); | 145 return EqualFP64(expected, core, core->dreg(fpreg.code())); |
| 146 } | 146 } |
| 147 | 147 |
| 148 | 148 |
| 149 bool Equal64(const Register& reg0, | 149 bool Equal64(const Register& reg0, |
| 150 const RegisterDump* core, | 150 const RegisterDump* core, |
| 151 const Register& reg1) { | 151 const Register& reg1) { |
| 152 DCHECK(reg0.Is64Bits() && reg1.Is64Bits()); | 152 CHECK(reg0.Is64Bits() && reg1.Is64Bits()); |
| 153 int64_t expected = core->xreg(reg0.code()); | 153 int64_t expected = core->xreg(reg0.code()); |
| 154 int64_t result = core->xreg(reg1.code()); | 154 int64_t result = core->xreg(reg1.code()); |
| 155 return Equal64(expected, core, result); | 155 return Equal64(expected, core, result); |
| 156 } | 156 } |
| 157 | 157 |
| 158 | 158 |
| 159 static char FlagN(uint32_t flags) { | 159 static char FlagN(uint32_t flags) { |
| 160 return (flags & NFlag) ? 'N' : 'n'; | 160 return (flags & NFlag) ? 'N' : 'n'; |
| 161 } | 161 } |
| 162 | 162 |
| 163 | 163 |
| 164 static char FlagZ(uint32_t flags) { | 164 static char FlagZ(uint32_t flags) { |
| 165 return (flags & ZFlag) ? 'Z' : 'z'; | 165 return (flags & ZFlag) ? 'Z' : 'z'; |
| 166 } | 166 } |
| 167 | 167 |
| 168 | 168 |
| 169 static char FlagC(uint32_t flags) { | 169 static char FlagC(uint32_t flags) { |
| 170 return (flags & CFlag) ? 'C' : 'c'; | 170 return (flags & CFlag) ? 'C' : 'c'; |
| 171 } | 171 } |
| 172 | 172 |
| 173 | 173 |
| 174 static char FlagV(uint32_t flags) { | 174 static char FlagV(uint32_t flags) { |
| 175 return (flags & VFlag) ? 'V' : 'v'; | 175 return (flags & VFlag) ? 'V' : 'v'; |
| 176 } | 176 } |
| 177 | 177 |
| 178 | 178 |
| 179 bool EqualNzcv(uint32_t expected, uint32_t result) { | 179 bool EqualNzcv(uint32_t expected, uint32_t result) { |
| 180 DCHECK((expected & ~NZCVFlag) == 0); | 180 CHECK((expected & ~NZCVFlag) == 0); |
| 181 DCHECK((result & ~NZCVFlag) == 0); | 181 CHECK((result & ~NZCVFlag) == 0); |
| 182 if (result != expected) { | 182 if (result != expected) { |
| 183 printf("Expected: %c%c%c%c\t Found: %c%c%c%c\n", | 183 printf("Expected: %c%c%c%c\t Found: %c%c%c%c\n", |
| 184 FlagN(expected), FlagZ(expected), FlagC(expected), FlagV(expected), | 184 FlagN(expected), FlagZ(expected), FlagC(expected), FlagV(expected), |
| 185 FlagN(result), FlagZ(result), FlagC(result), FlagV(result)); | 185 FlagN(result), FlagZ(result), FlagC(result), FlagV(result)); |
| 186 return false; | 186 return false; |
| 187 } | 187 } |
| 188 | 188 |
| 189 return true; | 189 return true; |
| 190 } | 190 } |
| 191 | 191 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 x[i] = Register::Create(n, kXRegSizeInBits); | 227 x[i] = Register::Create(n, kXRegSizeInBits); |
| 228 } | 228 } |
| 229 if (w) { | 229 if (w) { |
| 230 w[i] = Register::Create(n, kWRegSizeInBits); | 230 w[i] = Register::Create(n, kWRegSizeInBits); |
| 231 } | 231 } |
| 232 list |= (1UL << n); | 232 list |= (1UL << n); |
| 233 i++; | 233 i++; |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 // Check that we got enough registers. | 236 // Check that we got enough registers. |
| 237 DCHECK(CountSetBits(list, kNumberOfRegisters) == reg_count); | 237 CHECK(CountSetBits(list, kNumberOfRegisters) == reg_count); |
| 238 | 238 |
| 239 return list; | 239 return list; |
| 240 } | 240 } |
| 241 | 241 |
| 242 | 242 |
| 243 RegList PopulateFPRegisterArray(FPRegister* s, FPRegister* d, FPRegister* v, | 243 RegList PopulateFPRegisterArray(FPRegister* s, FPRegister* d, FPRegister* v, |
| 244 int reg_size, int reg_count, RegList allowed) { | 244 int reg_size, int reg_count, RegList allowed) { |
| 245 RegList list = 0; | 245 RegList list = 0; |
| 246 int i = 0; | 246 int i = 0; |
| 247 for (unsigned n = 0; (n < kNumberOfFPRegisters) && (i < reg_count); n++) { | 247 for (unsigned n = 0; (n < kNumberOfFPRegisters) && (i < reg_count); n++) { |
| 248 if (((1UL << n) & allowed) != 0) { | 248 if (((1UL << n) & allowed) != 0) { |
| 249 // Only assigned allowed registers. | 249 // Only assigned allowed registers. |
| 250 if (v) { | 250 if (v) { |
| 251 v[i] = FPRegister::Create(n, reg_size); | 251 v[i] = FPRegister::Create(n, reg_size); |
| 252 } | 252 } |
| 253 if (d) { | 253 if (d) { |
| 254 d[i] = FPRegister::Create(n, kDRegSizeInBits); | 254 d[i] = FPRegister::Create(n, kDRegSizeInBits); |
| 255 } | 255 } |
| 256 if (s) { | 256 if (s) { |
| 257 s[i] = FPRegister::Create(n, kSRegSizeInBits); | 257 s[i] = FPRegister::Create(n, kSRegSizeInBits); |
| 258 } | 258 } |
| 259 list |= (1UL << n); | 259 list |= (1UL << n); |
| 260 i++; | 260 i++; |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 // Check that we got enough registers. | 263 // Check that we got enough registers. |
| 264 DCHECK(CountSetBits(list, kNumberOfFPRegisters) == reg_count); | 264 CHECK(CountSetBits(list, kNumberOfFPRegisters) == reg_count); |
| 265 | 265 |
| 266 return list; | 266 return list; |
| 267 } | 267 } |
| 268 | 268 |
| 269 | 269 |
| 270 void Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) { | 270 void Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) { |
| 271 Register first = NoReg; | 271 Register first = NoReg; |
| 272 for (unsigned i = 0; i < kNumberOfRegisters; i++) { | 272 for (unsigned i = 0; i < kNumberOfRegisters; i++) { |
| 273 if (reg_list & (1UL << i)) { | 273 if (reg_list & (1UL << i)) { |
| 274 Register xn = Register::Create(i, kXRegSizeInBits); | 274 Register xn = Register::Create(i, kXRegSizeInBits); |
| 275 // We should never write into csp here. | 275 // We should never write into csp here. |
| 276 DCHECK(!xn.Is(csp)); | 276 CHECK(!xn.Is(csp)); |
| 277 if (!xn.IsZero()) { | 277 if (!xn.IsZero()) { |
| 278 if (!first.IsValid()) { | 278 if (!first.IsValid()) { |
| 279 // This is the first register we've hit, so construct the literal. | 279 // This is the first register we've hit, so construct the literal. |
| 280 __ Mov(xn, value); | 280 __ Mov(xn, value); |
| 281 first = xn; | 281 first = xn; |
| 282 } else { | 282 } else { |
| 283 // We've already loaded the literal, so re-use the value already | 283 // We've already loaded the literal, so re-use the value already |
| 284 // loaded into the first register we hit. | 284 // loaded into the first register we hit. |
| 285 __ Mov(xn, first); | 285 __ Mov(xn, first); |
| 286 } | 286 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 316 } else if (reg_list.type() == CPURegister::kFPRegister) { | 316 } else if (reg_list.type() == CPURegister::kFPRegister) { |
| 317 // This will always clobber D registers. | 317 // This will always clobber D registers. |
| 318 ClobberFP(masm, reg_list.list()); | 318 ClobberFP(masm, reg_list.list()); |
| 319 } else { | 319 } else { |
| 320 UNREACHABLE(); | 320 UNREACHABLE(); |
| 321 } | 321 } |
| 322 } | 322 } |
| 323 | 323 |
| 324 | 324 |
| 325 void RegisterDump::Dump(MacroAssembler* masm) { | 325 void RegisterDump::Dump(MacroAssembler* masm) { |
| 326 DCHECK(__ StackPointer().Is(csp)); | 326 CHECK(__ StackPointer().Is(csp)); |
| 327 | 327 |
| 328 // Ensure that we don't unintentionally clobber any registers. | 328 // Ensure that we don't unintentionally clobber any registers. |
| 329 RegList old_tmp_list = masm->TmpList()->list(); | 329 RegList old_tmp_list = masm->TmpList()->list(); |
| 330 RegList old_fptmp_list = masm->FPTmpList()->list(); | 330 RegList old_fptmp_list = masm->FPTmpList()->list(); |
| 331 masm->TmpList()->set_list(0); | 331 masm->TmpList()->set_list(0); |
| 332 masm->FPTmpList()->set_list(0); | 332 masm->FPTmpList()->set_list(0); |
| 333 | 333 |
| 334 // Preserve some temporary registers. | 334 // Preserve some temporary registers. |
| 335 Register dump_base = x0; | 335 Register dump_base = x0; |
| 336 Register dump = x1; | 336 Register dump = x1; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 | 392 |
| 393 // Dump the flags. | 393 // Dump the flags. |
| 394 __ Mrs(tmp, NZCV); | 394 __ Mrs(tmp, NZCV); |
| 395 __ Str(tmp, MemOperand(dump_base, flags_offset)); | 395 __ Str(tmp, MemOperand(dump_base, flags_offset)); |
| 396 | 396 |
| 397 // To dump the values that were in tmp amd dump, we need a new scratch | 397 // To dump the values that were in tmp amd dump, we need a new scratch |
| 398 // register. We can use any of the already dumped registers since we can | 398 // register. We can use any of the already dumped registers since we can |
| 399 // easily restore them. | 399 // easily restore them. |
| 400 Register dump2_base = x10; | 400 Register dump2_base = x10; |
| 401 Register dump2 = x11; | 401 Register dump2 = x11; |
| 402 DCHECK(!AreAliased(dump_base, dump, tmp, dump2_base, dump2)); | 402 CHECK(!AreAliased(dump_base, dump, tmp, dump2_base, dump2)); |
| 403 | 403 |
| 404 // Don't lose the dump_ address. | 404 // Don't lose the dump_ address. |
| 405 __ Mov(dump2_base, dump_base); | 405 __ Mov(dump2_base, dump_base); |
| 406 | 406 |
| 407 __ Pop(tmp, dump, dump_base, xzr); | 407 __ Pop(tmp, dump, dump_base, xzr); |
| 408 | 408 |
| 409 __ Add(dump2, dump2_base, w_offset); | 409 __ Add(dump2, dump2_base, w_offset); |
| 410 __ Str(dump_base_w, MemOperand(dump2, dump_base.code() * kWRegSize)); | 410 __ Str(dump_base_w, MemOperand(dump2, dump_base.code() * kWRegSize)); |
| 411 __ Str(dump_w, MemOperand(dump2, dump.code() * kWRegSize)); | 411 __ Str(dump_w, MemOperand(dump2, dump.code() * kWRegSize)); |
| 412 __ Str(tmp_w, MemOperand(dump2, tmp.code() * kWRegSize)); | 412 __ Str(tmp_w, MemOperand(dump2, tmp.code() * kWRegSize)); |
| 413 | 413 |
| 414 __ Add(dump2, dump2_base, x_offset); | 414 __ Add(dump2, dump2_base, x_offset); |
| 415 __ Str(dump_base, MemOperand(dump2, dump_base.code() * kXRegSize)); | 415 __ Str(dump_base, MemOperand(dump2, dump_base.code() * kXRegSize)); |
| 416 __ Str(dump, MemOperand(dump2, dump.code() * kXRegSize)); | 416 __ Str(dump, MemOperand(dump2, dump.code() * kXRegSize)); |
| 417 __ Str(tmp, MemOperand(dump2, tmp.code() * kXRegSize)); | 417 __ Str(tmp, MemOperand(dump2, tmp.code() * kXRegSize)); |
| 418 | 418 |
| 419 // Finally, restore dump2_base and dump2. | 419 // Finally, restore dump2_base and dump2. |
| 420 __ Ldr(dump2_base, MemOperand(dump2, dump2_base.code() * kXRegSize)); | 420 __ Ldr(dump2_base, MemOperand(dump2, dump2_base.code() * kXRegSize)); |
| 421 __ Ldr(dump2, MemOperand(dump2, dump2.code() * kXRegSize)); | 421 __ Ldr(dump2, MemOperand(dump2, dump2.code() * kXRegSize)); |
| 422 | 422 |
| 423 // Restore the MacroAssembler's scratch registers. | 423 // Restore the MacroAssembler's scratch registers. |
| 424 masm->TmpList()->set_list(old_tmp_list); | 424 masm->TmpList()->set_list(old_tmp_list); |
| 425 masm->FPTmpList()->set_list(old_fptmp_list); | 425 masm->FPTmpList()->set_list(old_fptmp_list); |
| 426 | 426 |
| 427 completed_ = true; | 427 completed_ = true; |
| 428 } | 428 } |
| OLD | NEW |