| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ | 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ |
| 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ | 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <list> | 9 #include <list> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 | 74 |
| 75 enum RegisterType { | 75 enum RegisterType { |
| 76 // The kInvalid value is used to detect uninitialized static instances, | 76 // The kInvalid value is used to detect uninitialized static instances, |
| 77 // which are always zero-initialized before any constructors are called. | 77 // which are always zero-initialized before any constructors are called. |
| 78 kInvalid = 0, | 78 kInvalid = 0, |
| 79 kRegister, | 79 kRegister, |
| 80 kFPRegister, | 80 kFPRegister, |
| 81 kNoRegister | 81 kNoRegister |
| 82 }; | 82 }; |
| 83 | 83 |
| 84 static CPURegister Create(unsigned code, unsigned size, RegisterType type) { | 84 static CPURegister Create(int code, int size, RegisterType type) { |
| 85 CPURegister r = {code, size, type}; | 85 CPURegister r = {code, size, type}; |
| 86 return r; | 86 return r; |
| 87 } | 87 } |
| 88 | 88 |
| 89 unsigned code() const; | 89 int code() const; |
| 90 RegisterType type() const; | 90 RegisterType type() const; |
| 91 RegList Bit() const; | 91 RegList Bit() const; |
| 92 unsigned SizeInBits() const; | 92 int SizeInBits() const; |
| 93 int SizeInBytes() const; | 93 int SizeInBytes() const; |
| 94 bool Is32Bits() const; | 94 bool Is32Bits() const; |
| 95 bool Is64Bits() const; | 95 bool Is64Bits() const; |
| 96 bool IsValid() const; | 96 bool IsValid() const; |
| 97 bool IsValidOrNone() const; | 97 bool IsValidOrNone() const; |
| 98 bool IsValidRegister() const; | 98 bool IsValidRegister() const; |
| 99 bool IsValidFPRegister() const; | 99 bool IsValidFPRegister() const; |
| 100 bool IsNone() const; | 100 bool IsNone() const; |
| 101 bool Is(const CPURegister& other) const; | 101 bool Is(const CPURegister& other) const; |
| 102 bool Aliases(const CPURegister& other) const; | 102 bool Aliases(const CPURegister& other) const; |
| 103 | 103 |
| 104 bool IsZero() const; | 104 bool IsZero() const; |
| 105 bool IsSP() const; | 105 bool IsSP() const; |
| 106 | 106 |
| 107 bool IsRegister() const; | 107 bool IsRegister() const; |
| 108 bool IsFPRegister() const; | 108 bool IsFPRegister() const; |
| 109 | 109 |
| 110 Register X() const; | 110 Register X() const; |
| 111 Register W() const; | 111 Register W() const; |
| 112 FPRegister D() const; | 112 FPRegister D() const; |
| 113 FPRegister S() const; | 113 FPRegister S() const; |
| 114 | 114 |
| 115 bool IsSameSizeAndType(const CPURegister& other) const; | 115 bool IsSameSizeAndType(const CPURegister& other) const; |
| 116 | 116 |
| 117 // V8 compatibility. | 117 // V8 compatibility. |
| 118 bool is(const CPURegister& other) const { return Is(other); } | 118 bool is(const CPURegister& other) const { return Is(other); } |
| 119 bool is_valid() const { return IsValid(); } | 119 bool is_valid() const { return IsValid(); } |
| 120 | 120 |
| 121 unsigned reg_code; | 121 int reg_code; |
| 122 unsigned reg_size; | 122 int reg_size; |
| 123 RegisterType reg_type; | 123 RegisterType reg_type; |
| 124 }; | 124 }; |
| 125 | 125 |
| 126 | 126 |
| 127 struct Register : public CPURegister { | 127 struct Register : public CPURegister { |
| 128 static Register Create(unsigned code, unsigned size) { | 128 static Register Create(int code, int size) { |
| 129 return Register(CPURegister::Create(code, size, CPURegister::kRegister)); | 129 return Register(CPURegister::Create(code, size, CPURegister::kRegister)); |
| 130 } | 130 } |
| 131 | 131 |
| 132 Register() { | 132 Register() { |
| 133 reg_code = 0; | 133 reg_code = 0; |
| 134 reg_size = 0; | 134 reg_size = 0; |
| 135 reg_type = CPURegister::kNoRegister; | 135 reg_type = CPURegister::kNoRegister; |
| 136 } | 136 } |
| 137 | 137 |
| 138 explicit Register(const CPURegister& r) { | 138 explicit Register(const CPURegister& r) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 | 193 |
| 194 struct FPRegister : public CPURegister { | 194 struct FPRegister : public CPURegister { |
| 195 enum Code { | 195 enum Code { |
| 196 #define REGISTER_CODE(R) kCode_##R, | 196 #define REGISTER_CODE(R) kCode_##R, |
| 197 DOUBLE_REGISTERS(REGISTER_CODE) | 197 DOUBLE_REGISTERS(REGISTER_CODE) |
| 198 #undef REGISTER_CODE | 198 #undef REGISTER_CODE |
| 199 kAfterLast, | 199 kAfterLast, |
| 200 kCode_no_reg = -1 | 200 kCode_no_reg = -1 |
| 201 }; | 201 }; |
| 202 | 202 |
| 203 static FPRegister Create(unsigned code, unsigned size) { | 203 static FPRegister Create(int code, int size) { |
| 204 return FPRegister( | 204 return FPRegister( |
| 205 CPURegister::Create(code, size, CPURegister::kFPRegister)); | 205 CPURegister::Create(code, size, CPURegister::kFPRegister)); |
| 206 } | 206 } |
| 207 | 207 |
| 208 FPRegister() { | 208 FPRegister() { |
| 209 reg_code = 0; | 209 reg_code = 0; |
| 210 reg_size = 0; | 210 reg_size = 0; |
| 211 reg_type = CPURegister::kNoRegister; | 211 reg_type = CPURegister::kNoRegister; |
| 212 } | 212 } |
| 213 | 213 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 explicit CPURegList(CPURegister reg1, | 378 explicit CPURegList(CPURegister reg1, |
| 379 CPURegister reg2 = NoCPUReg, | 379 CPURegister reg2 = NoCPUReg, |
| 380 CPURegister reg3 = NoCPUReg, | 380 CPURegister reg3 = NoCPUReg, |
| 381 CPURegister reg4 = NoCPUReg) | 381 CPURegister reg4 = NoCPUReg) |
| 382 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), | 382 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), |
| 383 size_(reg1.SizeInBits()), type_(reg1.type()) { | 383 size_(reg1.SizeInBits()), type_(reg1.type()) { |
| 384 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4)); | 384 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4)); |
| 385 DCHECK(IsValid()); | 385 DCHECK(IsValid()); |
| 386 } | 386 } |
| 387 | 387 |
| 388 CPURegList(CPURegister::RegisterType type, unsigned size, RegList list) | 388 CPURegList(CPURegister::RegisterType type, int size, RegList list) |
| 389 : list_(list), size_(size), type_(type) { | 389 : list_(list), size_(size), type_(type) { |
| 390 DCHECK(IsValid()); | 390 DCHECK(IsValid()); |
| 391 } | 391 } |
| 392 | 392 |
| 393 CPURegList(CPURegister::RegisterType type, unsigned size, | 393 CPURegList(CPURegister::RegisterType type, int size, int first_reg, |
| 394 unsigned first_reg, unsigned last_reg) | 394 int last_reg) |
| 395 : size_(size), type_(type) { | 395 : size_(size), type_(type) { |
| 396 DCHECK(((type == CPURegister::kRegister) && | 396 DCHECK(((type == CPURegister::kRegister) && |
| 397 (last_reg < kNumberOfRegisters)) || | 397 (last_reg < kNumberOfRegisters)) || |
| 398 ((type == CPURegister::kFPRegister) && | 398 ((type == CPURegister::kFPRegister) && |
| 399 (last_reg < kNumberOfFPRegisters))); | 399 (last_reg < kNumberOfFPRegisters))); |
| 400 DCHECK(last_reg >= first_reg); | 400 DCHECK(last_reg >= first_reg); |
| 401 list_ = (1UL << (last_reg + 1)) - 1; | 401 list_ = (1UL << (last_reg + 1)) - 1; |
| 402 list_ &= ~((1UL << first_reg) - 1); | 402 list_ &= ~((1UL << first_reg) - 1); |
| 403 DCHECK(IsValid()); | 403 DCHECK(IsValid()); |
| 404 } | 404 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 void Remove(int code); | 441 void Remove(int code); |
| 442 | 442 |
| 443 // Remove all callee-saved registers from the list. This can be useful when | 443 // Remove all callee-saved registers from the list. This can be useful when |
| 444 // preparing registers for an AAPCS64 function call, for example. | 444 // preparing registers for an AAPCS64 function call, for example. |
| 445 void RemoveCalleeSaved(); | 445 void RemoveCalleeSaved(); |
| 446 | 446 |
| 447 CPURegister PopLowestIndex(); | 447 CPURegister PopLowestIndex(); |
| 448 CPURegister PopHighestIndex(); | 448 CPURegister PopHighestIndex(); |
| 449 | 449 |
| 450 // AAPCS64 callee-saved registers. | 450 // AAPCS64 callee-saved registers. |
| 451 static CPURegList GetCalleeSaved(unsigned size = kXRegSizeInBits); | 451 static CPURegList GetCalleeSaved(int size = kXRegSizeInBits); |
| 452 static CPURegList GetCalleeSavedFP(unsigned size = kDRegSizeInBits); | 452 static CPURegList GetCalleeSavedFP(int size = kDRegSizeInBits); |
| 453 | 453 |
| 454 // AAPCS64 caller-saved registers. Note that this includes lr. | 454 // AAPCS64 caller-saved registers. Note that this includes lr. |
| 455 static CPURegList GetCallerSaved(unsigned size = kXRegSizeInBits); | 455 static CPURegList GetCallerSaved(int size = kXRegSizeInBits); |
| 456 static CPURegList GetCallerSavedFP(unsigned size = kDRegSizeInBits); | 456 static CPURegList GetCallerSavedFP(int size = kDRegSizeInBits); |
| 457 | 457 |
| 458 // Registers saved as safepoints. | 458 // Registers saved as safepoints. |
| 459 static CPURegList GetSafepointSavedRegisters(); | 459 static CPURegList GetSafepointSavedRegisters(); |
| 460 | 460 |
| 461 bool IsEmpty() const { | 461 bool IsEmpty() const { |
| 462 DCHECK(IsValid()); | 462 DCHECK(IsValid()); |
| 463 return list_ == 0; | 463 return list_ == 0; |
| 464 } | 464 } |
| 465 | 465 |
| 466 bool IncludesAliasOf(const CPURegister& other1, | 466 bool IncludesAliasOf(const CPURegister& other1, |
| 467 const CPURegister& other2 = NoCPUReg, | 467 const CPURegister& other2 = NoCPUReg, |
| 468 const CPURegister& other3 = NoCPUReg, | 468 const CPURegister& other3 = NoCPUReg, |
| 469 const CPURegister& other4 = NoCPUReg) const { | 469 const CPURegister& other4 = NoCPUReg) const { |
| 470 DCHECK(IsValid()); | 470 DCHECK(IsValid()); |
| 471 RegList list = 0; | 471 RegList list = 0; |
| 472 if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit(); | 472 if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit(); |
| 473 if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit(); | 473 if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit(); |
| 474 if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit(); | 474 if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit(); |
| 475 if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit(); | 475 if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit(); |
| 476 return (list_ & list) != 0; | 476 return (list_ & list) != 0; |
| 477 } | 477 } |
| 478 | 478 |
| 479 int Count() const { | 479 int Count() const { |
| 480 DCHECK(IsValid()); | 480 DCHECK(IsValid()); |
| 481 return CountSetBits(list_, kRegListSizeInBits); | 481 return CountSetBits(list_, kRegListSizeInBits); |
| 482 } | 482 } |
| 483 | 483 |
| 484 unsigned RegisterSizeInBits() const { | 484 int RegisterSizeInBits() const { |
| 485 DCHECK(IsValid()); | 485 DCHECK(IsValid()); |
| 486 return size_; | 486 return size_; |
| 487 } | 487 } |
| 488 | 488 |
| 489 unsigned RegisterSizeInBytes() const { | 489 int RegisterSizeInBytes() const { |
| 490 int size_in_bits = RegisterSizeInBits(); | 490 int size_in_bits = RegisterSizeInBits(); |
| 491 DCHECK((size_in_bits % kBitsPerByte) == 0); | 491 DCHECK((size_in_bits % kBitsPerByte) == 0); |
| 492 return size_in_bits / kBitsPerByte; | 492 return size_in_bits / kBitsPerByte; |
| 493 } | 493 } |
| 494 | 494 |
| 495 unsigned TotalSizeInBytes() const { | 495 int TotalSizeInBytes() const { |
| 496 DCHECK(IsValid()); | 496 DCHECK(IsValid()); |
| 497 return RegisterSizeInBytes() * Count(); | 497 return RegisterSizeInBytes() * Count(); |
| 498 } | 498 } |
| 499 | 499 |
| 500 private: | 500 private: |
| 501 RegList list_; | 501 RegList list_; |
| 502 unsigned size_; | 502 int size_; |
| 503 CPURegister::RegisterType type_; | 503 CPURegister::RegisterType type_; |
| 504 | 504 |
| 505 bool IsValid() const { | 505 bool IsValid() const { |
| 506 const RegList kValidRegisters = 0x8000000ffffffff; | 506 const RegList kValidRegisters = 0x8000000ffffffff; |
| 507 const RegList kValidFPRegisters = 0x0000000ffffffff; | 507 const RegList kValidFPRegisters = 0x0000000ffffffff; |
| 508 switch (type_) { | 508 switch (type_) { |
| 509 case CPURegister::kRegister: | 509 case CPURegister::kRegister: |
| 510 return (list_ & kValidRegisters) == list_; | 510 return (list_ & kValidRegisters) == list_; |
| 511 case CPURegister::kFPRegister: | 511 case CPURegister::kFPRegister: |
| 512 return (list_ & kValidFPRegisters) == list_; | 512 return (list_ & kValidFPRegisters) == list_; |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 void lsrv(const Register& rd, const Register& rn, const Register& rm); | 1114 void lsrv(const Register& rd, const Register& rn, const Register& rm); |
| 1115 | 1115 |
| 1116 // Arithmetic shift right variable. | 1116 // Arithmetic shift right variable. |
| 1117 void asrv(const Register& rd, const Register& rn, const Register& rm); | 1117 void asrv(const Register& rd, const Register& rn, const Register& rm); |
| 1118 | 1118 |
| 1119 // Rotate right variable. | 1119 // Rotate right variable. |
| 1120 void rorv(const Register& rd, const Register& rn, const Register& rm); | 1120 void rorv(const Register& rd, const Register& rn, const Register& rm); |
| 1121 | 1121 |
| 1122 // Bitfield instructions. | 1122 // Bitfield instructions. |
| 1123 // Bitfield move. | 1123 // Bitfield move. |
| 1124 void bfm(const Register& rd, | 1124 void bfm(const Register& rd, const Register& rn, int immr, int imms); |
| 1125 const Register& rn, | |
| 1126 unsigned immr, | |
| 1127 unsigned imms); | |
| 1128 | 1125 |
| 1129 // Signed bitfield move. | 1126 // Signed bitfield move. |
| 1130 void sbfm(const Register& rd, | 1127 void sbfm(const Register& rd, const Register& rn, int immr, int imms); |
| 1131 const Register& rn, | |
| 1132 unsigned immr, | |
| 1133 unsigned imms); | |
| 1134 | 1128 |
| 1135 // Unsigned bitfield move. | 1129 // Unsigned bitfield move. |
| 1136 void ubfm(const Register& rd, | 1130 void ubfm(const Register& rd, const Register& rn, int immr, int imms); |
| 1137 const Register& rn, | |
| 1138 unsigned immr, | |
| 1139 unsigned imms); | |
| 1140 | 1131 |
| 1141 // Bfm aliases. | 1132 // Bfm aliases. |
| 1142 // Bitfield insert. | 1133 // Bitfield insert. |
| 1143 void bfi(const Register& rd, | 1134 void bfi(const Register& rd, const Register& rn, int lsb, int width) { |
| 1144 const Register& rn, | |
| 1145 unsigned lsb, | |
| 1146 unsigned width) { | |
| 1147 DCHECK(width >= 1); | 1135 DCHECK(width >= 1); |
| 1148 DCHECK(lsb + width <= rn.SizeInBits()); | 1136 DCHECK(lsb + width <= rn.SizeInBits()); |
| 1149 bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); | 1137 bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); |
| 1150 } | 1138 } |
| 1151 | 1139 |
| 1152 // Bitfield extract and insert low. | 1140 // Bitfield extract and insert low. |
| 1153 void bfxil(const Register& rd, | 1141 void bfxil(const Register& rd, const Register& rn, int lsb, int width) { |
| 1154 const Register& rn, | |
| 1155 unsigned lsb, | |
| 1156 unsigned width) { | |
| 1157 DCHECK(width >= 1); | 1142 DCHECK(width >= 1); |
| 1158 DCHECK(lsb + width <= rn.SizeInBits()); | 1143 DCHECK(lsb + width <= rn.SizeInBits()); |
| 1159 bfm(rd, rn, lsb, lsb + width - 1); | 1144 bfm(rd, rn, lsb, lsb + width - 1); |
| 1160 } | 1145 } |
| 1161 | 1146 |
| 1162 // Sbfm aliases. | 1147 // Sbfm aliases. |
| 1163 // Arithmetic shift right. | 1148 // Arithmetic shift right. |
| 1164 void asr(const Register& rd, const Register& rn, unsigned shift) { | 1149 void asr(const Register& rd, const Register& rn, int shift) { |
| 1165 DCHECK(shift < rd.SizeInBits()); | 1150 DCHECK(shift < rd.SizeInBits()); |
| 1166 sbfm(rd, rn, shift, rd.SizeInBits() - 1); | 1151 sbfm(rd, rn, shift, rd.SizeInBits() - 1); |
| 1167 } | 1152 } |
| 1168 | 1153 |
| 1169 // Signed bitfield insert in zero. | 1154 // Signed bitfield insert in zero. |
| 1170 void sbfiz(const Register& rd, | 1155 void sbfiz(const Register& rd, const Register& rn, int lsb, int width) { |
| 1171 const Register& rn, | |
| 1172 unsigned lsb, | |
| 1173 unsigned width) { | |
| 1174 DCHECK(width >= 1); | 1156 DCHECK(width >= 1); |
| 1175 DCHECK(lsb + width <= rn.SizeInBits()); | 1157 DCHECK(lsb + width <= rn.SizeInBits()); |
| 1176 sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); | 1158 sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); |
| 1177 } | 1159 } |
| 1178 | 1160 |
| 1179 // Signed bitfield extract. | 1161 // Signed bitfield extract. |
| 1180 void sbfx(const Register& rd, | 1162 void sbfx(const Register& rd, const Register& rn, int lsb, int width) { |
| 1181 const Register& rn, | |
| 1182 unsigned lsb, | |
| 1183 unsigned width) { | |
| 1184 DCHECK(width >= 1); | 1163 DCHECK(width >= 1); |
| 1185 DCHECK(lsb + width <= rn.SizeInBits()); | 1164 DCHECK(lsb + width <= rn.SizeInBits()); |
| 1186 sbfm(rd, rn, lsb, lsb + width - 1); | 1165 sbfm(rd, rn, lsb, lsb + width - 1); |
| 1187 } | 1166 } |
| 1188 | 1167 |
| 1189 // Signed extend byte. | 1168 // Signed extend byte. |
| 1190 void sxtb(const Register& rd, const Register& rn) { | 1169 void sxtb(const Register& rd, const Register& rn) { |
| 1191 sbfm(rd, rn, 0, 7); | 1170 sbfm(rd, rn, 0, 7); |
| 1192 } | 1171 } |
| 1193 | 1172 |
| 1194 // Signed extend halfword. | 1173 // Signed extend halfword. |
| 1195 void sxth(const Register& rd, const Register& rn) { | 1174 void sxth(const Register& rd, const Register& rn) { |
| 1196 sbfm(rd, rn, 0, 15); | 1175 sbfm(rd, rn, 0, 15); |
| 1197 } | 1176 } |
| 1198 | 1177 |
| 1199 // Signed extend word. | 1178 // Signed extend word. |
| 1200 void sxtw(const Register& rd, const Register& rn) { | 1179 void sxtw(const Register& rd, const Register& rn) { |
| 1201 sbfm(rd, rn, 0, 31); | 1180 sbfm(rd, rn, 0, 31); |
| 1202 } | 1181 } |
| 1203 | 1182 |
| 1204 // Ubfm aliases. | 1183 // Ubfm aliases. |
| 1205 // Logical shift left. | 1184 // Logical shift left. |
| 1206 void lsl(const Register& rd, const Register& rn, unsigned shift) { | 1185 void lsl(const Register& rd, const Register& rn, int shift) { |
| 1207 unsigned reg_size = rd.SizeInBits(); | 1186 int reg_size = rd.SizeInBits(); |
| 1208 DCHECK(shift < reg_size); | 1187 DCHECK(shift < reg_size); |
| 1209 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); | 1188 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); |
| 1210 } | 1189 } |
| 1211 | 1190 |
| 1212 // Logical shift right. | 1191 // Logical shift right. |
| 1213 void lsr(const Register& rd, const Register& rn, unsigned shift) { | 1192 void lsr(const Register& rd, const Register& rn, int shift) { |
| 1214 DCHECK(shift < rd.SizeInBits()); | 1193 DCHECK(shift < rd.SizeInBits()); |
| 1215 ubfm(rd, rn, shift, rd.SizeInBits() - 1); | 1194 ubfm(rd, rn, shift, rd.SizeInBits() - 1); |
| 1216 } | 1195 } |
| 1217 | 1196 |
| 1218 // Unsigned bitfield insert in zero. | 1197 // Unsigned bitfield insert in zero. |
| 1219 void ubfiz(const Register& rd, | 1198 void ubfiz(const Register& rd, const Register& rn, int lsb, int width) { |
| 1220 const Register& rn, | |
| 1221 unsigned lsb, | |
| 1222 unsigned width) { | |
| 1223 DCHECK(width >= 1); | 1199 DCHECK(width >= 1); |
| 1224 DCHECK(lsb + width <= rn.SizeInBits()); | 1200 DCHECK(lsb + width <= rn.SizeInBits()); |
| 1225 ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); | 1201 ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); |
| 1226 } | 1202 } |
| 1227 | 1203 |
| 1228 // Unsigned bitfield extract. | 1204 // Unsigned bitfield extract. |
| 1229 void ubfx(const Register& rd, | 1205 void ubfx(const Register& rd, const Register& rn, int lsb, int width) { |
| 1230 const Register& rn, | |
| 1231 unsigned lsb, | |
| 1232 unsigned width) { | |
| 1233 DCHECK(width >= 1); | 1206 DCHECK(width >= 1); |
| 1234 DCHECK(lsb + width <= rn.SizeInBits()); | 1207 DCHECK(lsb + width <= rn.SizeInBits()); |
| 1235 ubfm(rd, rn, lsb, lsb + width - 1); | 1208 ubfm(rd, rn, lsb, lsb + width - 1); |
| 1236 } | 1209 } |
| 1237 | 1210 |
| 1238 // Unsigned extend byte. | 1211 // Unsigned extend byte. |
| 1239 void uxtb(const Register& rd, const Register& rn) { | 1212 void uxtb(const Register& rd, const Register& rn) { |
| 1240 ubfm(rd, rn, 0, 7); | 1213 ubfm(rd, rn, 0, 7); |
| 1241 } | 1214 } |
| 1242 | 1215 |
| 1243 // Unsigned extend halfword. | 1216 // Unsigned extend halfword. |
| 1244 void uxth(const Register& rd, const Register& rn) { | 1217 void uxth(const Register& rd, const Register& rn) { |
| 1245 ubfm(rd, rn, 0, 15); | 1218 ubfm(rd, rn, 0, 15); |
| 1246 } | 1219 } |
| 1247 | 1220 |
| 1248 // Unsigned extend word. | 1221 // Unsigned extend word. |
| 1249 void uxtw(const Register& rd, const Register& rn) { | 1222 void uxtw(const Register& rd, const Register& rn) { |
| 1250 ubfm(rd, rn, 0, 31); | 1223 ubfm(rd, rn, 0, 31); |
| 1251 } | 1224 } |
| 1252 | 1225 |
| 1253 // Extract. | 1226 // Extract. |
| 1254 void extr(const Register& rd, | 1227 void extr(const Register& rd, const Register& rn, const Register& rm, |
| 1255 const Register& rn, | 1228 int lsb); |
| 1256 const Register& rm, | |
| 1257 unsigned lsb); | |
| 1258 | 1229 |
| 1259 // Conditional select: rd = cond ? rn : rm. | 1230 // Conditional select: rd = cond ? rn : rm. |
| 1260 void csel(const Register& rd, | 1231 void csel(const Register& rd, |
| 1261 const Register& rn, | 1232 const Register& rn, |
| 1262 const Register& rm, | 1233 const Register& rm, |
| 1263 Condition cond); | 1234 Condition cond); |
| 1264 | 1235 |
| 1265 // Conditional select increment: rd = cond ? rn : rm + 1. | 1236 // Conditional select increment: rd = cond ? rn : rm + 1. |
| 1266 void csinc(const Register& rd, | 1237 void csinc(const Register& rd, |
| 1267 const Register& rn, | 1238 const Register& rn, |
| (...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2217 public: | 2188 public: |
| 2218 explicit EnsureSpace(Assembler* assembler) { | 2189 explicit EnsureSpace(Assembler* assembler) { |
| 2219 assembler->CheckBufferSpace(); | 2190 assembler->CheckBufferSpace(); |
| 2220 } | 2191 } |
| 2221 }; | 2192 }; |
| 2222 | 2193 |
| 2223 } // namespace internal | 2194 } // namespace internal |
| 2224 } // namespace v8 | 2195 } // namespace v8 |
| 2225 | 2196 |
| 2226 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ | 2197 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ |
| OLD | NEW |