Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(477)

Side by Side Diff: src/arm/assembler-arm.h

Issue 11428137: ARM: Make use of d16-d31 when available. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Get the feature detection right Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm/assembler-arm.cc » ('j') | src/arm/code-stubs-arm.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions 5 // modification, are permitted provided that the following conditions
6 // are met: 6 // are met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 29 matching lines...) Expand all
40 #ifndef V8_ARM_ASSEMBLER_ARM_H_ 40 #ifndef V8_ARM_ASSEMBLER_ARM_H_
41 #define V8_ARM_ASSEMBLER_ARM_H_ 41 #define V8_ARM_ASSEMBLER_ARM_H_
42 #include <stdio.h> 42 #include <stdio.h>
43 #include "assembler.h" 43 #include "assembler.h"
44 #include "constants-arm.h" 44 #include "constants-arm.h"
45 #include "serialize.h" 45 #include "serialize.h"
46 46
47 namespace v8 { 47 namespace v8 {
48 namespace internal { 48 namespace internal {
49 49
50 // CpuFeatures keeps track of which features are supported by the target CPU.
51 // Supported features must be enabled by a Scope before use.
52 class CpuFeatures : public AllStatic {
53 public:
54 // Detect features of the target CPU. Set safe defaults if the serializer
55 // is enabled (snapshots must be portable).
56 static void Probe();
57
58 // Check whether a feature is supported by the target CPU.
59 static bool IsSupported(CpuFeature f) {
60 ASSERT(initialized_);
61 if (f == VFP3 && !FLAG_enable_vfp3) return false;
62 if (f == VFP2 && !FLAG_enable_vfp2) return false;
63 if (f == SUDIV && !FLAG_enable_sudiv) return false;
64 if (f == UNALIGNED_ACCESSES && !FLAG_enable_unaligned_accesses) {
65 return false;
66 }
67 return (supported_ & (1u << f)) != 0;
68 }
69
70 #ifdef DEBUG
71 // Check whether a feature is currently enabled.
72 static bool IsEnabled(CpuFeature f) {
73 ASSERT(initialized_);
74 Isolate* isolate = Isolate::UncheckedCurrent();
75 if (isolate == NULL) {
76 // When no isolate is available, work as if we're running in
77 // release mode.
78 return IsSupported(f);
79 }
80 unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
81 return (enabled & (1u << f)) != 0;
82 }
83 #endif
84
85 // Enable a specified feature within a scope.
86 class Scope BASE_EMBEDDED {
87 #ifdef DEBUG
88
89 public:
90 explicit Scope(CpuFeature f) {
91 unsigned mask = 1u << f;
92 // VFP2 and ARMv7 are implied by VFP3.
93 if (f == VFP3) mask |= 1u << VFP2 | 1u << ARMv7;
94 ASSERT(CpuFeatures::IsSupported(f));
95 ASSERT(!Serializer::enabled() ||
96 (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
97 isolate_ = Isolate::UncheckedCurrent();
98 old_enabled_ = 0;
99 if (isolate_ != NULL) {
100 old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
101 isolate_->set_enabled_cpu_features(old_enabled_ | mask);
102 }
103 }
104 ~Scope() {
105 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
106 if (isolate_ != NULL) {
107 isolate_->set_enabled_cpu_features(old_enabled_);
108 }
109 }
110
111 private:
112 Isolate* isolate_;
113 unsigned old_enabled_;
114 #else
115
116 public:
117 explicit Scope(CpuFeature f) {}
118 #endif
119 };
120
121 class TryForceFeatureScope BASE_EMBEDDED {
122 public:
123 explicit TryForceFeatureScope(CpuFeature f)
124 : old_supported_(CpuFeatures::supported_) {
125 if (CanForce()) {
126 CpuFeatures::supported_ |= (1u << f);
127 }
128 }
129
130 ~TryForceFeatureScope() {
131 if (CanForce()) {
132 CpuFeatures::supported_ = old_supported_;
133 }
134 }
135
136 private:
137 static bool CanForce() {
138 // It's only safe to temporarily force support of CPU features
139 // when there's only a single isolate, which is guaranteed when
140 // the serializer is enabled.
141 return Serializer::enabled();
142 }
143
144 const unsigned old_supported_;
145 };
146
147 private:
148 #ifdef DEBUG
149 static bool initialized_;
150 #endif
151 static unsigned supported_;
152 static unsigned found_by_runtime_probing_;
153
154 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
155 };
156
157
50 // CPU Registers. 158 // CPU Registers.
51 // 159 //
52 // 1) We would prefer to use an enum, but enum values are assignment- 160 // 1) We would prefer to use an enum, but enum values are assignment-
53 // compatible with int, which has caused code-generation bugs. 161 // compatible with int, which has caused code-generation bugs.
54 // 162 //
55 // 2) We would prefer to use a class instead of a struct but we don't like 163 // 2) We would prefer to use a class instead of a struct but we don't like
56 // the register initialization to depend on the particular initialization 164 // the register initialization to depend on the particular initialization
57 // order (which appears to be different on OS X, Linux, and Windows for the 165 // order (which appears to be different on OS X, Linux, and Windows for the
58 // installed versions of C++ we tried). Using a struct permits C-style 166 // installed versions of C++ we tried). Using a struct permits C-style
59 // "initialization". Also, the Register objects cannot be const as this 167 // "initialization". Also, the Register objects cannot be const as this
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 *m = code_ & 0x1; 291 *m = code_ & 0x1;
184 *vm = code_ >> 1; 292 *vm = code_ >> 1;
185 } 293 }
186 294
187 int code_; 295 int code_;
188 }; 296 };
189 297
190 298
191 // Double word VFP register. 299 // Double word VFP register.
192 struct DwVfpRegister { 300 struct DwVfpRegister {
193 static const int kNumRegisters = 16; 301 static const int kNumRegisters = 32;
194 // A few double registers are reserved: one as a scratch register and one to 302 // A few double registers are reserved: one as a scratch register and one to
195 // hold 0.0, that does not fit in the immediate field of vmov instructions. 303 // hold 0.0, that does not fit in the immediate field of vmov instructions.
196 // d14: 0.0 304 // d14: 0.0
197 // d15: scratch register. 305 // d15: scratch register.
198 static const int kNumReservedRegisters = 2; 306 static const int kNumReservedRegisters = 2;
199 static const int kNumAllocatableRegisters = kNumRegisters - 307 static int NumAvailableRegisters() {
200 kNumReservedRegisters; 308 return CpuFeatures::IsSupported(VFP32DREGS) ? 32 : 16;
309 }
310 static int NumAllocatableRegisters() {
311 return NumAvailableRegisters() - kNumReservedRegisters;
312 }
201 313
202 inline static int ToAllocationIndex(DwVfpRegister reg); 314 inline static int ToAllocationIndex(DwVfpRegister reg);
203 315
204 static DwVfpRegister FromAllocationIndex(int index) { 316 static DwVfpRegister FromAllocationIndex(int index) {
205 ASSERT(index >= 0 && index < kNumAllocatableRegisters); 317 ASSERT(index >= 0 && index < NumAllocatableRegisters());
318 if (index >= 14)
ulan 2012/12/17 10:44:52 Here and below we can use kDoubleRegZero.code() in
hans 2012/12/17 12:31:44 I don't think that would work, since kDoubleRegZer
ulan 2012/12/17 13:03:36 I see. Yep, putting FromAllocationIndex near the T
hans 2012/12/17 13:53:21 Cool. I've moved it and AllocationIndexToString.
319 return from_code(index + kNumReservedRegisters);
206 return from_code(index); 320 return from_code(index);
207 } 321 }
208 322
209 static const char* AllocationIndexToString(int index) { 323 static const char* AllocationIndexToString(int index) {
210 ASSERT(index >= 0 && index < kNumAllocatableRegisters); 324 ASSERT(index >= 0 && index < NumAllocatableRegisters());
325 if (index >= 14)
326 index += kNumReservedRegisters;
211 const char* const names[] = { 327 const char* const names[] = {
212 "d0", 328 "d0",
213 "d1", 329 "d1",
214 "d2", 330 "d2",
215 "d3", 331 "d3",
216 "d4", 332 "d4",
217 "d5", 333 "d5",
218 "d6", 334 "d6",
219 "d7", 335 "d7",
220 "d8", 336 "d8",
221 "d9", 337 "d9",
222 "d10", 338 "d10",
223 "d11", 339 "d11",
224 "d12", 340 "d12",
225 "d13" 341 "d13",
342 "d14",
343 "d15",
344 "d16",
345 "d17",
346 "d18",
347 "d19",
348 "d20",
349 "d21",
350 "d22",
351 "d23",
352 "d24",
353 "d25",
354 "d26",
355 "d27",
356 "d28",
357 "d29",
358 "d30",
359 "d31"
226 }; 360 };
227 return names[index]; 361 return names[index];
228 } 362 }
229 363
230 static DwVfpRegister from_code(int code) { 364 static DwVfpRegister from_code(int code) {
231 DwVfpRegister r = { code }; 365 DwVfpRegister r = { code };
232 return r; 366 return r;
233 } 367 }
234 368
235 // Supporting d0 to d15, can be later extended to d31. 369 bool is_valid() const {
236 bool is_valid() const { return 0 <= code_ && code_ < 16; } 370 return 0 <= code_ && code_ < NumAvailableRegisters();
371 }
237 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 372 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
238 SwVfpRegister low() const { 373 SwVfpRegister low() const {
374 ASSERT(code_ < 16);
239 SwVfpRegister reg; 375 SwVfpRegister reg;
240 reg.code_ = code_ * 2; 376 reg.code_ = code_ * 2;
241 377
242 ASSERT(reg.is_valid()); 378 ASSERT(reg.is_valid());
243 return reg; 379 return reg;
244 } 380 }
245 SwVfpRegister high() const { 381 SwVfpRegister high() const {
382 ASSERT(code_ < 16);
246 SwVfpRegister reg; 383 SwVfpRegister reg;
247 reg.code_ = (code_ * 2) + 1; 384 reg.code_ = (code_ * 2) + 1;
248 385
249 ASSERT(reg.is_valid()); 386 ASSERT(reg.is_valid());
250 return reg; 387 return reg;
251 } 388 }
252 int code() const { 389 int code() const {
253 ASSERT(is_valid()); 390 ASSERT(is_valid());
254 return code_; 391 return code_;
255 } 392 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 const DwVfpRegister d6 = { 6 }; 452 const DwVfpRegister d6 = { 6 };
316 const DwVfpRegister d7 = { 7 }; 453 const DwVfpRegister d7 = { 7 };
317 const DwVfpRegister d8 = { 8 }; 454 const DwVfpRegister d8 = { 8 };
318 const DwVfpRegister d9 = { 9 }; 455 const DwVfpRegister d9 = { 9 };
319 const DwVfpRegister d10 = { 10 }; 456 const DwVfpRegister d10 = { 10 };
320 const DwVfpRegister d11 = { 11 }; 457 const DwVfpRegister d11 = { 11 };
321 const DwVfpRegister d12 = { 12 }; 458 const DwVfpRegister d12 = { 12 };
322 const DwVfpRegister d13 = { 13 }; 459 const DwVfpRegister d13 = { 13 };
323 const DwVfpRegister d14 = { 14 }; 460 const DwVfpRegister d14 = { 14 };
324 const DwVfpRegister d15 = { 15 }; 461 const DwVfpRegister d15 = { 15 };
462 const DwVfpRegister d16 = { 16 };
463 const DwVfpRegister d17 = { 17 };
464 const DwVfpRegister d18 = { 18 };
465 const DwVfpRegister d19 = { 19 };
466 const DwVfpRegister d20 = { 20 };
467 const DwVfpRegister d21 = { 21 };
468 const DwVfpRegister d22 = { 22 };
469 const DwVfpRegister d23 = { 23 };
470 const DwVfpRegister d24 = { 24 };
471 const DwVfpRegister d25 = { 25 };
472 const DwVfpRegister d26 = { 26 };
473 const DwVfpRegister d27 = { 27 };
474 const DwVfpRegister d28 = { 28 };
475 const DwVfpRegister d29 = { 29 };
476 const DwVfpRegister d30 = { 30 };
477 const DwVfpRegister d31 = { 31 };
325 478
326 // Aliases for double registers. Defined using #define instead of 479 // Aliases for double registers. Defined using #define instead of
327 // "static const DwVfpRegister&" because Clang complains otherwise when a 480 // "static const DwVfpRegister&" because Clang complains otherwise when a
328 // compilation unit that includes this header doesn't use the variables. 481 // compilation unit that includes this header doesn't use the variables.
329 #define kFirstCalleeSavedDoubleReg d8 482 #define kFirstCalleeSavedDoubleReg d8
330 #define kLastCalleeSavedDoubleReg d15 483 #define kLastCalleeSavedDoubleReg d15
331 #define kDoubleRegZero d14 484 #define kDoubleRegZero d14
332 #define kScratchDoubleReg d15 485 #define kScratchDoubleReg d15
333 486
334 487
335 // Coprocessor register 488 // Coprocessor register
336 struct CRegister { 489 struct CRegister {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 Register rn_; // base 644 Register rn_; // base
492 Register rm_; // register offset 645 Register rm_; // register offset
493 int32_t offset_; // valid if rm_ == no_reg 646 int32_t offset_; // valid if rm_ == no_reg
494 ShiftOp shift_op_; 647 ShiftOp shift_op_;
495 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 648 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
496 AddrMode am_; // bits P, U, and W 649 AddrMode am_; // bits P, U, and W
497 650
498 friend class Assembler; 651 friend class Assembler;
499 }; 652 };
500 653
501 // CpuFeatures keeps track of which features are supported by the target CPU.
502 // Supported features must be enabled by a Scope before use.
503 class CpuFeatures : public AllStatic {
504 public:
505 // Detect features of the target CPU. Set safe defaults if the serializer
506 // is enabled (snapshots must be portable).
507 static void Probe();
508
509 // Check whether a feature is supported by the target CPU.
510 static bool IsSupported(CpuFeature f) {
511 ASSERT(initialized_);
512 if (f == VFP3 && !FLAG_enable_vfp3) return false;
513 if (f == VFP2 && !FLAG_enable_vfp2) return false;
514 if (f == SUDIV && !FLAG_enable_sudiv) return false;
515 if (f == UNALIGNED_ACCESSES && !FLAG_enable_unaligned_accesses) {
516 return false;
517 }
518 return (supported_ & (1u << f)) != 0;
519 }
520
521 #ifdef DEBUG
522 // Check whether a feature is currently enabled.
523 static bool IsEnabled(CpuFeature f) {
524 ASSERT(initialized_);
525 Isolate* isolate = Isolate::UncheckedCurrent();
526 if (isolate == NULL) {
527 // When no isolate is available, work as if we're running in
528 // release mode.
529 return IsSupported(f);
530 }
531 unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
532 return (enabled & (1u << f)) != 0;
533 }
534 #endif
535
536 // Enable a specified feature within a scope.
537 class Scope BASE_EMBEDDED {
538 #ifdef DEBUG
539
540 public:
541 explicit Scope(CpuFeature f) {
542 unsigned mask = 1u << f;
543 // VFP2 and ARMv7 are implied by VFP3.
544 if (f == VFP3) mask |= 1u << VFP2 | 1u << ARMv7;
545 ASSERT(CpuFeatures::IsSupported(f));
546 ASSERT(!Serializer::enabled() ||
547 (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
548 isolate_ = Isolate::UncheckedCurrent();
549 old_enabled_ = 0;
550 if (isolate_ != NULL) {
551 old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
552 isolate_->set_enabled_cpu_features(old_enabled_ | mask);
553 }
554 }
555 ~Scope() {
556 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
557 if (isolate_ != NULL) {
558 isolate_->set_enabled_cpu_features(old_enabled_);
559 }
560 }
561
562 private:
563 Isolate* isolate_;
564 unsigned old_enabled_;
565 #else
566
567 public:
568 explicit Scope(CpuFeature f) {}
569 #endif
570 };
571
572 class TryForceFeatureScope BASE_EMBEDDED {
573 public:
574 explicit TryForceFeatureScope(CpuFeature f)
575 : old_supported_(CpuFeatures::supported_) {
576 if (CanForce()) {
577 CpuFeatures::supported_ |= (1u << f);
578 }
579 }
580
581 ~TryForceFeatureScope() {
582 if (CanForce()) {
583 CpuFeatures::supported_ = old_supported_;
584 }
585 }
586
587 private:
588 static bool CanForce() {
589 // It's only safe to temporarily force support of CPU features
590 // when there's only a single isolate, which is guaranteed when
591 // the serializer is enabled.
592 return Serializer::enabled();
593 }
594
595 const unsigned old_supported_;
596 };
597
598 private:
599 #ifdef DEBUG
600 static bool initialized_;
601 #endif
602 static unsigned supported_;
603 static unsigned found_by_runtime_probing_;
604
605 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
606 };
607
608
609 extern const Instr kMovLrPc; 654 extern const Instr kMovLrPc;
610 extern const Instr kLdrPCMask; 655 extern const Instr kLdrPCMask;
611 extern const Instr kLdrPCPattern; 656 extern const Instr kLdrPCPattern;
612 extern const Instr kBlxRegMask; 657 extern const Instr kBlxRegMask;
613 extern const Instr kBlxRegPattern; 658 extern const Instr kBlxRegPattern;
614 extern const Instr kBlxIp; 659 extern const Instr kBlxIp;
615 660
616 extern const Instr kMovMvnMask; 661 extern const Instr kMovMvnMask;
617 extern const Instr kMovMvnPattern; 662 extern const Instr kMovMvnPattern;
618 extern const Instr kMovMvnFlip; 663 extern const Instr kMovMvnFlip;
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 LFlag l = Short, Condition cond = al); 1032 LFlag l = Short, Condition cond = al);
988 void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 1033 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
989 LFlag l = Short, Condition cond = al); 1034 LFlag l = Short, Condition cond = al);
990 1035
991 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 1036 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
992 LFlag l = Short); // v5 and above 1037 LFlag l = Short); // v5 and above
993 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 1038 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
994 LFlag l = Short); // v5 and above 1039 LFlag l = Short); // v5 and above
995 1040
996 // Support for VFP. 1041 // Support for VFP.
997 // All these APIs support S0 to S31 and D0 to D15. 1042 // All these APIs support S0 to S31 and D0 to D31.
998 // Currently these APIs do not support extended D registers, i.e, D16 to D31.
999 // However, some simple modifications can allow
1000 // these APIs to support D16 to D31.
1001 1043
1002 void vldr(const DwVfpRegister dst, 1044 void vldr(const DwVfpRegister dst,
1003 const Register base, 1045 const Register base,
1004 int offset, 1046 int offset,
1005 const Condition cond = al); 1047 const Condition cond = al);
1006 void vldr(const DwVfpRegister dst, 1048 void vldr(const DwVfpRegister dst,
1007 const MemOperand& src, 1049 const MemOperand& src,
1008 const Condition cond = al); 1050 const Condition cond = al);
1009 1051
1010 void vldr(const SwVfpRegister dst, 1052 void vldr(const SwVfpRegister dst,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1059 double imm, 1101 double imm,
1060 const Register scratch = no_reg, 1102 const Register scratch = no_reg,
1061 const Condition cond = al); 1103 const Condition cond = al);
1062 void vmov(const SwVfpRegister dst, 1104 void vmov(const SwVfpRegister dst,
1063 const SwVfpRegister src, 1105 const SwVfpRegister src,
1064 const Condition cond = al); 1106 const Condition cond = al);
1065 void vmov(const DwVfpRegister dst, 1107 void vmov(const DwVfpRegister dst,
1066 const DwVfpRegister src, 1108 const DwVfpRegister src,
1067 const Condition cond = al); 1109 const Condition cond = al);
1068 void vmov(const DwVfpRegister dst, 1110 void vmov(const DwVfpRegister dst,
1111 int x,
ulan 2012/12/17 10:44:52 I wonder if there is more descriptive name than 'x
hans 2012/12/17 12:31:44 How about "index"?
ulan 2012/12/17 13:03:36 Yep, I like it more.
hans 2012/12/17 13:53:21 Done.
1112 const Register src,
1113 const Condition cond = al);
1114 void vmov(const DwVfpRegister dst,
1069 const Register src1, 1115 const Register src1,
1070 const Register src2, 1116 const Register src2,
1071 const Condition cond = al); 1117 const Condition cond = al);
1072 void vmov(const Register dst1, 1118 void vmov(const Register dst1,
1073 const Register dst2, 1119 const Register dst2,
1074 const DwVfpRegister src, 1120 const DwVfpRegister src,
1075 const Condition cond = al); 1121 const Condition cond = al);
1076 void vmov(const SwVfpRegister dst, 1122 void vmov(const SwVfpRegister dst,
1077 const Register src, 1123 const Register src,
1078 const Condition cond = al); 1124 const Condition cond = al);
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 public: 1534 public:
1489 explicit EnsureSpace(Assembler* assembler) { 1535 explicit EnsureSpace(Assembler* assembler) {
1490 assembler->CheckBuffer(); 1536 assembler->CheckBuffer();
1491 } 1537 }
1492 }; 1538 };
1493 1539
1494 1540
1495 } } // namespace v8::internal 1541 } } // namespace v8::internal
1496 1542
1497 #endif // V8_ARM_ASSEMBLER_ARM_H_ 1543 #endif // V8_ARM_ASSEMBLER_ARM_H_
OLDNEW
« no previous file with comments | « no previous file | src/arm/assembler-arm.cc » ('j') | src/arm/code-stubs-arm.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698