| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include "native_client/src/trusted/validator_arm/actual_classes.h" | 7 #include "native_client/src/trusted/validator_arm/actual_classes.h" |
| 8 | 8 |
| 9 #include <assert.h> | 9 #include <assert.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 } | 334 } |
| 335 | 335 |
| 336 if (t2.reg(i).Equals(kRegisterPc)) { | 336 if (t2.reg(i).Equals(kRegisterPc)) { |
| 337 return UNPREDICTABLE; | 337 return UNPREDICTABLE; |
| 338 } | 338 } |
| 339 | 339 |
| 340 if (HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { | 340 if (HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { |
| 341 return UNPREDICTABLE; | 341 return UNPREDICTABLE; |
| 342 } | 342 } |
| 343 | 343 |
| 344 if (m.reg(i).Equals(t.reg(i)) || m.reg(i).Equals(t2.reg(i))) { |
| 345 return UNPREDICTABLE; |
| 346 } |
| 347 |
| 344 // Now apply non-double width restrictions for this instruction. | 348 // Now apply non-double width restrictions for this instruction. |
| 345 return LoadBasedOffsetMemory::safety(i); | 349 return LoadBasedOffsetMemory::safety(i); |
| 346 } | 350 } |
| 347 | 351 |
| 348 RegisterList LoadBasedOffsetMemoryDouble::defs(Instruction i) const { | 352 RegisterList LoadBasedOffsetMemoryDouble::defs(Instruction i) const { |
| 349 return LoadBasedOffsetMemory::defs(i).Add(t2.reg(i)); | 353 return LoadBasedOffsetMemory::defs(i).Add(t2.reg(i)); |
| 350 } | 354 } |
| 351 | 355 |
| 352 RegisterList LoadBasedImmedMemory:: | 356 RegisterList LoadBasedImmedMemory:: |
| 353 immediate_addressing_defs(const Instruction i) const { | 357 immediate_addressing_defs(const Instruction i) const { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 return UNPREDICTABLE; | 391 return UNPREDICTABLE; |
| 388 } | 392 } |
| 389 | 393 |
| 390 if (HasWriteBack(i) && | 394 if (HasWriteBack(i) && |
| 391 (n.reg(i).Equals(kRegisterPc))) { | 395 (n.reg(i).Equals(kRegisterPc))) { |
| 392 // NOTE: The manual states that that it is also unpredictable | 396 // NOTE: The manual states that that it is also unpredictable |
| 393 // when HasWriteBack(i) and Rn=Rt. However, the compilers | 397 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 394 // may not check for this. For the moment, we are changing | 398 // may not check for this. For the moment, we are changing |
| 395 // the code to ignore this case for stores. | 399 // the code to ignore this case for stores. |
| 396 // TODO(karl): Should we not allow this? | 400 // TODO(karl): Should we not allow this? |
| 401 // TODO(jfb) Fix this. |
| 397 return UNPREDICTABLE; | 402 return UNPREDICTABLE; |
| 398 } | 403 } |
| 399 | 404 |
| 400 // Don't let addressing writeback alter PC (NaCl constraint). | 405 // Don't let addressing writeback alter PC (NaCl constraint). |
| 401 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 406 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 402 | 407 |
| 403 return MAY_BE_SAFE; | 408 return MAY_BE_SAFE; |
| 404 } | 409 } |
| 405 | 410 |
| 406 RegisterList StoreBasedMemoryWithWriteBack::defs(const Instruction i) const { | 411 RegisterList StoreBasedMemoryWithWriteBack::defs(const Instruction i) const { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 421 return UNPREDICTABLE; | 426 return UNPREDICTABLE; |
| 422 } | 427 } |
| 423 | 428 |
| 424 if (HasWriteBack(i) && | 429 if (HasWriteBack(i) && |
| 425 (n.reg(i).Equals(kRegisterPc))) { | 430 (n.reg(i).Equals(kRegisterPc))) { |
| 426 // NOTE: The manual states that that it is also unpredictable | 431 // NOTE: The manual states that that it is also unpredictable |
| 427 // when HasWriteBack(i) and Rn=Rt. However, the compilers | 432 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 428 // may not check for this. For the moment, we are changing | 433 // may not check for this. For the moment, we are changing |
| 429 // the code to ignore this case for stores. | 434 // the code to ignore this case for stores. |
| 430 // TODO(karl): Should we not allow this? | 435 // TODO(karl): Should we not allow this? |
| 436 // TODO(jfb) Fix this. |
| 431 return UNPREDICTABLE; | 437 return UNPREDICTABLE; |
| 432 } | 438 } |
| 433 | 439 |
| 440 // TODO(jfb) if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; |
| 441 |
| 434 return StoreBasedMemoryWithWriteBack::safety(i); | 442 return StoreBasedMemoryWithWriteBack::safety(i); |
| 435 } | 443 } |
| 436 | 444 |
| 437 SafetyLevel StoreBasedOffsetMemoryDouble::safety(const Instruction i) const { | 445 SafetyLevel StoreBasedOffsetMemoryDouble::safety(const Instruction i) const { |
| 438 // Arm double width restrictions for this instruction. | 446 // Arm double width restrictions for this instruction. |
| 439 if (!t.IsEven(i)) { | 447 if (!t.IsEven(i)) { |
| 440 return UNDEFINED; | 448 return UNDEFINED; |
| 441 } | 449 } |
| 442 | 450 |
| 443 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { | 451 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 UNREFERENCED_PARAMETER(i); | 514 UNREFERENCED_PARAMETER(i); |
| 507 return MAY_BE_SAFE; | 515 return MAY_BE_SAFE; |
| 508 } | 516 } |
| 509 | 517 |
| 510 RegisterList Roadblock::defs(Instruction i) const { | 518 RegisterList Roadblock::defs(Instruction i) const { |
| 511 UNREFERENCED_PARAMETER(i); | 519 UNREFERENCED_PARAMETER(i); |
| 512 return RegisterList(); | 520 return RegisterList(); |
| 513 } | 521 } |
| 514 | 522 |
| 515 // Breakpoint | 523 // Breakpoint |
| 524 SafetyLevel Breakpoint::safety(Instruction i) const { |
| 525 return i.GetCondition() == Instruction::AL |
| 526 ? MAY_BE_SAFE |
| 527 : UNPREDICTABLE; |
| 528 } |
| 529 |
| 516 bool Breakpoint::is_literal_pool_head(const Instruction i) const { | 530 bool Breakpoint::is_literal_pool_head(const Instruction i) const { |
| 517 return i.GetCondition() == Instruction::AL | 531 return i.GetCondition() == Instruction::AL |
| 518 && i.Bits(19, 8) == 0x777 | 532 && i.Bits(19, 8) == 0x777 |
| 519 && i.Bits(3, 0) == 0x7; | 533 && i.Bits(3, 0) == 0x7; |
| 520 } | 534 } |
| 521 | 535 |
| 522 SafetyLevel PackSatRev::safety(const Instruction i) const { | 536 SafetyLevel PackSatRev::safety(const Instruction i) const { |
| 523 if (defs(i).Contains(kRegisterPc)) { | 537 if (defs(i).Contains(kRegisterPc)) { |
| 524 return FORBIDDEN_OPERANDS; | 538 return FORBIDDEN_OPERANDS; |
| 525 } | 539 } |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 } | 714 } |
| 701 | 715 |
| 702 | 716 |
| 703 RegisterList MoveDoubleFromCoprocessor::defs(Instruction i) const { | 717 RegisterList MoveDoubleFromCoprocessor::defs(Instruction i) const { |
| 704 return RegisterList(Rt(i)).Add(Rt2(i)); | 718 return RegisterList(Rt(i)).Add(Rt2(i)); |
| 705 } | 719 } |
| 706 | 720 |
| 707 // Control flow | 721 // Control flow |
| 708 | 722 |
| 709 SafetyLevel BxBlx::safety(Instruction i) const { | 723 SafetyLevel BxBlx::safety(Instruction i) const { |
| 724 // Extra NaCl constraint: can't branch to PC. This would branch to 8 bytes |
| 725 // after the current instruction. This instruction should be in an instruction |
| 726 // pair, the mask should therefore be to PC and fail checking, but there's |
| 727 // little harm in checking. |
| 728 if (m.reg(i).Equals(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 729 |
| 730 // Redundant with the above, but this is actually UNPREDICTABLE. Expect DCE. |
| 710 if (link_register.IsUpdated(i) && m.reg(i).Equals(kRegisterPc)) { | 731 if (link_register.IsUpdated(i) && m.reg(i).Equals(kRegisterPc)) { |
| 711 return UNPREDICTABLE; | 732 return UNPREDICTABLE; |
| 712 } | 733 } |
| 713 | 734 |
| 714 return MAY_BE_SAFE; | 735 return MAY_BE_SAFE; |
| 715 } | 736 } |
| 716 | 737 |
| 717 RegisterList BxBlx::defs(const Instruction i) const { | 738 RegisterList BxBlx::defs(const Instruction i) const { |
| 718 return RegisterList(kRegisterPc). | 739 return RegisterList(kRegisterPc). |
| 719 Add(link_register.IsUpdated(i) ? kRegisterLink : kRegisterNone); | 740 Add(link_register.IsUpdated(i) ? kRegisterLink : kRegisterNone); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 int width = msbit + 1 - lsbit; | 820 int width = msbit + 1 - lsbit; |
| 800 if (width == 32) { | 821 if (width == 32) { |
| 801 return mask == 0; | 822 return mask == 0; |
| 802 } else { | 823 } else { |
| 803 uint32_t bit_mask = (((1 << width) - 1) << lsbit); | 824 uint32_t bit_mask = (((1 << width) - 1) << lsbit); |
| 804 return (bit_mask & mask) == mask; | 825 return (bit_mask & mask) == mask; |
| 805 } | 826 } |
| 806 } | 827 } |
| 807 | 828 |
| 808 } // namespace nacl_arm_dec | 829 } // namespace nacl_arm_dec |
| OLD | NEW |