OLD | NEW |
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 are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // 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 16 matching lines...) Expand all Loading... |
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 // The original source code covered by the above license above has been | 31 // The original source code covered by the above license above has been |
32 // modified significantly by Google Inc. | 32 // modified significantly by Google Inc. |
33 // Copyright 2011 the V8 project authors. All rights reserved. | 33 // Copyright 2011 the V8 project authors. All rights reserved. |
34 | 34 |
35 // A light-weight IA32 Assembler. | 35 // A light-weight IA32 Assembler. |
36 | 36 |
37 #ifndef V8_IA32_ASSEMBLER_IA32_H_ | 37 #ifndef V8_X87_ASSEMBLER_X87_H_ |
38 #define V8_IA32_ASSEMBLER_IA32_H_ | 38 #define V8_X87_ASSEMBLER_X87_H_ |
39 | 39 |
40 #include "isolate.h" | 40 #include "isolate.h" |
41 #include "serialize.h" | 41 #include "serialize.h" |
42 | 42 |
43 namespace v8 { | 43 namespace v8 { |
44 namespace internal { | 44 namespace internal { |
45 | 45 |
46 // CPU Registers. | 46 // CPU Registers. |
47 // | 47 // |
48 // 1) We would prefer to use an enum, but enum values are assignment- | 48 // 1) We would prefer to use an enum, but enum values are assignment- |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 return (reg.code() >= 6) ? reg.code() - 2 : reg.code(); | 134 return (reg.code() >= 6) ? reg.code() - 2 : reg.code(); |
135 } | 135 } |
136 | 136 |
137 | 137 |
138 inline Register Register::FromAllocationIndex(int index) { | 138 inline Register Register::FromAllocationIndex(int index) { |
139 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 139 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); |
140 return (index >= 4) ? from_code(index + 2) : from_code(index); | 140 return (index >= 4) ? from_code(index + 2) : from_code(index); |
141 } | 141 } |
142 | 142 |
143 | 143 |
144 struct XMMRegister { | 144 struct X87Register { |
145 static const int kMaxNumAllocatableRegisters = 7; | 145 static const int kMaxNumAllocatableRegisters = 8; |
146 static const int kMaxNumRegisters = 8; | 146 static const int kMaxNumRegisters = 8; |
147 static int NumAllocatableRegisters() { | 147 static int NumAllocatableRegisters() { |
148 return kMaxNumAllocatableRegisters; | 148 return kMaxNumAllocatableRegisters; |
149 } | 149 } |
150 | 150 |
151 static int ToAllocationIndex(XMMRegister reg) { | 151 static int ToAllocationIndex(X87Register reg) { |
152 ASSERT(reg.code() != 0); | 152 return reg.code_; |
153 return reg.code() - 1; | |
154 } | 153 } |
155 | 154 |
156 static XMMRegister FromAllocationIndex(int index) { | 155 static const char* AllocationIndexToString(int index) { |
157 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 156 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); |
158 return from_code(index + 1); | 157 const char* const names[] = { |
| 158 "stX_0", "stX_1", "stX_2", "stX_3", "stX_4", |
| 159 "stX_5", "stX_6", "stX_7" |
| 160 }; |
| 161 return names[index]; |
159 } | 162 } |
160 | 163 |
161 static XMMRegister from_code(int code) { | 164 static X87Register FromAllocationIndex(int index) { |
162 XMMRegister result = { code }; | 165 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); |
| 166 X87Register result; |
| 167 result.code_ = index; |
163 return result; | 168 return result; |
164 } | 169 } |
165 | 170 |
166 bool is_valid() const { | 171 bool is_valid() const { |
167 return 0 <= code_ && code_ < kMaxNumRegisters; | 172 return 0 <= code_ && code_ < kMaxNumRegisters; |
168 } | 173 } |
169 | 174 |
170 int code() const { | 175 int code() const { |
171 ASSERT(is_valid()); | 176 ASSERT(is_valid()); |
172 return code_; | 177 return code_; |
173 } | 178 } |
174 | 179 |
175 bool is(XMMRegister reg) const { return code_ == reg.code_; } | 180 bool is(X87Register reg) const { |
176 | 181 return code_ == reg.code_; |
177 static const char* AllocationIndexToString(int index) { | |
178 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | |
179 const char* const names[] = { | |
180 "xmm1", | |
181 "xmm2", | |
182 "xmm3", | |
183 "xmm4", | |
184 "xmm5", | |
185 "xmm6", | |
186 "xmm7" | |
187 }; | |
188 return names[index]; | |
189 } | 182 } |
190 | 183 |
191 int code_; | 184 int code_; |
192 }; | 185 }; |
193 | 186 |
194 | 187 |
195 typedef XMMRegister DoubleRegister; | 188 typedef X87Register DoubleRegister; |
196 | 189 |
197 | 190 |
198 const XMMRegister xmm0 = { 0 }; | 191 const X87Register stX_0 = { 0 }; |
199 const XMMRegister xmm1 = { 1 }; | 192 const X87Register stX_1 = { 1 }; |
200 const XMMRegister xmm2 = { 2 }; | 193 const X87Register stX_2 = { 2 }; |
201 const XMMRegister xmm3 = { 3 }; | 194 const X87Register stX_3 = { 3 }; |
202 const XMMRegister xmm4 = { 4 }; | 195 const X87Register stX_4 = { 4 }; |
203 const XMMRegister xmm5 = { 5 }; | 196 const X87Register stX_5 = { 5 }; |
204 const XMMRegister xmm6 = { 6 }; | 197 const X87Register stX_6 = { 6 }; |
205 const XMMRegister xmm7 = { 7 }; | 198 const X87Register stX_7 = { 7 }; |
206 const XMMRegister no_xmm_reg = { -1 }; | |
207 | 199 |
208 | 200 |
209 enum Condition { | 201 enum Condition { |
210 // any value < 0 is considered no_condition | 202 // any value < 0 is considered no_condition |
211 no_condition = -1, | 203 no_condition = -1, |
212 | 204 |
213 overflow = 0, | 205 overflow = 0, |
214 no_overflow = 1, | 206 no_overflow = 1, |
215 below = 2, | 207 below = 2, |
216 above_equal = 3, | 208 above_equal = 3, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 times_8 = 3, | 307 times_8 = 3, |
316 times_int_size = times_4, | 308 times_int_size = times_4, |
317 times_half_pointer_size = times_2, | 309 times_half_pointer_size = times_2, |
318 times_pointer_size = times_4, | 310 times_pointer_size = times_4, |
319 times_twice_pointer_size = times_8 | 311 times_twice_pointer_size = times_8 |
320 }; | 312 }; |
321 | 313 |
322 | 314 |
323 class Operand BASE_EMBEDDED { | 315 class Operand BASE_EMBEDDED { |
324 public: | 316 public: |
325 // XMM reg | |
326 INLINE(explicit Operand(XMMRegister xmm_reg)); | |
327 | |
328 // [disp/r] | 317 // [disp/r] |
329 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); | 318 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); |
330 // disp only must always be relocated | 319 // disp only must always be relocated |
331 | 320 |
332 // [base + disp/r] | 321 // [base + disp/r] |
333 explicit Operand(Register base, int32_t disp, | 322 explicit Operand(Register base, int32_t disp, |
334 RelocInfo::Mode rmode = RelocInfo::NONE32); | 323 RelocInfo::Mode rmode = RelocInfo::NONE32); |
335 | 324 |
336 // [base + index*scale + disp/r] | 325 // [base + index*scale + disp/r] |
337 explicit Operand(Register base, | 326 explicit Operand(Register base, |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 | 611 |
623 void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } | 612 void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } |
624 void movsx_w(Register dst, const Operand& src); | 613 void movsx_w(Register dst, const Operand& src); |
625 | 614 |
626 void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } | 615 void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } |
627 void movzx_b(Register dst, const Operand& src); | 616 void movzx_b(Register dst, const Operand& src); |
628 | 617 |
629 void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } | 618 void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } |
630 void movzx_w(Register dst, const Operand& src); | 619 void movzx_w(Register dst, const Operand& src); |
631 | 620 |
632 // Conditional moves | |
633 void cmov(Condition cc, Register dst, Register src) { | |
634 cmov(cc, dst, Operand(src)); | |
635 } | |
636 void cmov(Condition cc, Register dst, const Operand& src); | |
637 | |
638 // Flag management. | 621 // Flag management. |
639 void cld(); | 622 void cld(); |
640 | 623 |
641 // Repetitive string instructions. | 624 // Repetitive string instructions. |
642 void rep_movs(); | 625 void rep_movs(); |
643 void rep_stos(); | 626 void rep_stos(); |
644 void stos(); | 627 void stos(); |
645 | 628 |
646 // Exchange two registers | 629 // Exchange two registers |
647 void xchg(Register dst, Register src); | 630 void xchg(Register dst, Register src); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 void fwait(); | 867 void fwait(); |
885 void fnclex(); | 868 void fnclex(); |
886 | 869 |
887 void frndint(); | 870 void frndint(); |
888 | 871 |
889 void sahf(); | 872 void sahf(); |
890 void setcc(Condition cc, Register reg); | 873 void setcc(Condition cc, Register reg); |
891 | 874 |
892 void cpuid(); | 875 void cpuid(); |
893 | 876 |
894 // SSE instructions | |
895 void movaps(XMMRegister dst, XMMRegister src); | |
896 void shufps(XMMRegister dst, XMMRegister src, byte imm8); | |
897 | |
898 void andps(XMMRegister dst, const Operand& src); | |
899 void andps(XMMRegister dst, XMMRegister src) { andps(dst, Operand(src)); } | |
900 void xorps(XMMRegister dst, const Operand& src); | |
901 void xorps(XMMRegister dst, XMMRegister src) { xorps(dst, Operand(src)); } | |
902 void orps(XMMRegister dst, const Operand& src); | |
903 void orps(XMMRegister dst, XMMRegister src) { orps(dst, Operand(src)); } | |
904 | |
905 void addps(XMMRegister dst, const Operand& src); | |
906 void addps(XMMRegister dst, XMMRegister src) { addps(dst, Operand(src)); } | |
907 void subps(XMMRegister dst, const Operand& src); | |
908 void subps(XMMRegister dst, XMMRegister src) { subps(dst, Operand(src)); } | |
909 void mulps(XMMRegister dst, const Operand& src); | |
910 void mulps(XMMRegister dst, XMMRegister src) { mulps(dst, Operand(src)); } | |
911 void divps(XMMRegister dst, const Operand& src); | |
912 void divps(XMMRegister dst, XMMRegister src) { divps(dst, Operand(src)); } | |
913 | |
914 // SSE2 instructions | |
915 void cvttss2si(Register dst, const Operand& src); | |
916 void cvttss2si(Register dst, XMMRegister src) { | |
917 cvttss2si(dst, Operand(src)); | |
918 } | |
919 void cvttsd2si(Register dst, const Operand& src); | |
920 void cvtsd2si(Register dst, XMMRegister src); | |
921 | |
922 void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); } | |
923 void cvtsi2sd(XMMRegister dst, const Operand& src); | |
924 void cvtss2sd(XMMRegister dst, XMMRegister src); | |
925 void cvtsd2ss(XMMRegister dst, XMMRegister src); | |
926 | |
927 void addsd(XMMRegister dst, XMMRegister src); | |
928 void addsd(XMMRegister dst, const Operand& src); | |
929 void subsd(XMMRegister dst, XMMRegister src); | |
930 void mulsd(XMMRegister dst, XMMRegister src); | |
931 void mulsd(XMMRegister dst, const Operand& src); | |
932 void divsd(XMMRegister dst, XMMRegister src); | |
933 void xorpd(XMMRegister dst, XMMRegister src); | |
934 void sqrtsd(XMMRegister dst, XMMRegister src); | |
935 | |
936 void andpd(XMMRegister dst, XMMRegister src); | |
937 void orpd(XMMRegister dst, XMMRegister src); | |
938 | |
939 void ucomisd(XMMRegister dst, XMMRegister src) { ucomisd(dst, Operand(src)); } | |
940 void ucomisd(XMMRegister dst, const Operand& src); | |
941 | |
942 enum RoundingMode { | |
943 kRoundToNearest = 0x0, | |
944 kRoundDown = 0x1, | |
945 kRoundUp = 0x2, | |
946 kRoundToZero = 0x3 | |
947 }; | |
948 | |
949 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode); | |
950 | |
951 void movmskpd(Register dst, XMMRegister src); | |
952 void movmskps(Register dst, XMMRegister src); | |
953 | |
954 void cmpltsd(XMMRegister dst, XMMRegister src); | |
955 void pcmpeqd(XMMRegister dst, XMMRegister src); | |
956 | |
957 void movdqa(XMMRegister dst, const Operand& src); | |
958 void movdqa(const Operand& dst, XMMRegister src); | |
959 void movdqu(XMMRegister dst, const Operand& src); | |
960 void movdqu(const Operand& dst, XMMRegister src); | |
961 void movdq(bool aligned, XMMRegister dst, const Operand& src) { | |
962 if (aligned) { | |
963 movdqa(dst, src); | |
964 } else { | |
965 movdqu(dst, src); | |
966 } | |
967 } | |
968 | |
969 void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); } | |
970 void movd(XMMRegister dst, const Operand& src); | |
971 void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); } | |
972 void movd(const Operand& dst, XMMRegister src); | |
973 void movsd(XMMRegister dst, XMMRegister src) { movsd(dst, Operand(src)); } | |
974 void movsd(XMMRegister dst, const Operand& src); | |
975 void movsd(const Operand& dst, XMMRegister src); | |
976 | |
977 | |
978 void movss(XMMRegister dst, const Operand& src); | |
979 void movss(const Operand& dst, XMMRegister src); | |
980 void movss(XMMRegister dst, XMMRegister src) { movss(dst, Operand(src)); } | |
981 void extractps(Register dst, XMMRegister src, byte imm8); | |
982 | |
983 void pand(XMMRegister dst, XMMRegister src); | |
984 void pxor(XMMRegister dst, XMMRegister src); | |
985 void por(XMMRegister dst, XMMRegister src); | |
986 void ptest(XMMRegister dst, XMMRegister src); | |
987 | |
988 void psllq(XMMRegister reg, int8_t shift); | |
989 void psllq(XMMRegister dst, XMMRegister src); | |
990 void psrlq(XMMRegister reg, int8_t shift); | |
991 void psrlq(XMMRegister dst, XMMRegister src); | |
992 void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle); | |
993 void pextrd(Register dst, XMMRegister src, int8_t offset) { | |
994 pextrd(Operand(dst), src, offset); | |
995 } | |
996 void pextrd(const Operand& dst, XMMRegister src, int8_t offset); | |
997 void pinsrd(XMMRegister dst, Register src, int8_t offset) { | |
998 pinsrd(dst, Operand(src), offset); | |
999 } | |
1000 void pinsrd(XMMRegister dst, const Operand& src, int8_t offset); | |
1001 | |
1002 // Parallel XMM operations. | |
1003 void movntdqa(XMMRegister dst, const Operand& src); | |
1004 void movntdq(const Operand& dst, XMMRegister src); | |
1005 // Prefetch src position into cache level. | |
1006 // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a | |
1007 // non-temporal | |
1008 void prefetch(const Operand& src, int level); | |
1009 // TODO(lrn): Need SFENCE for movnt? | 877 // TODO(lrn): Need SFENCE for movnt? |
1010 | 878 |
1011 // Debugging | 879 // Debugging |
1012 void Print(); | 880 void Print(); |
1013 | 881 |
1014 // Check the code size generated from label to here. | 882 // Check the code size generated from label to here. |
1015 int SizeOfCodeGeneratedSince(Label* label) { | 883 int SizeOfCodeGeneratedSince(Label* label) { |
1016 return pc_offset() - label->pos(); | 884 return pc_offset() - label->pos(); |
1017 } | 885 } |
1018 | 886 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 byte byte_at(int pos) { return buffer_[pos]; } | 924 byte byte_at(int pos) { return buffer_[pos]; } |
1057 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } | 925 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } |
1058 | 926 |
1059 // Allocate a constant pool of the correct size for the generated code. | 927 // Allocate a constant pool of the correct size for the generated code. |
1060 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); | 928 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); |
1061 | 929 |
1062 // Generate the constant pool for the generated code. | 930 // Generate the constant pool for the generated code. |
1063 void PopulateConstantPool(ConstantPoolArray* constant_pool); | 931 void PopulateConstantPool(ConstantPoolArray* constant_pool); |
1064 | 932 |
1065 protected: | 933 protected: |
1066 void emit_sse_operand(XMMRegister reg, const Operand& adr); | |
1067 void emit_sse_operand(XMMRegister dst, XMMRegister src); | |
1068 void emit_sse_operand(Register dst, XMMRegister src); | |
1069 void emit_sse_operand(XMMRegister dst, Register src); | |
1070 | |
1071 byte* addr_at(int pos) { return buffer_ + pos; } | 934 byte* addr_at(int pos) { return buffer_ + pos; } |
1072 | 935 |
1073 | 936 |
1074 private: | 937 private: |
1075 uint32_t long_at(int pos) { | 938 uint32_t long_at(int pos) { |
1076 return *reinterpret_cast<uint32_t*>(addr_at(pos)); | 939 return *reinterpret_cast<uint32_t*>(addr_at(pos)); |
1077 } | 940 } |
1078 void long_at_put(int pos, uint32_t x) { | 941 void long_at_put(int pos, uint32_t x) { |
1079 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; | 942 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; |
1080 } | 943 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 | 1017 |
1155 private: | 1018 private: |
1156 Assembler* assembler_; | 1019 Assembler* assembler_; |
1157 #ifdef DEBUG | 1020 #ifdef DEBUG |
1158 int space_before_; | 1021 int space_before_; |
1159 #endif | 1022 #endif |
1160 }; | 1023 }; |
1161 | 1024 |
1162 } } // namespace v8::internal | 1025 } } // namespace v8::internal |
1163 | 1026 |
1164 #endif // V8_IA32_ASSEMBLER_IA32_H_ | 1027 #endif // V8_X87_ASSEMBLER_X87_H_ |
OLD | NEW |