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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 | 615 |
627 void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } | 616 void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } |
628 void movsx_w(Register dst, const Operand& src); | 617 void movsx_w(Register dst, const Operand& src); |
629 | 618 |
630 void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } | 619 void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } |
631 void movzx_b(Register dst, const Operand& src); | 620 void movzx_b(Register dst, const Operand& src); |
632 | 621 |
633 void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } | 622 void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } |
634 void movzx_w(Register dst, const Operand& src); | 623 void movzx_w(Register dst, const Operand& src); |
635 | 624 |
636 // Conditional moves | |
637 void cmov(Condition cc, Register dst, Register src) { | |
638 cmov(cc, dst, Operand(src)); | |
639 } | |
640 void cmov(Condition cc, Register dst, const Operand& src); | |
641 | |
642 // Flag management. | 625 // Flag management. |
643 void cld(); | 626 void cld(); |
644 | 627 |
645 // Repetitive string instructions. | 628 // Repetitive string instructions. |
646 void rep_movs(); | 629 void rep_movs(); |
647 void rep_stos(); | 630 void rep_stos(); |
648 void stos(); | 631 void stos(); |
649 | 632 |
650 // Exchange two registers | 633 // Exchange two registers |
651 void xchg(Register dst, Register src); | 634 void xchg(Register dst, Register src); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
888 void fwait(); | 871 void fwait(); |
889 void fnclex(); | 872 void fnclex(); |
890 | 873 |
891 void frndint(); | 874 void frndint(); |
892 | 875 |
893 void sahf(); | 876 void sahf(); |
894 void setcc(Condition cc, Register reg); | 877 void setcc(Condition cc, Register reg); |
895 | 878 |
896 void cpuid(); | 879 void cpuid(); |
897 | 880 |
898 // SSE instructions | |
899 void movaps(XMMRegister dst, XMMRegister src); | |
900 void shufps(XMMRegister dst, XMMRegister src, byte imm8); | |
901 | |
902 void andps(XMMRegister dst, const Operand& src); | |
903 void andps(XMMRegister dst, XMMRegister src) { andps(dst, Operand(src)); } | |
904 void xorps(XMMRegister dst, const Operand& src); | |
905 void xorps(XMMRegister dst, XMMRegister src) { xorps(dst, Operand(src)); } | |
906 void orps(XMMRegister dst, const Operand& src); | |
907 void orps(XMMRegister dst, XMMRegister src) { orps(dst, Operand(src)); } | |
908 | |
909 void addps(XMMRegister dst, const Operand& src); | |
910 void addps(XMMRegister dst, XMMRegister src) { addps(dst, Operand(src)); } | |
911 void subps(XMMRegister dst, const Operand& src); | |
912 void subps(XMMRegister dst, XMMRegister src) { subps(dst, Operand(src)); } | |
913 void mulps(XMMRegister dst, const Operand& src); | |
914 void mulps(XMMRegister dst, XMMRegister src) { mulps(dst, Operand(src)); } | |
915 void divps(XMMRegister dst, const Operand& src); | |
916 void divps(XMMRegister dst, XMMRegister src) { divps(dst, Operand(src)); } | |
917 | |
918 // SSE2 instructions | |
919 void cvttss2si(Register dst, const Operand& src); | |
920 void cvttss2si(Register dst, XMMRegister src) { | |
921 cvttss2si(dst, Operand(src)); | |
922 } | |
923 void cvttsd2si(Register dst, const Operand& src); | |
924 void cvtsd2si(Register dst, XMMRegister src); | |
925 | |
926 void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); } | |
927 void cvtsi2sd(XMMRegister dst, const Operand& src); | |
928 void cvtss2sd(XMMRegister dst, XMMRegister src); | |
929 void cvtsd2ss(XMMRegister dst, XMMRegister src); | |
930 | |
931 void addsd(XMMRegister dst, XMMRegister src); | |
932 void addsd(XMMRegister dst, const Operand& src); | |
933 void subsd(XMMRegister dst, XMMRegister src); | |
934 void mulsd(XMMRegister dst, XMMRegister src); | |
935 void mulsd(XMMRegister dst, const Operand& src); | |
936 void divsd(XMMRegister dst, XMMRegister src); | |
937 void xorpd(XMMRegister dst, XMMRegister src); | |
938 void sqrtsd(XMMRegister dst, XMMRegister src); | |
939 | |
940 void andpd(XMMRegister dst, XMMRegister src); | |
941 void orpd(XMMRegister dst, XMMRegister src); | |
942 | |
943 void ucomisd(XMMRegister dst, XMMRegister src) { ucomisd(dst, Operand(src)); } | |
944 void ucomisd(XMMRegister dst, const Operand& src); | |
945 | |
946 enum RoundingMode { | |
947 kRoundToNearest = 0x0, | |
948 kRoundDown = 0x1, | |
949 kRoundUp = 0x2, | |
950 kRoundToZero = 0x3 | |
951 }; | |
952 | |
953 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode); | |
954 | |
955 void movmskpd(Register dst, XMMRegister src); | |
956 void movmskps(Register dst, XMMRegister src); | |
957 | |
958 void cmpltsd(XMMRegister dst, XMMRegister src); | |
959 void pcmpeqd(XMMRegister dst, XMMRegister src); | |
960 | |
961 void movdqa(XMMRegister dst, const Operand& src); | |
962 void movdqa(const Operand& dst, XMMRegister src); | |
963 void movdqu(XMMRegister dst, const Operand& src); | |
964 void movdqu(const Operand& dst, XMMRegister src); | |
965 void movdq(bool aligned, XMMRegister dst, const Operand& src) { | |
966 if (aligned) { | |
967 movdqa(dst, src); | |
968 } else { | |
969 movdqu(dst, src); | |
970 } | |
971 } | |
972 | |
973 void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); } | |
974 void movd(XMMRegister dst, const Operand& src); | |
975 void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); } | |
976 void movd(const Operand& dst, XMMRegister src); | |
977 void movsd(XMMRegister dst, XMMRegister src) { movsd(dst, Operand(src)); } | |
978 void movsd(XMMRegister dst, const Operand& src); | |
979 void movsd(const Operand& dst, XMMRegister src); | |
980 | |
981 | |
982 void movss(XMMRegister dst, const Operand& src); | |
983 void movss(const Operand& dst, XMMRegister src); | |
984 void movss(XMMRegister dst, XMMRegister src) { movss(dst, Operand(src)); } | |
985 void extractps(Register dst, XMMRegister src, byte imm8); | |
986 | |
987 void pand(XMMRegister dst, XMMRegister src); | |
988 void pxor(XMMRegister dst, XMMRegister src); | |
989 void por(XMMRegister dst, XMMRegister src); | |
990 void ptest(XMMRegister dst, XMMRegister src); | |
991 | |
992 void psllq(XMMRegister reg, int8_t shift); | |
993 void psllq(XMMRegister dst, XMMRegister src); | |
994 void psrlq(XMMRegister reg, int8_t shift); | |
995 void psrlq(XMMRegister dst, XMMRegister src); | |
996 void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle); | |
997 void pextrd(Register dst, XMMRegister src, int8_t offset) { | |
998 pextrd(Operand(dst), src, offset); | |
999 } | |
1000 void pextrd(const Operand& dst, XMMRegister src, int8_t offset); | |
1001 void pinsrd(XMMRegister dst, Register src, int8_t offset) { | |
1002 pinsrd(dst, Operand(src), offset); | |
1003 } | |
1004 void pinsrd(XMMRegister dst, const Operand& src, int8_t offset); | |
1005 | |
1006 // Parallel XMM operations. | |
1007 void movntdqa(XMMRegister dst, const Operand& src); | |
1008 void movntdq(const Operand& dst, XMMRegister src); | |
1009 // Prefetch src position into cache level. | |
1010 // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a | |
1011 // non-temporal | |
1012 void prefetch(const Operand& src, int level); | |
1013 // TODO(lrn): Need SFENCE for movnt? | 881 // TODO(lrn): Need SFENCE for movnt? |
1014 | 882 |
1015 // Debugging | 883 // Debugging |
1016 void Print(); | 884 void Print(); |
1017 | 885 |
1018 // Check the code size generated from label to here. | 886 // Check the code size generated from label to here. |
1019 int SizeOfCodeGeneratedSince(Label* label) { | 887 int SizeOfCodeGeneratedSince(Label* label) { |
1020 return pc_offset() - label->pos(); | 888 return pc_offset() - label->pos(); |
1021 } | 889 } |
1022 | 890 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 byte byte_at(int pos) { return buffer_[pos]; } | 928 byte byte_at(int pos) { return buffer_[pos]; } |
1061 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } | 929 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } |
1062 | 930 |
1063 // Allocate a constant pool of the correct size for the generated code. | 931 // Allocate a constant pool of the correct size for the generated code. |
1064 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); | 932 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); |
1065 | 933 |
1066 // Generate the constant pool for the generated code. | 934 // Generate the constant pool for the generated code. |
1067 void PopulateConstantPool(ConstantPoolArray* constant_pool); | 935 void PopulateConstantPool(ConstantPoolArray* constant_pool); |
1068 | 936 |
1069 protected: | 937 protected: |
1070 void emit_sse_operand(XMMRegister reg, const Operand& adr); | |
1071 void emit_sse_operand(XMMRegister dst, XMMRegister src); | |
1072 void emit_sse_operand(Register dst, XMMRegister src); | |
1073 void emit_sse_operand(XMMRegister dst, Register src); | |
1074 | |
1075 byte* addr_at(int pos) { return buffer_ + pos; } | 938 byte* addr_at(int pos) { return buffer_ + pos; } |
1076 | 939 |
1077 | 940 |
1078 private: | 941 private: |
1079 uint32_t long_at(int pos) { | 942 uint32_t long_at(int pos) { |
1080 return *reinterpret_cast<uint32_t*>(addr_at(pos)); | 943 return *reinterpret_cast<uint32_t*>(addr_at(pos)); |
1081 } | 944 } |
1082 void long_at_put(int pos, uint32_t x) { | 945 void long_at_put(int pos, uint32_t x) { |
1083 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; | 946 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; |
1084 } | 947 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 | 1021 |
1159 private: | 1022 private: |
1160 Assembler* assembler_; | 1023 Assembler* assembler_; |
1161 #ifdef DEBUG | 1024 #ifdef DEBUG |
1162 int space_before_; | 1025 int space_before_; |
1163 #endif | 1026 #endif |
1164 }; | 1027 }; |
1165 | 1028 |
1166 } } // namespace v8::internal | 1029 } } // namespace v8::internal |
1167 | 1030 |
1168 #endif // V8_IA32_ASSEMBLER_IA32_H_ | 1031 #endif // V8_X87_ASSEMBLER_X87_H_ |
OLD | NEW |