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 19 matching lines...) Expand all Loading... |
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_IA32_ASSEMBLER_IA32_H_ |
38 #define V8_IA32_ASSEMBLER_IA32_H_ | 38 #define V8_IA32_ASSEMBLER_IA32_H_ |
39 | 39 |
| 40 #include <deque> |
| 41 |
40 #include "src/isolate.h" | 42 #include "src/isolate.h" |
41 #include "src/serialize.h" | 43 #include "src/serialize.h" |
42 | 44 |
43 namespace v8 { | 45 namespace v8 { |
44 namespace internal { | 46 namespace internal { |
45 | 47 |
46 // CPU Registers. | 48 // CPU Registers. |
47 // | 49 // |
48 // 1) We would prefer to use an enum, but enum values are assignment- | 50 // 1) We would prefer to use an enum, but enum values are assignment- |
49 // compatible with int, which has caused code-generation bugs. | 51 // compatible with int, which has caused code-generation bugs. |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 ScaleFactor scale, | 352 ScaleFactor scale, |
351 int32_t disp, | 353 int32_t disp, |
352 RelocInfo::Mode rmode = RelocInfo::NONE32); | 354 RelocInfo::Mode rmode = RelocInfo::NONE32); |
353 | 355 |
354 // [index*scale + disp/r] | 356 // [index*scale + disp/r] |
355 explicit Operand(Register index, | 357 explicit Operand(Register index, |
356 ScaleFactor scale, | 358 ScaleFactor scale, |
357 int32_t disp, | 359 int32_t disp, |
358 RelocInfo::Mode rmode = RelocInfo::NONE32); | 360 RelocInfo::Mode rmode = RelocInfo::NONE32); |
359 | 361 |
| 362 static Operand JumpTable(Register index, ScaleFactor scale, Label* table) { |
| 363 return Operand(index, scale, reinterpret_cast<int32_t>(table), |
| 364 RelocInfo::INTERNAL_REFERENCE); |
| 365 } |
| 366 |
360 static Operand StaticVariable(const ExternalReference& ext) { | 367 static Operand StaticVariable(const ExternalReference& ext) { |
361 return Operand(reinterpret_cast<int32_t>(ext.address()), | 368 return Operand(reinterpret_cast<int32_t>(ext.address()), |
362 RelocInfo::EXTERNAL_REFERENCE); | 369 RelocInfo::EXTERNAL_REFERENCE); |
363 } | 370 } |
364 | 371 |
365 static Operand StaticArray(Register index, | 372 static Operand StaticArray(Register index, |
366 ScaleFactor scale, | 373 ScaleFactor scale, |
367 const ExternalReference& arr) { | 374 const ExternalReference& arr) { |
368 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), | 375 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), |
369 RelocInfo::EXTERNAL_REFERENCE); | 376 RelocInfo::EXTERNAL_REFERENCE); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 // be no displacement at position zero, because there is always at least one | 430 // be no displacement at position zero, because there is always at least one |
424 // instruction byte before the displacement). | 431 // instruction byte before the displacement). |
425 // | 432 // |
426 // Displacement _data field layout | 433 // Displacement _data field layout |
427 // | 434 // |
428 // |31.....2|1......0| | 435 // |31.....2|1......0| |
429 // [ next | type | | 436 // [ next | type | |
430 | 437 |
431 class Displacement BASE_EMBEDDED { | 438 class Displacement BASE_EMBEDDED { |
432 public: | 439 public: |
433 enum Type { | 440 enum Type { UNCONDITIONAL_JUMP, CODE_RELATIVE, OTHER, CODE_ABSOLUTE }; |
434 UNCONDITIONAL_JUMP, | |
435 CODE_RELATIVE, | |
436 OTHER | |
437 }; | |
438 | 441 |
439 int data() const { return data_; } | 442 int data() const { return data_; } |
440 Type type() const { return TypeField::decode(data_); } | 443 Type type() const { return TypeField::decode(data_); } |
441 void next(Label* L) const { | 444 void next(Label* L) const { |
442 int n = NextField::decode(data_); | 445 int n = NextField::decode(data_); |
443 n > 0 ? L->link_to(n) : L->Unuse(); | 446 n > 0 ? L->link_to(n) : L->Unuse(); |
444 } | 447 } |
445 void link_to(Label* L) { init(L, type()); } | 448 void link_to(Label* L) { init(L, type()); } |
446 | 449 |
447 explicit Displacement(int data) { data_ = data; } | 450 explicit Displacement(int data) { data_ = data; } |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 void bts(Register dst, Register src) { bts(Operand(dst), src); } | 800 void bts(Register dst, Register src) { bts(Operand(dst), src); } |
798 void bts(const Operand& dst, Register src); | 801 void bts(const Operand& dst, Register src); |
799 void bsr(Register dst, Register src) { bsr(dst, Operand(src)); } | 802 void bsr(Register dst, Register src) { bsr(dst, Operand(src)); } |
800 void bsr(Register dst, const Operand& src); | 803 void bsr(Register dst, const Operand& src); |
801 | 804 |
802 // Miscellaneous | 805 // Miscellaneous |
803 void hlt(); | 806 void hlt(); |
804 void int3(); | 807 void int3(); |
805 void nop(); | 808 void nop(); |
806 void ret(int imm16); | 809 void ret(int imm16); |
| 810 void ud2(); |
807 | 811 |
808 // Label operations & relative jumps (PPUM Appendix D) | 812 // Label operations & relative jumps (PPUM Appendix D) |
809 // | 813 // |
810 // Takes a branch opcode (cc) and a label (L) and generates | 814 // Takes a branch opcode (cc) and a label (L) and generates |
811 // either a backward branch or a forward branch and links it | 815 // either a backward branch or a forward branch and links it |
812 // to the label fixup chain. Usage: | 816 // to the label fixup chain. Usage: |
813 // | 817 // |
814 // Label L; // unbound label | 818 // Label L; // unbound label |
815 // j(cc, &L); // forward branch to unbound label | 819 // j(cc, &L); // forward branch to unbound label |
816 // bind(&L); // bind label to the current pc | 820 // bind(&L); // bind label to the current pc |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 void RecordComment(const char* msg, bool force = false); | 1265 void RecordComment(const char* msg, bool force = false); |
1262 | 1266 |
1263 // Record a deoptimization reason that can be used by a log or cpu profiler. | 1267 // Record a deoptimization reason that can be used by a log or cpu profiler. |
1264 // Use --trace-deopt to enable. | 1268 // Use --trace-deopt to enable. |
1265 void RecordDeoptReason(const int reason, const int raw_position); | 1269 void RecordDeoptReason(const int reason, const int raw_position); |
1266 | 1270 |
1267 // Writes a single byte or word of data in the code stream. Used for | 1271 // Writes a single byte or word of data in the code stream. Used for |
1268 // inline tables, e.g., jump-tables. | 1272 // inline tables, e.g., jump-tables. |
1269 void db(uint8_t data); | 1273 void db(uint8_t data); |
1270 void dd(uint32_t data); | 1274 void dd(uint32_t data); |
| 1275 void dd(Label* label); |
1271 | 1276 |
1272 // Check if there is less than kGap bytes available in the buffer. | 1277 // Check if there is less than kGap bytes available in the buffer. |
1273 // If this is the case, we need to grow the buffer before emitting | 1278 // If this is the case, we need to grow the buffer before emitting |
1274 // an instruction or relocation information. | 1279 // an instruction or relocation information. |
1275 inline bool buffer_overflow() const { | 1280 inline bool buffer_overflow() const { |
1276 return pc_ >= reloc_info_writer.pos() - kGap; | 1281 return pc_ >= reloc_info_writer.pos() - kGap; |
1277 } | 1282 } |
1278 | 1283 |
1279 // Get the number of bytes available in the buffer. | 1284 // Get the number of bytes available in the buffer. |
1280 inline int available_space() const { return reloc_info_writer.pos() - pc_; } | 1285 inline int available_space() const { return reloc_info_writer.pos() - pc_; } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 void emit_arith_b(int op1, int op2, Register dst, int imm8); | 1341 void emit_arith_b(int op1, int op2, Register dst, int imm8); |
1337 | 1342 |
1338 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) | 1343 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) |
1339 // with a given destination expression and an immediate operand. It attempts | 1344 // with a given destination expression and an immediate operand. It attempts |
1340 // to use the shortest encoding possible. | 1345 // to use the shortest encoding possible. |
1341 // sel specifies the /n in the modrm byte (see the Intel PRM). | 1346 // sel specifies the /n in the modrm byte (see the Intel PRM). |
1342 void emit_arith(int sel, Operand dst, const Immediate& x); | 1347 void emit_arith(int sel, Operand dst, const Immediate& x); |
1343 | 1348 |
1344 void emit_operand(Register reg, const Operand& adr); | 1349 void emit_operand(Register reg, const Operand& adr); |
1345 | 1350 |
| 1351 void emit_label(Label* label); |
| 1352 |
1346 void emit_farith(int b1, int b2, int i); | 1353 void emit_farith(int b1, int b2, int i); |
1347 | 1354 |
1348 // Emit vex prefix | 1355 // Emit vex prefix |
1349 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 }; | 1356 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 }; |
1350 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128 }; | 1357 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128 }; |
1351 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 }; | 1358 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 }; |
1352 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x2 }; | 1359 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x2 }; |
1353 inline void emit_vex_prefix(XMMRegister v, VectorLength l, SIMDPrefix pp, | 1360 inline void emit_vex_prefix(XMMRegister v, VectorLength l, SIMDPrefix pp, |
1354 LeadingOpcode m, VexW w); | 1361 LeadingOpcode m, VexW w); |
1355 | 1362 |
1356 // labels | 1363 // labels |
1357 void print(Label* L); | 1364 void print(Label* L); |
1358 void bind_to(Label* L, int pos); | 1365 void bind_to(Label* L, int pos); |
1359 | 1366 |
1360 // displacements | 1367 // displacements |
1361 inline Displacement disp_at(Label* L); | 1368 inline Displacement disp_at(Label* L); |
1362 inline void disp_at_put(Label* L, Displacement disp); | 1369 inline void disp_at_put(Label* L, Displacement disp); |
1363 inline void emit_disp(Label* L, Displacement::Type type); | 1370 inline void emit_disp(Label* L, Displacement::Type type); |
1364 inline void emit_near_disp(Label* L); | 1371 inline void emit_near_disp(Label* L); |
1365 | 1372 |
1366 // record reloc info for current pc_ | 1373 // record reloc info for current pc_ |
1367 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1374 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
1368 | 1375 |
1369 friend class CodePatcher; | 1376 friend class CodePatcher; |
1370 friend class EnsureSpace; | 1377 friend class EnsureSpace; |
1371 | 1378 |
| 1379 // Internal reference positions, required for (potential) patching in |
| 1380 // GrowBuffer(); contains only those internal references whose labels |
| 1381 // are already bound. |
| 1382 std::deque<int> internal_reference_positions_; |
| 1383 |
1372 // code generation | 1384 // code generation |
1373 RelocInfoWriter reloc_info_writer; | 1385 RelocInfoWriter reloc_info_writer; |
1374 | 1386 |
1375 PositionsRecorder positions_recorder_; | 1387 PositionsRecorder positions_recorder_; |
1376 friend class PositionsRecorder; | 1388 friend class PositionsRecorder; |
1377 }; | 1389 }; |
1378 | 1390 |
1379 | 1391 |
1380 // Helper class that ensures that there is enough space for generating | 1392 // Helper class that ensures that there is enough space for generating |
1381 // instructions and relocation information. The constructor makes | 1393 // instructions and relocation information. The constructor makes |
(...skipping 18 matching lines...) Expand all Loading... |
1400 private: | 1412 private: |
1401 Assembler* assembler_; | 1413 Assembler* assembler_; |
1402 #ifdef DEBUG | 1414 #ifdef DEBUG |
1403 int space_before_; | 1415 int space_before_; |
1404 #endif | 1416 #endif |
1405 }; | 1417 }; |
1406 | 1418 |
1407 } } // namespace v8::internal | 1419 } } // namespace v8::internal |
1408 | 1420 |
1409 #endif // V8_IA32_ASSEMBLER_IA32_H_ | 1421 #endif // V8_IA32_ASSEMBLER_IA32_H_ |
OLD | NEW |