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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 const Register ra = { 31 }; // ra: Return address pointer. | 161 const Register ra = { 31 }; // ra: Return address pointer. |
162 | 162 |
163 | 163 |
164 int ToNumber(Register reg); | 164 int ToNumber(Register reg); |
165 | 165 |
166 Register ToRegister(int num); | 166 Register ToRegister(int num); |
167 | 167 |
168 // Coprocessor register. | 168 // Coprocessor register. |
169 struct FPURegister { | 169 struct FPURegister { |
170 static const int kNumRegisters = v8::internal::kNumFPURegisters; | 170 static const int kNumRegisters = v8::internal::kNumFPURegisters; |
171 // f0 has been excluded from allocation. This is following ia32 | 171 |
172 // where xmm0 is excluded. | 172 // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers |
173 static const int kNumAllocatableRegisters = 15; | 173 // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to |
| 174 // number of Double regs (64-bit regs, or FPU-reg-pairs). |
| 175 |
| 176 // A few double registers are reserved: one as a scratch register and one to |
| 177 // hold 0.0. |
| 178 // f28: 0.0 |
| 179 // f30: scratch register. |
| 180 static const int kNumReservedRegisters = 2; |
| 181 static const int kNumAllocatableRegisters = kNumRegisters / 2 - |
| 182 kNumReservedRegisters; |
| 183 |
174 | 184 |
175 static int ToAllocationIndex(FPURegister reg) { | 185 static int ToAllocationIndex(FPURegister reg) { |
176 ASSERT(reg.code() != 0); | |
177 ASSERT(reg.code() % 2 == 0); | 186 ASSERT(reg.code() % 2 == 0); |
178 return (reg.code() / 2) - 1; | 187 ASSERT(reg.code() / 2 < kNumAllocatableRegisters); |
| 188 ASSERT(reg.is_valid()); |
| 189 return (reg.code() / 2); |
179 } | 190 } |
180 | 191 |
181 static FPURegister FromAllocationIndex(int index) { | 192 static FPURegister FromAllocationIndex(int index) { |
182 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | 193 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
183 return from_code((index + 1) * 2); | 194 return from_code(index * 2); |
184 } | 195 } |
185 | 196 |
186 static const char* AllocationIndexToString(int index) { | 197 static const char* AllocationIndexToString(int index) { |
187 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | 198 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
188 const char* const names[] = { | 199 const char* const names[] = { |
| 200 "f0", |
189 "f2", | 201 "f2", |
190 "f4", | 202 "f4", |
191 "f6", | 203 "f6", |
192 "f8", | 204 "f8", |
193 "f10", | 205 "f10", |
194 "f12", | 206 "f12", |
195 "f14", | 207 "f14", |
196 "f16", | 208 "f16", |
197 "f18", | 209 "f18", |
198 "f20", | 210 "f20", |
199 "f22", | 211 "f22", |
200 "f24", | 212 "f24", |
201 "f26", | 213 "f26" |
202 "f28", | |
203 "f30" | |
204 }; | 214 }; |
205 return names[index]; | 215 return names[index]; |
206 } | 216 } |
207 | 217 |
208 static FPURegister from_code(int code) { | 218 static FPURegister from_code(int code) { |
209 FPURegister r = { code }; | 219 FPURegister r = { code }; |
210 return r; | 220 return r; |
211 } | 221 } |
212 | 222 |
213 bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; } | 223 bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; } |
214 bool is(FPURegister creg) const { return code_ == creg.code_; } | 224 bool is(FPURegister creg) const { return code_ == creg.code_; } |
| 225 FPURegister low() const { |
| 226 // Find low reg of a Double-reg pair, which is the reg itself. |
| 227 ASSERT(code_ % 2 == 0); // Specified Double reg must be even. |
| 228 FPURegister reg; |
| 229 reg.code_ = code_; |
| 230 ASSERT(reg.is_valid()); |
| 231 return reg; |
| 232 } |
| 233 FPURegister high() const { |
| 234 // Find high reg of a Doubel-reg pair, which is reg + 1. |
| 235 ASSERT(code_ % 2 == 0); // Specified Double reg must be even. |
| 236 FPURegister reg; |
| 237 reg.code_ = code_ + 1; |
| 238 ASSERT(reg.is_valid()); |
| 239 return reg; |
| 240 } |
| 241 |
215 int code() const { | 242 int code() const { |
216 ASSERT(is_valid()); | 243 ASSERT(is_valid()); |
217 return code_; | 244 return code_; |
218 } | 245 } |
219 int bit() const { | 246 int bit() const { |
220 ASSERT(is_valid()); | 247 ASSERT(is_valid()); |
221 return 1 << code_; | 248 return 1 << code_; |
222 } | 249 } |
223 void setcode(int f) { | 250 void setcode(int f) { |
224 code_ = f; | 251 code_ = f; |
225 ASSERT(is_valid()); | 252 ASSERT(is_valid()); |
226 } | 253 } |
227 // Unfortunately we can't make this private in a struct. | 254 // Unfortunately we can't make this private in a struct. |
228 int code_; | 255 int code_; |
229 }; | 256 }; |
230 | 257 |
| 258 // V8 now supports the O32 ABI, and the FPU Registers are organized as 32 |
| 259 // 32-bit registers, f0 through f31. When used as 'double' they are used |
| 260 // in pairs, starting with the even numbered register. So a double operation |
| 261 // on f0 really uses f0 and f1. |
| 262 // (Modern mips hardware also supports 32 64-bit registers, via setting |
| 263 // (priviledged) Status Register FR bit to 1. This is used by the N32 ABI, |
| 264 // but it is not in common use. Someday we will want to support this in v8.) |
| 265 |
| 266 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers. |
231 typedef FPURegister DoubleRegister; | 267 typedef FPURegister DoubleRegister; |
| 268 typedef FPURegister FloatRegister; |
232 | 269 |
233 const FPURegister no_creg = { -1 }; | 270 const FPURegister no_freg = { -1 }; |
234 | 271 |
235 const FPURegister f0 = { 0 }; // Return value in hard float mode. | 272 const FPURegister f0 = { 0 }; // Return value in hard float mode. |
236 const FPURegister f1 = { 1 }; | 273 const FPURegister f1 = { 1 }; |
237 const FPURegister f2 = { 2 }; | 274 const FPURegister f2 = { 2 }; |
238 const FPURegister f3 = { 3 }; | 275 const FPURegister f3 = { 3 }; |
239 const FPURegister f4 = { 4 }; | 276 const FPURegister f4 = { 4 }; |
240 const FPURegister f5 = { 5 }; | 277 const FPURegister f5 = { 5 }; |
241 const FPURegister f6 = { 6 }; | 278 const FPURegister f6 = { 6 }; |
242 const FPURegister f7 = { 7 }; | 279 const FPURegister f7 = { 7 }; |
243 const FPURegister f8 = { 8 }; | 280 const FPURegister f8 = { 8 }; |
(...skipping 14 matching lines...) Expand all Loading... |
258 const FPURegister f23 = { 23 }; | 295 const FPURegister f23 = { 23 }; |
259 const FPURegister f24 = { 24 }; | 296 const FPURegister f24 = { 24 }; |
260 const FPURegister f25 = { 25 }; | 297 const FPURegister f25 = { 25 }; |
261 const FPURegister f26 = { 26 }; | 298 const FPURegister f26 = { 26 }; |
262 const FPURegister f27 = { 27 }; | 299 const FPURegister f27 = { 27 }; |
263 const FPURegister f28 = { 28 }; | 300 const FPURegister f28 = { 28 }; |
264 const FPURegister f29 = { 29 }; | 301 const FPURegister f29 = { 29 }; |
265 const FPURegister f30 = { 30 }; | 302 const FPURegister f30 = { 30 }; |
266 const FPURegister f31 = { 31 }; | 303 const FPURegister f31 = { 31 }; |
267 | 304 |
| 305 const FPURegister kDoubleRegZero = f28; |
| 306 |
268 // FPU (coprocessor 1) control registers. | 307 // FPU (coprocessor 1) control registers. |
269 // Currently only FCSR (#31) is implemented. | 308 // Currently only FCSR (#31) is implemented. |
270 struct FPUControlRegister { | 309 struct FPUControlRegister { |
271 bool is_valid() const { return code_ == kFCSRRegister; } | 310 bool is_valid() const { return code_ == kFCSRRegister; } |
272 bool is(FPUControlRegister creg) const { return code_ == creg.code_; } | 311 bool is(FPUControlRegister creg) const { return code_ == creg.code_; } |
273 int code() const { | 312 int code() const { |
274 ASSERT(is_valid()); | 313 ASSERT(is_valid()); |
275 return code_; | 314 return code_; |
276 } | 315 } |
277 int bit() const { | 316 int bit() const { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 }; | 363 }; |
325 | 364 |
326 | 365 |
327 // On MIPS we have only one adressing mode with base_reg + offset. | 366 // On MIPS we have only one adressing mode with base_reg + offset. |
328 // Class MemOperand represents a memory operand in load and store instructions. | 367 // Class MemOperand represents a memory operand in load and store instructions. |
329 class MemOperand : public Operand { | 368 class MemOperand : public Operand { |
330 public: | 369 public: |
331 explicit MemOperand(Register rn, int32_t offset = 0); | 370 explicit MemOperand(Register rn, int32_t offset = 0); |
332 int32_t offset() const { return offset_; } | 371 int32_t offset() const { return offset_; } |
333 | 372 |
| 373 bool OffsetIsInt16Encodable() const { |
| 374 return is_int16(offset_); |
| 375 } |
| 376 |
334 private: | 377 private: |
335 int32_t offset_; | 378 int32_t offset_; |
336 | 379 |
337 friend class Assembler; | 380 friend class Assembler; |
338 }; | 381 }; |
339 | 382 |
340 | 383 |
341 // CpuFeatures keeps track of which features are supported by the target CPU. | 384 // CpuFeatures keeps track of which features are supported by the target CPU. |
342 // Supported features must be enabled by a Scope before use. | 385 // Supported features must be enabled by a Scope before use. |
343 class CpuFeatures : public AllStatic { | 386 class CpuFeatures : public AllStatic { |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 uint32_t jump_address(Label* L); | 540 uint32_t jump_address(Label* L); |
498 | 541 |
499 // Puts a labels target address at the given position. | 542 // Puts a labels target address at the given position. |
500 // The high 8 bits are set to zero. | 543 // The high 8 bits are set to zero. |
501 void label_at_put(Label* L, int at_offset); | 544 void label_at_put(Label* L, int at_offset); |
502 | 545 |
503 // Read/Modify the code target address in the branch/call instruction at pc. | 546 // Read/Modify the code target address in the branch/call instruction at pc. |
504 static Address target_address_at(Address pc); | 547 static Address target_address_at(Address pc); |
505 static void set_target_address_at(Address pc, Address target); | 548 static void set_target_address_at(Address pc, Address target); |
506 | 549 |
| 550 static void JumpLabelToJumpRegister(Address pc); |
| 551 |
507 // This sets the branch destination (which gets loaded at the call address). | 552 // This sets the branch destination (which gets loaded at the call address). |
508 // This is for calls and branches within generated code. | 553 // This is for calls and branches within generated code. |
509 inline static void set_target_at(Address instruction_payload, | 554 inline static void set_target_at(Address instruction_payload, |
510 Address target) { | 555 Address target) { |
511 set_target_address_at(instruction_payload, target); | 556 set_target_address_at(instruction_payload, target); |
512 } | 557 } |
513 | 558 |
514 // This sets the branch destination. | 559 // This sets the branch destination. |
515 // This is for calls and branches to runtime code. | 560 // This is for calls and branches to runtime code. |
516 inline static void set_external_target_at(Address instruction_payload, | 561 inline static void set_external_target_at(Address instruction_payload, |
(...skipping 10 matching lines...) Expand all Loading... |
527 // Here we are patching the address in the LUI/ORI instruction pair. | 572 // Here we are patching the address in the LUI/ORI instruction pair. |
528 // These values are used in the serialization process and must be zero for | 573 // These values are used in the serialization process and must be zero for |
529 // MIPS platform, as Code, Embedded Object or External-reference pointers | 574 // MIPS platform, as Code, Embedded Object or External-reference pointers |
530 // are split across two consecutive instructions and don't exist separately | 575 // are split across two consecutive instructions and don't exist separately |
531 // in the code, so the serializer should not step forwards in memory after | 576 // in the code, so the serializer should not step forwards in memory after |
532 // a target is resolved and written. | 577 // a target is resolved and written. |
533 static const int kCallTargetSize = 0 * kInstrSize; | 578 static const int kCallTargetSize = 0 * kInstrSize; |
534 static const int kExternalTargetSize = 0 * kInstrSize; | 579 static const int kExternalTargetSize = 0 * kInstrSize; |
535 | 580 |
536 // Number of consecutive instructions used to store 32bit constant. | 581 // Number of consecutive instructions used to store 32bit constant. |
537 // Used in RelocInfo::target_address_address() function to tell serializer | 582 // Before jump-optimizations, this constant was used in |
538 // address of the instruction that follows LUI/ORI instruction pair. | 583 // RelocInfo::target_address_address() function to tell serializer address of |
539 static const int kInstructionsFor32BitConstant = 2; | 584 // the instruction that follows LUI/ORI instruction pair. Now, with new jump |
| 585 // optimization, where jump-through-register instruction that usually |
| 586 // follows LUI/ORI pair is substituted with J/JAL, this constant equals |
| 587 // to 3 instructions (LUI+ORI+J/JAL/JR/JALR). |
| 588 static const int kInstructionsFor32BitConstant = 3; |
540 | 589 |
541 // Distance between the instruction referring to the address of the call | 590 // Distance between the instruction referring to the address of the call |
542 // target and the return address. | 591 // target and the return address. |
543 static const int kCallTargetAddressOffset = 4 * kInstrSize; | 592 static const int kCallTargetAddressOffset = 4 * kInstrSize; |
544 | 593 |
545 // Distance between start of patched return sequence and the emitted address | 594 // Distance between start of patched return sequence and the emitted address |
546 // to jump to. | 595 // to jump to. |
547 static const int kPatchReturnSequenceAddressOffset = 0; | 596 static const int kPatchReturnSequenceAddressOffset = 0; |
548 | 597 |
549 // Distance between start of patched debug break slot and the emitted address | 598 // Distance between start of patched debug break slot and the emitted address |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 665 } |
617 | 666 |
618 // Never use the int16_t b(l)cond version with a branch offset | 667 // Never use the int16_t b(l)cond version with a branch offset |
619 // instead of using the Label* version. | 668 // instead of using the Label* version. |
620 | 669 |
621 // Jump targets must be in the current 256 MB-aligned region. ie 28 bits. | 670 // Jump targets must be in the current 256 MB-aligned region. ie 28 bits. |
622 void j(int32_t target); | 671 void j(int32_t target); |
623 void jal(int32_t target); | 672 void jal(int32_t target); |
624 void jalr(Register rs, Register rd = ra); | 673 void jalr(Register rs, Register rd = ra); |
625 void jr(Register target); | 674 void jr(Register target); |
| 675 void j_or_jr(int32_t target, Register rs); |
| 676 void jal_or_jalr(int32_t target, Register rs); |
626 | 677 |
627 | 678 |
628 //-------Data-processing-instructions--------- | 679 //-------Data-processing-instructions--------- |
629 | 680 |
630 // Arithmetic. | 681 // Arithmetic. |
631 void addu(Register rd, Register rs, Register rt); | 682 void addu(Register rd, Register rs, Register rt); |
632 void subu(Register rd, Register rs, Register rt); | 683 void subu(Register rd, Register rs, Register rt); |
633 void mult(Register rs, Register rt); | 684 void mult(Register rs, Register rt); |
634 void multu(Register rs, Register rt); | 685 void multu(Register rs, Register rt); |
635 void div(Register rs, Register rt); | 686 void div(Register rs, Register rt); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 // Check if an instruction is a branch of some kind. | 936 // Check if an instruction is a branch of some kind. |
886 static bool IsBranch(Instr instr); | 937 static bool IsBranch(Instr instr); |
887 static bool IsBeq(Instr instr); | 938 static bool IsBeq(Instr instr); |
888 static bool IsBne(Instr instr); | 939 static bool IsBne(Instr instr); |
889 | 940 |
890 static bool IsJump(Instr instr); | 941 static bool IsJump(Instr instr); |
891 static bool IsJ(Instr instr); | 942 static bool IsJ(Instr instr); |
892 static bool IsLui(Instr instr); | 943 static bool IsLui(Instr instr); |
893 static bool IsOri(Instr instr); | 944 static bool IsOri(Instr instr); |
894 | 945 |
| 946 static bool IsJal(Instr instr); |
| 947 static bool IsJr(Instr instr); |
| 948 static bool IsJalr(Instr instr); |
| 949 |
895 static bool IsNop(Instr instr, unsigned int type); | 950 static bool IsNop(Instr instr, unsigned int type); |
896 static bool IsPop(Instr instr); | 951 static bool IsPop(Instr instr); |
897 static bool IsPush(Instr instr); | 952 static bool IsPush(Instr instr); |
898 static bool IsLwRegFpOffset(Instr instr); | 953 static bool IsLwRegFpOffset(Instr instr); |
899 static bool IsSwRegFpOffset(Instr instr); | 954 static bool IsSwRegFpOffset(Instr instr); |
900 static bool IsLwRegFpNegOffset(Instr instr); | 955 static bool IsLwRegFpNegOffset(Instr instr); |
901 static bool IsSwRegFpNegOffset(Instr instr); | 956 static bool IsSwRegFpNegOffset(Instr instr); |
902 | 957 |
903 static Register GetRtReg(Instr instr); | 958 static Register GetRtReg(Instr instr); |
904 static Register GetRsReg(Instr instr); | 959 static Register GetRsReg(Instr instr); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 } | 1024 } |
970 | 1025 |
971 bool is_trampoline_pool_blocked() const { | 1026 bool is_trampoline_pool_blocked() const { |
972 return trampoline_pool_blocked_nesting_ > 0; | 1027 return trampoline_pool_blocked_nesting_ > 0; |
973 } | 1028 } |
974 | 1029 |
975 bool has_exception() const { | 1030 bool has_exception() const { |
976 return internal_trampoline_exception_; | 1031 return internal_trampoline_exception_; |
977 } | 1032 } |
978 | 1033 |
| 1034 void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi); |
| 1035 |
979 bool is_trampoline_emitted() const { | 1036 bool is_trampoline_emitted() const { |
980 return trampoline_emitted_; | 1037 return trampoline_emitted_; |
981 } | 1038 } |
982 | 1039 |
983 // Temporarily block automatic assembly buffer growth. | 1040 // Temporarily block automatic assembly buffer growth. |
984 void StartBlockGrowBuffer() { | 1041 void StartBlockGrowBuffer() { |
985 ASSERT(!block_buffer_growth_); | 1042 ASSERT(!block_buffer_growth_); |
986 block_buffer_growth_ = true; | 1043 block_buffer_growth_ = true; |
987 } | 1044 } |
988 | 1045 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 class EnsureSpace BASE_EMBEDDED { | 1254 class EnsureSpace BASE_EMBEDDED { |
1198 public: | 1255 public: |
1199 explicit EnsureSpace(Assembler* assembler) { | 1256 explicit EnsureSpace(Assembler* assembler) { |
1200 assembler->CheckBuffer(); | 1257 assembler->CheckBuffer(); |
1201 } | 1258 } |
1202 }; | 1259 }; |
1203 | 1260 |
1204 } } // namespace v8::internal | 1261 } } // namespace v8::internal |
1205 | 1262 |
1206 #endif // V8_ARM_ASSEMBLER_MIPS_H_ | 1263 #endif // V8_ARM_ASSEMBLER_MIPS_H_ |
OLD | NEW |