| 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/baseline_classes.h" | 7 #include "native_client/src/trusted/validator_arm/baseline_classes.h" |
| 8 | 8 |
| 9 #include <assert.h> | 9 #include <assert.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 bool BranchImmediate24::is_relative_branch(Instruction i) const { | 75 bool BranchImmediate24::is_relative_branch(Instruction i) const { |
| 76 UNREFERENCED_PARAMETER(i); | 76 UNREFERENCED_PARAMETER(i); |
| 77 return true; | 77 return true; |
| 78 } | 78 } |
| 79 | 79 |
| 80 int32_t BranchImmediate24::branch_target_offset(Instruction i) const { | 80 int32_t BranchImmediate24::branch_target_offset(Instruction i) const { |
| 81 return imm24.relative_address(i); | 81 return imm24.relative_address(i); |
| 82 } | 82 } |
| 83 | 83 |
| 84 // BreakPointAndConstantPoolHead | 84 // BreakPointAndConstantPoolHead |
| 85 SafetyLevel BreakPointAndConstantPoolHead::safety(const Instruction i) const { |
| 86 return i.GetCondition() == Instruction::AL |
| 87 ? MAY_BE_SAFE |
| 88 : UNPREDICTABLE; |
| 89 } |
| 90 |
| 85 bool BreakPointAndConstantPoolHead:: | 91 bool BreakPointAndConstantPoolHead:: |
| 86 is_literal_pool_head(const Instruction i) const { | 92 is_literal_pool_head(const Instruction i) const { |
| 87 return i.GetCondition() == Instruction::AL && | 93 return i.GetCondition() == Instruction::AL && |
| 88 value(i) == 0x7777; | 94 value(i) == 0x7777; |
| 89 } | 95 } |
| 90 | 96 |
| 91 // BranchToRegister | 97 // BranchToRegister |
| 92 SafetyLevel BranchToRegister::safety(const Instruction i) const { | 98 SafetyLevel BranchToRegister::safety(const Instruction i) const { |
| 99 // Extra NaCl constraint: can't branch to PC. This would branch to 8 bytes |
| 100 // after the current instruction. This instruction should be in an instruction |
| 101 // pair, the mask should therefore be to PC and fail checking, but there's |
| 102 // little harm in checking. |
| 103 if (m.reg(i).Equals(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 104 |
| 105 // Redundant with the above, but this is actually UNPREDICTABLE. Expect DCE. |
| 93 if (link_register.IsUpdated(i) && m.reg(i).Equals(kRegisterPc)) { | 106 if (link_register.IsUpdated(i) && m.reg(i).Equals(kRegisterPc)) { |
| 94 return UNPREDICTABLE; | 107 return UNPREDICTABLE; |
| 95 } | 108 } |
| 96 | 109 |
| 97 return MAY_BE_SAFE; | 110 return MAY_BE_SAFE; |
| 98 } | 111 } |
| 99 | 112 |
| 100 RegisterList BranchToRegister::defs(const Instruction i) const { | 113 RegisterList BranchToRegister::defs(const Instruction i) const { |
| 101 return RegisterList(kRegisterPc). | 114 return RegisterList(kRegisterPc). |
| 102 Add(link_register.IsUpdated(i) ? kRegisterLink : kRegisterNone); | 115 Add(link_register.IsUpdated(i) ? kRegisterLink : kRegisterNone); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 return UNPREDICTABLE; | 363 return UNPREDICTABLE; |
| 351 } | 364 } |
| 352 | 365 |
| 353 if (HasWriteBack(i) && | 366 if (HasWriteBack(i) && |
| 354 (n.reg(i).Equals(kRegisterPc) || | 367 (n.reg(i).Equals(kRegisterPc) || |
| 355 // NOTE: The manual states that that it is also unpredictable | 368 // NOTE: The manual states that that it is also unpredictable |
| 356 // when HasWriteBack(i) and Rn=Rt. However, the compilers | 369 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 357 // may not check for this. For the moment, we are changing | 370 // may not check for this. For the moment, we are changing |
| 358 // the code to ignore this case for stores. | 371 // the code to ignore this case for stores. |
| 359 // TODO(karl): Should we not allow this? | 372 // TODO(karl): Should we not allow this? |
| 373 // TODO(jfb) Fix this. |
| 360 (is_load_ && n.reg(i).Equals(t.reg(i))))) { | 374 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 361 return UNPREDICTABLE; | 375 return UNPREDICTABLE; |
| 362 } | 376 } |
| 363 | 377 |
| 364 // Above implies literal loads can't writeback, the following checks the | 378 // Above implies literal loads can't writeback, the following checks the |
| 365 // ARM restriction that literal loads can't have P == W. | 379 // ARM restriction that literal loads can't have P == W. |
| 366 // This should always decode to another instruction, but checking it is good. | 380 // This should always decode to another instruction, but checking it is good. |
| 367 if (n.reg(i).Equals(kRegisterPc) && | 381 if (n.reg(i).Equals(kRegisterPc) && |
| 368 (indexing.IsDefined(i) == writes.IsDefined(i))) { | 382 (indexing.IsDefined(i) == writes.IsDefined(i))) { |
| 369 return UNPREDICTABLE; | 383 return UNPREDICTABLE; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // LoadStore2RegisterImm12Op | 457 // LoadStore2RegisterImm12Op |
| 444 SafetyLevel LoadStore2RegisterImm12Op::safety(const Instruction i) const { | 458 SafetyLevel LoadStore2RegisterImm12Op::safety(const Instruction i) const { |
| 445 // Arm restrictions for this instruction. | 459 // Arm restrictions for this instruction. |
| 446 if (HasWriteBack(i) && | 460 if (HasWriteBack(i) && |
| 447 (n.reg(i).Equals(kRegisterPc) || | 461 (n.reg(i).Equals(kRegisterPc) || |
| 448 // NOTE: The manual states that that it is also unpredictable | 462 // NOTE: The manual states that that it is also unpredictable |
| 449 // when HasWriteBack(i) and Rn=Rt. However, the compilers | 463 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 450 // may not check for this. For the moment, we are changing | 464 // may not check for this. For the moment, we are changing |
| 451 // the code to ignore this case for stores. | 465 // the code to ignore this case for stores. |
| 452 // TODO(karl): Should we not allow this? | 466 // TODO(karl): Should we not allow this? |
| 467 // TODO(jfb) Fix this. Once this is fixed, |
| 468 // Store2RegisterImm12OpRnNotRtOnWriteback becomes redundant |
| 469 // with this class and can be removed. |
| 453 (is_load_ && n.reg(i).Equals(t.reg(i))))) { | 470 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 454 return UNPREDICTABLE; | 471 return UNPREDICTABLE; |
| 455 } | 472 } |
| 456 | 473 |
| 457 // Don't allow modification of PC (NaCl constraint). | 474 // Don't allow modification of PC (NaCl constraint). |
| 458 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 475 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 459 | 476 |
| 460 // NaCl special restriction to make all load/store immediates behave | 477 // NaCl special restriction to make all load/store immediates behave |
| 461 // the same. | 478 // the same. |
| 462 if (t.reg(i).Equals(kRegisterPc)) { | 479 if (t.reg(i).Equals(kRegisterPc)) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 487 } | 504 } |
| 488 | 505 |
| 489 // Store2RegisterImm12Op | 506 // Store2RegisterImm12Op |
| 490 RegisterList Store2RegisterImm12Op::defs(Instruction i) const { | 507 RegisterList Store2RegisterImm12Op::defs(Instruction i) const { |
| 491 return immediate_addressing_defs(i); | 508 return immediate_addressing_defs(i); |
| 492 } | 509 } |
| 493 | 510 |
| 494 // Store2RegisterImm12OpRnNotRtOnWriteback | 511 // Store2RegisterImm12OpRnNotRtOnWriteback |
| 495 SafetyLevel Store2RegisterImm12OpRnNotRtOnWriteback:: | 512 SafetyLevel Store2RegisterImm12OpRnNotRtOnWriteback:: |
| 496 safety(Instruction i) const { | 513 safety(Instruction i) const { |
| 514 // TODO(jfb) Redundant with LoadStore2RegisterImm12Op, once it is fixed. |
| 497 if (HasWriteBack(i) && (n.reg(i).Equals(t.reg(i)))) | 515 if (HasWriteBack(i) && (n.reg(i).Equals(t.reg(i)))) |
| 498 return UNPREDICTABLE; | 516 return UNPREDICTABLE; |
| 499 return Store2RegisterImm12Op::safety(i); | 517 return Store2RegisterImm12Op::safety(i); |
| 500 } | 518 } |
| 501 | 519 |
| 502 // LoadStoreRegisterList | 520 // LoadStoreRegisterList |
| 503 SafetyLevel LoadStoreRegisterList::safety(const Instruction i) const { | 521 SafetyLevel LoadStoreRegisterList::safety(const Instruction i) const { |
| 504 if (n.reg(i).Equals(kRegisterPc) || (register_list.value(i) == 0)) { | 522 if (n.reg(i).Equals(kRegisterPc) || (register_list.value(i) == 0)) { |
| 505 return UNPREDICTABLE; | 523 return UNPREDICTABLE; |
| 506 } | 524 } |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 return UNPREDICTABLE; | 676 return UNPREDICTABLE; |
| 659 } | 677 } |
| 660 | 678 |
| 661 if (HasWriteBack(i) && | 679 if (HasWriteBack(i) && |
| 662 (n.reg(i).Equals(kRegisterPc) || | 680 (n.reg(i).Equals(kRegisterPc) || |
| 663 // NOTE: The manual states that that it is also unpredictable | 681 // NOTE: The manual states that that it is also unpredictable |
| 664 // when HasWriteBack(i) and Rn=Rt. However, the compilers | 682 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 665 // may not check for this. For the moment, we are changing | 683 // may not check for this. For the moment, we are changing |
| 666 // the code to ignore this case for stores. | 684 // the code to ignore this case for stores. |
| 667 // TODO(karl): Should we not allow this? | 685 // TODO(karl): Should we not allow this? |
| 686 // TODO(jfb) Fix this. |
| 668 (is_load_ && n.reg(i).Equals(t.reg(i))))) { | 687 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 669 return UNPREDICTABLE; | 688 return UNPREDICTABLE; |
| 670 } | 689 } |
| 671 | 690 |
| 691 // TODO(jfb) if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; |
| 692 |
| 672 // Don't let addressing writeback alter PC (NaCl constraint). | 693 // Don't let addressing writeback alter PC (NaCl constraint). |
| 673 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 694 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 674 | 695 |
| 675 return MAY_BE_SAFE; | 696 return MAY_BE_SAFE; |
| 676 } | 697 } |
| 677 | 698 |
| 678 Register LoadStore3RegisterOp::base_address_register( | 699 Register LoadStore3RegisterOp::base_address_register( |
| 679 const Instruction i) const { | 700 const Instruction i) const { |
| 680 return n.reg(i); | 701 return n.reg(i); |
| 681 } | 702 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 707 | 728 |
| 708 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { | 729 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { |
| 709 return UNPREDICTABLE; | 730 return UNPREDICTABLE; |
| 710 } | 731 } |
| 711 | 732 |
| 712 // NOTE: The manual states that that it is also unpredictable | 733 // NOTE: The manual states that that it is also unpredictable |
| 713 // when HasWriteBack(i) and Rn=Rt2. However, the compilers | 734 // when HasWriteBack(i) and Rn=Rt2. However, the compilers |
| 714 // may not check for this. For the moment, we are changing | 735 // may not check for this. For the moment, we are changing |
| 715 // the code to ignore this case for stores. | 736 // the code to ignore this case for stores. |
| 716 // TODO(karl): Should we not allow this? | 737 // TODO(karl): Should we not allow this? |
| 738 // TODO(jfb) Fix this. |
| 717 if (is_load_ && HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { | 739 if (is_load_ && HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { |
| 718 return UNPREDICTABLE; | 740 return UNPREDICTABLE; |
| 719 } | 741 } |
| 720 | 742 |
| 743 if (is_load_ && (m.reg(i).Equals(t.reg(i)) || m.reg(i).Equals(t2.reg(i)))) { |
| 744 return UNPREDICTABLE; |
| 745 } |
| 746 |
| 721 // Now apply non-double width restrictions for this instruction. | 747 // Now apply non-double width restrictions for this instruction. |
| 722 return LoadStore3RegisterOp::safety(i); | 748 return LoadStore3RegisterOp::safety(i); |
| 723 } | 749 } |
| 724 | 750 |
| 725 // StoreExclusive3RegisterOp | 751 // StoreExclusive3RegisterOp |
| 726 SafetyLevel StoreExclusive3RegisterOp::safety(const Instruction i) const { | 752 SafetyLevel StoreExclusive3RegisterOp::safety(const Instruction i) const { |
| 727 // Arm restrictions for this instruction. | 753 // Arm restrictions for this instruction. |
| 728 if (RegisterList(d.reg(i)).Add(t.reg(i)).Add(n.reg(i)). | 754 if (RegisterList(d.reg(i)).Add(t.reg(i)).Add(n.reg(i)). |
| 729 Contains(kRegisterPc)) { | 755 Contains(kRegisterPc)) { |
| 730 return UNPREDICTABLE; | 756 return UNPREDICTABLE; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 return UNPREDICTABLE; | 827 return UNPREDICTABLE; |
| 802 } | 828 } |
| 803 | 829 |
| 804 if (HasWriteBack(i) && | 830 if (HasWriteBack(i) && |
| 805 (n.reg(i).Equals(kRegisterPc) || | 831 (n.reg(i).Equals(kRegisterPc) || |
| 806 // NOTE: The manual states that that it is also unpredictable | 832 // NOTE: The manual states that that it is also unpredictable |
| 807 // when HasWriteBack(i) and Rn=Rt2. However, the compilers | 833 // when HasWriteBack(i) and Rn=Rt2. However, the compilers |
| 808 // may not check for this. For the moment, we are changing | 834 // may not check for this. For the moment, we are changing |
| 809 // the code to ignore this case for stores. | 835 // the code to ignore this case for stores. |
| 810 // TODO(karl): Should we not allow this? | 836 // TODO(karl): Should we not allow this? |
| 837 // TODO(jfb) Fix this. |
| 811 (is_load_ && n.reg(i).Equals(t.reg(i))))) { | 838 (is_load_ && n.reg(i).Equals(t.reg(i))))) { |
| 812 return UNPREDICTABLE; | 839 return UNPREDICTABLE; |
| 813 } | 840 } |
| 814 | 841 |
| 815 // Don't let Rt be Pc (NaCl constraint -- See header file for special | 842 // Don't let Rt be Pc (NaCl constraint -- See header file for special |
| 816 // note). | 843 // note). |
| 817 if (t.reg(i).Equals(kRegisterPc)) { | 844 if (t.reg(i).Equals(kRegisterPc)) { |
| 818 return FORBIDDEN_OPERANDS; | 845 return FORBIDDEN_OPERANDS; |
| 819 } | 846 } |
| 820 | 847 |
| 821 // Don't let addressing writeback alter PC (NaCl constraint). | 848 // Don't let addressing writeback alter PC (NaCl constraint). |
| 822 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 849 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 823 | 850 |
| 851 // TODO(jfb) if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; |
| 852 |
| 824 return MAY_BE_SAFE; | 853 return MAY_BE_SAFE; |
| 825 } | 854 } |
| 826 | 855 |
| 827 Register LoadStore3RegisterImm5Op::base_address_register( | 856 Register LoadStore3RegisterImm5Op::base_address_register( |
| 828 const Instruction i) const { | 857 const Instruction i) const { |
| 829 return n.reg(i); | 858 return n.reg(i); |
| 830 } | 859 } |
| 831 | 860 |
| 832 // Load3RegisterImm5Op | 861 // Load3RegisterImm5Op |
| 833 RegisterList Load3RegisterImm5Op::defs(const Instruction i) const { | 862 RegisterList Load3RegisterImm5Op::defs(const Instruction i) const { |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 if (be_value(i) == 0x3) | 1078 if (be_value(i) == 0x3) |
| 1050 return UNDEFINED; | 1079 return UNDEFINED; |
| 1051 | 1080 |
| 1052 if (t.reg(i).Equals(kRegisterPc)) | 1081 if (t.reg(i).Equals(kRegisterPc)) |
| 1053 return UNPREDICTABLE; | 1082 return UNPREDICTABLE; |
| 1054 | 1083 |
| 1055 return CondVfpOp::safety(i); | 1084 return CondVfpOp::safety(i); |
| 1056 } | 1085 } |
| 1057 | 1086 |
| 1058 } // namespace nacl_arm_dec | 1087 } // namespace nacl_arm_dec |
| OLD | NEW |