| 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 |