| 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 | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are 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 23 matching lines...) Expand all Loading... |
| 34 // modified significantly by Google Inc. | 34 // modified significantly by Google Inc. |
| 35 // Copyright 2010 the V8 project authors. All rights reserved. | 35 // Copyright 2010 the V8 project authors. All rights reserved. |
| 36 | 36 |
| 37 // A light-weight ARM Assembler | 37 // A light-weight ARM Assembler |
| 38 // Generates user mode instructions for the ARM architecture up to version 5 | 38 // Generates user mode instructions for the ARM architecture up to version 5 |
| 39 | 39 |
| 40 #ifndef V8_ARM_ASSEMBLER_ARM_H_ | 40 #ifndef V8_ARM_ASSEMBLER_ARM_H_ |
| 41 #define V8_ARM_ASSEMBLER_ARM_H_ | 41 #define V8_ARM_ASSEMBLER_ARM_H_ |
| 42 #include <stdio.h> | 42 #include <stdio.h> |
| 43 #include "assembler.h" | 43 #include "assembler.h" |
| 44 #include "constants-arm.h" |
| 44 #include "serialize.h" | 45 #include "serialize.h" |
| 45 | 46 |
| 46 namespace v8 { | 47 namespace v8 { |
| 47 namespace internal { | 48 namespace internal { |
| 48 | 49 |
| 49 // CPU Registers. | 50 // CPU Registers. |
| 50 // | 51 // |
| 51 // 1) We would prefer to use an enum, but enum values are assignment- | 52 // 1) We would prefer to use an enum, but enum values are assignment- |
| 52 // compatible with int, which has caused code-generation bugs. | 53 // compatible with int, which has caused code-generation bugs. |
| 53 // | 54 // |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 165 |
| 165 | 166 |
| 166 // Double word VFP register. | 167 // Double word VFP register. |
| 167 struct DwVfpRegister { | 168 struct DwVfpRegister { |
| 168 // d0 has been excluded from allocation. This is following ia32 | 169 // d0 has been excluded from allocation. This is following ia32 |
| 169 // where xmm0 is excluded. This should be revisited. | 170 // where xmm0 is excluded. This should be revisited. |
| 170 // Currently d0 is used as a scratch register. | 171 // Currently d0 is used as a scratch register. |
| 171 // d1 has also been excluded from allocation to be used as a scratch | 172 // d1 has also been excluded from allocation to be used as a scratch |
| 172 // register as well. | 173 // register as well. |
| 173 static const int kNumRegisters = 16; | 174 static const int kNumRegisters = 16; |
| 174 static const int kNumAllocatableRegisters = 14; | 175 static const int kNumAllocatableRegisters = 15; |
| 175 | 176 |
| 176 static int ToAllocationIndex(DwVfpRegister reg) { | 177 static int ToAllocationIndex(DwVfpRegister reg) { |
| 177 ASSERT(reg.code() != 0); | 178 ASSERT(reg.code() != 0); |
| 178 return reg.code() - 1; | 179 return reg.code() - 1; |
| 179 } | 180 } |
| 180 | 181 |
| 181 static DwVfpRegister FromAllocationIndex(int index) { | 182 static DwVfpRegister FromAllocationIndex(int index) { |
| 182 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | 183 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 183 return from_code(index + 2); | 184 return from_code(index + 1); |
| 184 } | 185 } |
| 185 | 186 |
| 186 static const char* AllocationIndexToString(int index) { | 187 static const char* AllocationIndexToString(int index) { |
| 187 ASSERT(index >= 0 && index < kNumAllocatableRegisters); | 188 ASSERT(index >= 0 && index < kNumAllocatableRegisters); |
| 188 const char* const names[] = { | 189 const char* const names[] = { |
| 190 "d1", |
| 189 "d2", | 191 "d2", |
| 190 "d3", | 192 "d3", |
| 191 "d4", | 193 "d4", |
| 192 "d5", | 194 "d5", |
| 193 "d6", | 195 "d6", |
| 194 "d7", | 196 "d7", |
| 195 "d8", | 197 "d8", |
| 196 "d9", | 198 "d9", |
| 197 "d10", | 199 "d10", |
| 198 "d11", | 200 "d11", |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 const DwVfpRegister d7 = { 7 }; | 294 const DwVfpRegister d7 = { 7 }; |
| 293 const DwVfpRegister d8 = { 8 }; | 295 const DwVfpRegister d8 = { 8 }; |
| 294 const DwVfpRegister d9 = { 9 }; | 296 const DwVfpRegister d9 = { 9 }; |
| 295 const DwVfpRegister d10 = { 10 }; | 297 const DwVfpRegister d10 = { 10 }; |
| 296 const DwVfpRegister d11 = { 11 }; | 298 const DwVfpRegister d11 = { 11 }; |
| 297 const DwVfpRegister d12 = { 12 }; | 299 const DwVfpRegister d12 = { 12 }; |
| 298 const DwVfpRegister d13 = { 13 }; | 300 const DwVfpRegister d13 = { 13 }; |
| 299 const DwVfpRegister d14 = { 14 }; | 301 const DwVfpRegister d14 = { 14 }; |
| 300 const DwVfpRegister d15 = { 15 }; | 302 const DwVfpRegister d15 = { 15 }; |
| 301 | 303 |
| 302 // VFP FPSCR constants. | |
| 303 static const uint32_t kVFPNConditionFlagBit = 1 << 31; | |
| 304 static const uint32_t kVFPZConditionFlagBit = 1 << 30; | |
| 305 static const uint32_t kVFPCConditionFlagBit = 1 << 29; | |
| 306 static const uint32_t kVFPVConditionFlagBit = 1 << 28; | |
| 307 | |
| 308 static const uint32_t kVFPFlushToZeroMask = 1 << 24; | |
| 309 | |
| 310 static const uint32_t kVFPRoundingModeMask = 3 << 22; | |
| 311 static const uint32_t kVFPRoundToMinusInfinityBits = 2 << 22; | |
| 312 | |
| 313 static const uint32_t kVFPExceptionMask = 0xf; | |
| 314 | 304 |
| 315 // Coprocessor register | 305 // Coprocessor register |
| 316 struct CRegister { | 306 struct CRegister { |
| 317 bool is_valid() const { return 0 <= code_ && code_ < 16; } | 307 bool is_valid() const { return 0 <= code_ && code_ < 16; } |
| 318 bool is(CRegister creg) const { return code_ == creg.code_; } | 308 bool is(CRegister creg) const { return code_ == creg.code_; } |
| 319 int code() const { | 309 int code() const { |
| 320 ASSERT(is_valid()); | 310 ASSERT(is_valid()); |
| 321 return code_; | 311 return code_; |
| 322 } | 312 } |
| 323 int bit() const { | 313 int bit() const { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 p9 = 9, | 354 p9 = 9, |
| 365 p10 = 10, | 355 p10 = 10, |
| 366 p11 = 11, | 356 p11 = 11, |
| 367 p12 = 12, | 357 p12 = 12, |
| 368 p13 = 13, | 358 p13 = 13, |
| 369 p14 = 14, | 359 p14 = 14, |
| 370 p15 = 15 | 360 p15 = 15 |
| 371 }; | 361 }; |
| 372 | 362 |
| 373 | 363 |
| 374 // Condition field in instructions. | |
| 375 enum Condition { | |
| 376 // any value < 0 is considered no_condition | |
| 377 no_condition = -1, | |
| 378 | |
| 379 eq = 0 << 28, // Z set equal. | |
| 380 ne = 1 << 28, // Z clear not equal. | |
| 381 nz = 1 << 28, // Z clear not zero. | |
| 382 cs = 2 << 28, // C set carry set. | |
| 383 hs = 2 << 28, // C set unsigned higher or same. | |
| 384 cc = 3 << 28, // C clear carry clear. | |
| 385 lo = 3 << 28, // C clear unsigned lower. | |
| 386 mi = 4 << 28, // N set negative. | |
| 387 pl = 5 << 28, // N clear positive or zero. | |
| 388 vs = 6 << 28, // V set overflow. | |
| 389 vc = 7 << 28, // V clear no overflow. | |
| 390 hi = 8 << 28, // C set, Z clear unsigned higher. | |
| 391 ls = 9 << 28, // C clear or Z set unsigned lower or same. | |
| 392 ge = 10 << 28, // N == V greater or equal. | |
| 393 lt = 11 << 28, // N != V less than. | |
| 394 gt = 12 << 28, // Z clear, N == V greater than. | |
| 395 le = 13 << 28, // Z set or N != V less then or equal | |
| 396 al = 14 << 28 // always. | |
| 397 }; | |
| 398 | |
| 399 | |
| 400 // Returns the equivalent of !cc. | |
| 401 inline Condition NegateCondition(Condition cc) { | |
| 402 ASSERT(cc != al); | |
| 403 return static_cast<Condition>(cc ^ ne); | |
| 404 } | |
| 405 | |
| 406 | |
| 407 // Corresponds to transposing the operands of a comparison. | |
| 408 inline Condition ReverseCondition(Condition cc) { | |
| 409 switch (cc) { | |
| 410 case lo: | |
| 411 return hi; | |
| 412 case hi: | |
| 413 return lo; | |
| 414 case hs: | |
| 415 return ls; | |
| 416 case ls: | |
| 417 return hs; | |
| 418 case lt: | |
| 419 return gt; | |
| 420 case gt: | |
| 421 return lt; | |
| 422 case ge: | |
| 423 return le; | |
| 424 case le: | |
| 425 return ge; | |
| 426 default: | |
| 427 return cc; | |
| 428 }; | |
| 429 } | |
| 430 | |
| 431 | |
| 432 // Branch hints are not used on the ARM. They are defined so that they can | |
| 433 // appear in shared function signatures, but will be ignored in ARM | |
| 434 // implementations. | |
| 435 enum Hint { no_hint }; | |
| 436 | |
| 437 // Hints are not used on the arm. Negating is trivial. | |
| 438 inline Hint NegateHint(Hint ignored) { return no_hint; } | |
| 439 | |
| 440 | |
| 441 // ----------------------------------------------------------------------------- | |
| 442 // Addressing modes and instruction variants | |
| 443 | |
| 444 // Shifter operand shift operation | |
| 445 enum ShiftOp { | |
| 446 LSL = 0 << 5, | |
| 447 LSR = 1 << 5, | |
| 448 ASR = 2 << 5, | |
| 449 ROR = 3 << 5, | |
| 450 RRX = -1 | |
| 451 }; | |
| 452 | |
| 453 | |
| 454 // Condition code updating mode | |
| 455 enum SBit { | |
| 456 SetCC = 1 << 20, // set condition code | |
| 457 LeaveCC = 0 << 20 // leave condition code unchanged | |
| 458 }; | |
| 459 | |
| 460 | |
| 461 // Status register selection | |
| 462 enum SRegister { | |
| 463 CPSR = 0 << 22, | |
| 464 SPSR = 1 << 22 | |
| 465 }; | |
| 466 | |
| 467 | |
| 468 // Status register fields | |
| 469 enum SRegisterField { | |
| 470 CPSR_c = CPSR | 1 << 16, | |
| 471 CPSR_x = CPSR | 1 << 17, | |
| 472 CPSR_s = CPSR | 1 << 18, | |
| 473 CPSR_f = CPSR | 1 << 19, | |
| 474 SPSR_c = SPSR | 1 << 16, | |
| 475 SPSR_x = SPSR | 1 << 17, | |
| 476 SPSR_s = SPSR | 1 << 18, | |
| 477 SPSR_f = SPSR | 1 << 19 | |
| 478 }; | |
| 479 | |
| 480 // Status register field mask (or'ed SRegisterField enum values) | |
| 481 typedef uint32_t SRegisterFieldMask; | |
| 482 | |
| 483 | |
| 484 // Memory operand addressing mode | |
| 485 enum AddrMode { | |
| 486 // bit encoding P U W | |
| 487 Offset = (8|4|0) << 21, // offset (without writeback to base) | |
| 488 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback | |
| 489 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback | |
| 490 NegOffset = (8|0|0) << 21, // negative offset (without writeback to base) | |
| 491 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback | |
| 492 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback | |
| 493 }; | |
| 494 | |
| 495 | |
| 496 // Load/store multiple addressing mode | |
| 497 enum BlockAddrMode { | |
| 498 // bit encoding P U W | |
| 499 da = (0|0|0) << 21, // decrement after | |
| 500 ia = (0|4|0) << 21, // increment after | |
| 501 db = (8|0|0) << 21, // decrement before | |
| 502 ib = (8|4|0) << 21, // increment before | |
| 503 da_w = (0|0|1) << 21, // decrement after with writeback to base | |
| 504 ia_w = (0|4|1) << 21, // increment after with writeback to base | |
| 505 db_w = (8|0|1) << 21, // decrement before with writeback to base | |
| 506 ib_w = (8|4|1) << 21 // increment before with writeback to base | |
| 507 }; | |
| 508 | |
| 509 | |
| 510 // Coprocessor load/store operand size | |
| 511 enum LFlag { | |
| 512 Long = 1 << 22, // long load/store coprocessor | |
| 513 Short = 0 << 22 // short load/store coprocessor | |
| 514 }; | |
| 515 | |
| 516 | |
| 517 // ----------------------------------------------------------------------------- | 364 // ----------------------------------------------------------------------------- |
| 518 // Machine instruction Operands | 365 // Machine instruction Operands |
| 519 | 366 |
| 520 // Class Operand represents a shifter operand in data processing instructions | 367 // Class Operand represents a shifter operand in data processing instructions |
| 521 class Operand BASE_EMBEDDED { | 368 class Operand BASE_EMBEDDED { |
| 522 public: | 369 public: |
| 523 // immediate | 370 // immediate |
| 524 INLINE(explicit Operand(int32_t immediate, | 371 INLINE(explicit Operand(int32_t immediate, |
| 525 RelocInfo::Mode rmode = RelocInfo::NONE)); | 372 RelocInfo::Mode rmode = RelocInfo::NONE)); |
| 526 INLINE(explicit Operand(const ExternalReference& f)); | 373 INLINE(explicit Operand(const ExternalReference& f)); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 unsigned supported_; | 510 unsigned supported_; |
| 664 unsigned enabled_; | 511 unsigned enabled_; |
| 665 unsigned found_by_runtime_probing_; | 512 unsigned found_by_runtime_probing_; |
| 666 | 513 |
| 667 friend class Isolate; | 514 friend class Isolate; |
| 668 | 515 |
| 669 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); | 516 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); |
| 670 }; | 517 }; |
| 671 | 518 |
| 672 | 519 |
| 673 typedef int32_t Instr; | |
| 674 | |
| 675 | |
| 676 extern const Instr kMovLrPc; | 520 extern const Instr kMovLrPc; |
| 677 extern const Instr kLdrPCMask; | 521 extern const Instr kLdrPCMask; |
| 678 extern const Instr kLdrPCPattern; | 522 extern const Instr kLdrPCPattern; |
| 679 extern const Instr kBlxRegMask; | 523 extern const Instr kBlxRegMask; |
| 680 extern const Instr kBlxRegPattern; | 524 extern const Instr kBlxRegPattern; |
| 681 | 525 |
| 682 extern const Instr kMovMvnMask; | 526 extern const Instr kMovMvnMask; |
| 683 extern const Instr kMovMvnPattern; | 527 extern const Instr kMovMvnPattern; |
| 684 extern const Instr kMovMvnFlip; | 528 extern const Instr kMovMvnFlip; |
| 685 | 529 |
| 686 extern const Instr kMovLeaveCCMask; | 530 extern const Instr kMovLeaveCCMask; |
| 687 extern const Instr kMovLeaveCCPattern; | 531 extern const Instr kMovLeaveCCPattern; |
| 688 extern const Instr kMovwMask; | 532 extern const Instr kMovwMask; |
| 689 extern const Instr kMovwPattern; | 533 extern const Instr kMovwPattern; |
| 690 extern const Instr kMovwLeaveCCFlip; | 534 extern const Instr kMovwLeaveCCFlip; |
| 691 | 535 |
| 692 extern const Instr kCmpCmnMask; | 536 extern const Instr kCmpCmnMask; |
| 693 extern const Instr kCmpCmnPattern; | 537 extern const Instr kCmpCmnPattern; |
| 694 extern const Instr kCmpCmnFlip; | 538 extern const Instr kCmpCmnFlip; |
| 695 | |
| 696 extern const Instr kALUMask; | |
| 697 extern const Instr kAddPattern; | |
| 698 extern const Instr kSubPattern; | |
| 699 extern const Instr kAndPattern; | |
| 700 extern const Instr kBicPattern; | |
| 701 extern const Instr kAddSubFlip; | 539 extern const Instr kAddSubFlip; |
| 702 extern const Instr kAndBicFlip; | 540 extern const Instr kAndBicFlip; |
| 703 | 541 |
| 542 |
| 543 |
| 704 class Assembler : public Malloced { | 544 class Assembler : public Malloced { |
| 705 public: | 545 public: |
| 706 // Create an assembler. Instructions and relocation information are emitted | 546 // Create an assembler. Instructions and relocation information are emitted |
| 707 // into a buffer, with the instructions starting from the beginning and the | 547 // into a buffer, with the instructions starting from the beginning and the |
| 708 // relocation information starting from the end of the buffer. See CodeDesc | 548 // relocation information starting from the end of the buffer. See CodeDesc |
| 709 // for a detailed comment on the layout (globals.h). | 549 // for a detailed comment on the layout (globals.h). |
| 710 // | 550 // |
| 711 // If the provided buffer is NULL, the assembler allocates and grows its own | 551 // If the provided buffer is NULL, the assembler allocates and grows its own |
| 712 // buffer, and buffer_size determines the initial buffer size. The buffer is | 552 // buffer, and buffer_size determines the initial buffer size. The buffer is |
| 713 // owned by the assembler and deallocated upon destruction of the assembler. | 553 // owned by the assembler and deallocated upon destruction of the assembler. |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1006 const MemOperand& src, Condition cond = al); | 846 const MemOperand& src, Condition cond = al); |
| 1007 void strd(Register src1, | 847 void strd(Register src1, |
| 1008 Register src2, | 848 Register src2, |
| 1009 const MemOperand& dst, Condition cond = al); | 849 const MemOperand& dst, Condition cond = al); |
| 1010 | 850 |
| 1011 // Load/Store multiple instructions | 851 // Load/Store multiple instructions |
| 1012 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); | 852 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al); |
| 1013 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); | 853 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al); |
| 1014 | 854 |
| 1015 // Exception-generating instructions and debugging support | 855 // Exception-generating instructions and debugging support |
| 1016 static const int kDefaultStopCode = -1; | |
| 1017 void stop(const char* msg, | 856 void stop(const char* msg, |
| 1018 Condition cond = al, | 857 Condition cond = al, |
| 1019 int32_t code = kDefaultStopCode); | 858 int32_t code = kDefaultStopCode); |
| 1020 | 859 |
| 1021 void bkpt(uint32_t imm16); // v5 and above | 860 void bkpt(uint32_t imm16); // v5 and above |
| 1022 void svc(uint32_t imm24, Condition cond = al); | 861 void svc(uint32_t imm24, Condition cond = al); |
| 1023 | 862 |
| 1024 // Coprocessor instructions | 863 // Coprocessor instructions |
| 1025 | 864 |
| 1026 void cdp(Coprocessor coproc, int opcode_1, | 865 void cdp(Coprocessor coproc, int opcode_1, |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1245 // Mark address of the ExitJSFrame code. | 1084 // Mark address of the ExitJSFrame code. |
| 1246 void RecordJSReturn(); | 1085 void RecordJSReturn(); |
| 1247 | 1086 |
| 1248 // Mark address of a debug break slot. | 1087 // Mark address of a debug break slot. |
| 1249 void RecordDebugBreakSlot(); | 1088 void RecordDebugBreakSlot(); |
| 1250 | 1089 |
| 1251 // Record a comment relocation entry that can be used by a disassembler. | 1090 // Record a comment relocation entry that can be used by a disassembler. |
| 1252 // Use --code-comments to enable. | 1091 // Use --code-comments to enable. |
| 1253 void RecordComment(const char* msg); | 1092 void RecordComment(const char* msg); |
| 1254 | 1093 |
| 1255 // Writes a single byte or word of data in the code stream. Used for | 1094 // Writes a single byte or word of data in the code stream. Used |
| 1256 // inline tables, e.g., jump-tables. | 1095 // for inline tables, e.g., jump-tables. The constant pool should be |
| 1096 // emitted before any use of db and dd to ensure that constant pools |
| 1097 // are not emitted as part of the tables generated. |
| 1257 void db(uint8_t data); | 1098 void db(uint8_t data); |
| 1258 void dd(uint32_t data); | 1099 void dd(uint32_t data); |
| 1259 | 1100 |
| 1260 int pc_offset() const { return pc_ - buffer_; } | 1101 int pc_offset() const { return pc_ - buffer_; } |
| 1261 | 1102 |
| 1262 PositionsRecorder* positions_recorder() { return &positions_recorder_; } | 1103 PositionsRecorder* positions_recorder() { return &positions_recorder_; } |
| 1263 | 1104 |
| 1264 bool can_peephole_optimize(int instructions) { | 1105 bool can_peephole_optimize(int instructions) { |
| 1265 if (!allow_peephole_optimization_) return false; | 1106 if (!allow_peephole_optimization_) return false; |
| 1266 if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false; | 1107 if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 public: | 1273 public: |
| 1433 explicit EnsureSpace(Assembler* assembler) { | 1274 explicit EnsureSpace(Assembler* assembler) { |
| 1434 assembler->CheckBuffer(); | 1275 assembler->CheckBuffer(); |
| 1435 } | 1276 } |
| 1436 }; | 1277 }; |
| 1437 | 1278 |
| 1438 | 1279 |
| 1439 } } // namespace v8::internal | 1280 } } // namespace v8::internal |
| 1440 | 1281 |
| 1441 #endif // V8_ARM_ASSEMBLER_ARM_H_ | 1282 #endif // V8_ARM_ASSEMBLER_ARM_H_ |
| OLD | NEW |