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

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: Address more comments 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/assembler-arm-inl.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 inline static DwVfpRegister FromAllocationIndex(int index);
205 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
206 return from_code(index);
207 }
208 317
209 static const char* AllocationIndexToString(int index) { 318 inline static const char* AllocationIndexToString(int index);
210 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
211 const char* const names[] = {
212 "d0",
213 "d1",
214 "d2",
215 "d3",
216 "d4",
217 "d5",
218 "d6",
219 "d7",
220 "d8",
221 "d9",
222 "d10",
223 "d11",
224 "d12",
225 "d13"
226 };
227 return names[index];
228 }
229 319
230 static DwVfpRegister from_code(int code) { 320 static DwVfpRegister from_code(int code) {
231 DwVfpRegister r = { code }; 321 DwVfpRegister r = { code };
232 return r; 322 return r;
233 } 323 }
234 324
235 // Supporting d0 to d15, can be later extended to d31. 325 bool is_valid() const {
236 bool is_valid() const { return 0 <= code_ && code_ < 16; } 326 return 0 <= code_ && code_ < NumAvailableRegisters();
327 }
237 bool is(DwVfpRegister reg) const { return code_ == reg.code_; } 328 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
238 SwVfpRegister low() const { 329 SwVfpRegister low() const {
330 ASSERT(code_ < 16);
239 SwVfpRegister reg; 331 SwVfpRegister reg;
240 reg.code_ = code_ * 2; 332 reg.code_ = code_ * 2;
241 333
242 ASSERT(reg.is_valid()); 334 ASSERT(reg.is_valid());
243 return reg; 335 return reg;
244 } 336 }
245 SwVfpRegister high() const { 337 SwVfpRegister high() const {
338 ASSERT(code_ < 16);
246 SwVfpRegister reg; 339 SwVfpRegister reg;
247 reg.code_ = (code_ * 2) + 1; 340 reg.code_ = (code_ * 2) + 1;
248 341
249 ASSERT(reg.is_valid()); 342 ASSERT(reg.is_valid());
250 return reg; 343 return reg;
251 } 344 }
252 int code() const { 345 int code() const {
253 ASSERT(is_valid()); 346 ASSERT(is_valid());
254 return code_; 347 return code_;
255 } 348 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 const DwVfpRegister d6 = { 6 }; 408 const DwVfpRegister d6 = { 6 };
316 const DwVfpRegister d7 = { 7 }; 409 const DwVfpRegister d7 = { 7 };
317 const DwVfpRegister d8 = { 8 }; 410 const DwVfpRegister d8 = { 8 };
318 const DwVfpRegister d9 = { 9 }; 411 const DwVfpRegister d9 = { 9 };
319 const DwVfpRegister d10 = { 10 }; 412 const DwVfpRegister d10 = { 10 };
320 const DwVfpRegister d11 = { 11 }; 413 const DwVfpRegister d11 = { 11 };
321 const DwVfpRegister d12 = { 12 }; 414 const DwVfpRegister d12 = { 12 };
322 const DwVfpRegister d13 = { 13 }; 415 const DwVfpRegister d13 = { 13 };
323 const DwVfpRegister d14 = { 14 }; 416 const DwVfpRegister d14 = { 14 };
324 const DwVfpRegister d15 = { 15 }; 417 const DwVfpRegister d15 = { 15 };
418 const DwVfpRegister d16 = { 16 };
419 const DwVfpRegister d17 = { 17 };
420 const DwVfpRegister d18 = { 18 };
421 const DwVfpRegister d19 = { 19 };
422 const DwVfpRegister d20 = { 20 };
423 const DwVfpRegister d21 = { 21 };
424 const DwVfpRegister d22 = { 22 };
425 const DwVfpRegister d23 = { 23 };
426 const DwVfpRegister d24 = { 24 };
427 const DwVfpRegister d25 = { 25 };
428 const DwVfpRegister d26 = { 26 };
429 const DwVfpRegister d27 = { 27 };
430 const DwVfpRegister d28 = { 28 };
431 const DwVfpRegister d29 = { 29 };
432 const DwVfpRegister d30 = { 30 };
433 const DwVfpRegister d31 = { 31 };
325 434
326 // Aliases for double registers. Defined using #define instead of 435 // Aliases for double registers. Defined using #define instead of
327 // "static const DwVfpRegister&" because Clang complains otherwise when a 436 // "static const DwVfpRegister&" because Clang complains otherwise when a
328 // compilation unit that includes this header doesn't use the variables. 437 // compilation unit that includes this header doesn't use the variables.
329 #define kFirstCalleeSavedDoubleReg d8 438 #define kFirstCalleeSavedDoubleReg d8
330 #define kLastCalleeSavedDoubleReg d15 439 #define kLastCalleeSavedDoubleReg d15
331 #define kDoubleRegZero d14 440 #define kDoubleRegZero d14
332 #define kScratchDoubleReg d15 441 #define kScratchDoubleReg d15
333 442
334 443
335 // Coprocessor register 444 // Coprocessor register
336 struct CRegister { 445 struct CRegister {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 Register rn_; // base 600 Register rn_; // base
492 Register rm_; // register offset 601 Register rm_; // register offset
493 int32_t offset_; // valid if rm_ == no_reg 602 int32_t offset_; // valid if rm_ == no_reg
494 ShiftOp shift_op_; 603 ShiftOp shift_op_;
495 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg 604 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
496 AddrMode am_; // bits P, U, and W 605 AddrMode am_; // bits P, U, and W
497 606
498 friend class Assembler; 607 friend class Assembler;
499 }; 608 };
500 609
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; 610 extern const Instr kMovLrPc;
610 extern const Instr kLdrPCMask; 611 extern const Instr kLdrPCMask;
611 extern const Instr kLdrPCPattern; 612 extern const Instr kLdrPCPattern;
612 extern const Instr kBlxRegMask; 613 extern const Instr kBlxRegMask;
613 extern const Instr kBlxRegPattern; 614 extern const Instr kBlxRegPattern;
614 extern const Instr kBlxIp; 615 extern const Instr kBlxIp;
615 616
616 extern const Instr kMovMvnMask; 617 extern const Instr kMovMvnMask;
617 extern const Instr kMovMvnPattern; 618 extern const Instr kMovMvnPattern;
618 extern const Instr kMovMvnFlip; 619 extern const Instr kMovMvnFlip;
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 LFlag l = Short, Condition cond = al); 988 LFlag l = Short, Condition cond = al);
988 void ldc(Coprocessor coproc, CRegister crd, Register base, int option, 989 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
989 LFlag l = Short, Condition cond = al); 990 LFlag l = Short, Condition cond = al);
990 991
991 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src, 992 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
992 LFlag l = Short); // v5 and above 993 LFlag l = Short); // v5 and above
993 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option, 994 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
994 LFlag l = Short); // v5 and above 995 LFlag l = Short); // v5 and above
995 996
996 // Support for VFP. 997 // Support for VFP.
997 // All these APIs support S0 to S31 and D0 to D15. 998 // 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 999
1002 void vldr(const DwVfpRegister dst, 1000 void vldr(const DwVfpRegister dst,
1003 const Register base, 1001 const Register base,
1004 int offset, 1002 int offset,
1005 const Condition cond = al); 1003 const Condition cond = al);
1006 void vldr(const DwVfpRegister dst, 1004 void vldr(const DwVfpRegister dst,
1007 const MemOperand& src, 1005 const MemOperand& src,
1008 const Condition cond = al); 1006 const Condition cond = al);
1009 1007
1010 void vldr(const SwVfpRegister dst, 1008 void vldr(const SwVfpRegister dst,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1059 double imm, 1057 double imm,
1060 const Register scratch = no_reg, 1058 const Register scratch = no_reg,
1061 const Condition cond = al); 1059 const Condition cond = al);
1062 void vmov(const SwVfpRegister dst, 1060 void vmov(const SwVfpRegister dst,
1063 const SwVfpRegister src, 1061 const SwVfpRegister src,
1064 const Condition cond = al); 1062 const Condition cond = al);
1065 void vmov(const DwVfpRegister dst, 1063 void vmov(const DwVfpRegister dst,
1066 const DwVfpRegister src, 1064 const DwVfpRegister src,
1067 const Condition cond = al); 1065 const Condition cond = al);
1068 void vmov(const DwVfpRegister dst, 1066 void vmov(const DwVfpRegister dst,
1067 int index,
1068 const Register src,
1069 const Condition cond = al);
1070 void vmov(const DwVfpRegister dst,
1069 const Register src1, 1071 const Register src1,
1070 const Register src2, 1072 const Register src2,
1071 const Condition cond = al); 1073 const Condition cond = al);
1072 void vmov(const Register dst1, 1074 void vmov(const Register dst1,
1073 const Register dst2, 1075 const Register dst2,
1074 const DwVfpRegister src, 1076 const DwVfpRegister src,
1075 const Condition cond = al); 1077 const Condition cond = al);
1076 void vmov(const SwVfpRegister dst, 1078 void vmov(const SwVfpRegister dst,
1077 const Register src, 1079 const Register src,
1078 const Condition cond = al); 1080 const Condition cond = al);
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 public: 1490 public:
1489 explicit EnsureSpace(Assembler* assembler) { 1491 explicit EnsureSpace(Assembler* assembler) {
1490 assembler->CheckBuffer(); 1492 assembler->CheckBuffer();
1491 } 1493 }
1492 }; 1494 };
1493 1495
1494 1496
1495 } } // namespace v8::internal 1497 } } // namespace v8::internal
1496 1498
1497 #endif // V8_ARM_ASSEMBLER_ARM_H_ 1499 #endif // V8_ARM_ASSEMBLER_ARM_H_
OLDNEW
« no previous file with comments | « no previous file | src/arm/assembler-arm.cc » ('j') | src/arm/assembler-arm-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698