Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 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 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H | 7 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H |
| 8 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H | 8 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H |
| 9 | 9 |
| 10 #include <stdint.h> | 10 #include <stdint.h> |
| 11 #include "native_client/src/trusted/validator_arm/model.h" | 11 #include "native_client/src/trusted/validator_arm/model.h" |
| 12 #include "native_client/src/include/portability.h" | 12 #include "native_client/src/include/portability.h" |
| 13 // TODO(mrm) Remove this with debugging lines | |
| 14 #include <stdio.h> | |
| 13 | 15 |
| 14 /* | 16 /* |
| 15 * Models the "instruction classes" that the decoder produces. | 17 * Models the "instruction classes" that the decoder produces. |
| 16 */ | 18 */ |
| 17 namespace nacl_arm_dec { | 19 namespace nacl_arm_dec { |
| 18 | 20 |
| 19 /* | 21 /* |
| 22 * Describes whether an operation is safe to have during an IT. | |
| 23 */ | |
| 24 enum ITSafety { | |
| 25 // Safe to use in an IT block | |
| 26 ALWAYS, | |
| 27 // Unsafe to use in an IT block | |
| 28 NEVER, | |
| 29 // Can only go at the end of an IT block | |
| 30 END | |
| 31 }; | |
| 32 | |
| 33 /* | |
| 34 * Describes what mode an instruction governed under an IT is in. | |
| 35 * THEN means condition must match, ELSE means condition must not match, | |
| 36 * NONE means this is the end of IT control flow. | |
| 37 */ | |
| 38 enum ITMode { | |
| 39 // No condition. There should be no Thens or Elses after this | |
| 40 NONE = 0, | |
| 41 // Matches condition | |
| 42 THEN = 1, | |
| 43 // Does not match condition | |
| 44 ELSE = 2 | |
| 45 }; | |
| 46 | |
| 47 /* | |
| 48 * Used to store the full it conditional. This should fit in a byte, and so is | |
| 49 * used instead of an array. It is a bitpacked size 4 array of 2 bit values. | |
| 50 */ | |
| 51 typedef uint8_t ITCond; | |
| 52 inline ITMode it_select(uint8_t index, ITCond cond) { | |
| 53 return (ITMode)((cond >> (2 * index)) & 0x3); | |
| 54 } | |
| 55 inline ITCond it_set(uint8_t index, ITMode mode, ITCond cond) { | |
| 56 return (mode << (2 * index)) | (cond & (~(0x3 << (2 * index)))); | |
| 57 } | |
| 58 | |
| 59 /* | |
| 20 * Used to describe whether an instruction is safe, and if not, what the issue | 60 * Used to describe whether an instruction is safe, and if not, what the issue |
| 21 * is. Only instructions that MAY_BE_SAFE should be allowed in untrusted code, | 61 * is. Only instructions that MAY_BE_SAFE should be allowed in untrusted code, |
| 22 * and even those may be rejected by the validator. | 62 * and even those may be rejected by the validator. |
| 23 */ | 63 */ |
| 24 enum SafetyLevel { | 64 enum SafetyLevel { |
| 25 // The initial value of uninitialized SafetyLevels -- treat as unsafe. | 65 // The initial value of uninitialized SafetyLevels -- treat as unsafe. |
| 26 UNKNOWN = 0, | 66 UNKNOWN = 0, |
| 27 | 67 |
| 28 // This instruction is left undefined by the ARMv7 ISA spec. | 68 // This instruction is left undefined by the ARMv7 ISA spec. |
| 29 UNDEFINED, | 69 UNDEFINED, |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 /* | 209 /* |
| 170 * Checks whether this instruction is the special bit sequence that marks | 210 * Checks whether this instruction is the special bit sequence that marks |
| 171 * the start of a literal pool. | 211 * the start of a literal pool. |
| 172 */ | 212 */ |
| 173 virtual bool is_literal_pool_head(Instruction i) const { | 213 virtual bool is_literal_pool_head(Instruction i) const { |
| 174 UNREFERENCED_PARAMETER(i); | 214 UNREFERENCED_PARAMETER(i); |
| 175 return false; | 215 return false; |
| 176 } | 216 } |
| 177 | 217 |
| 178 /* | 218 /* |
| 219 * Checks that an instruction sets a certain pattern of bits in all its | |
| 220 * (non-flag) result registers. The mask should include 1s in the positions | |
| 221 * that should be set. Unlike clears_bits, which may clear a superset of these | |
| 222 * bits, sets_bits must set PRECISELY the bits in mask. | |
| 223 */ | |
| 224 virtual bool sets_bits(Instruction i, uint32_t mask) const { | |
| 225 UNREFERENCED_PARAMETER(i); | |
| 226 UNREFERENCED_PARAMETER(mask); | |
| 227 return false; | |
| 228 } | |
| 229 | |
| 230 /* | |
| 179 * Checks that an instruction clears a certain pattern of bits in all its | 231 * Checks that an instruction clears a certain pattern of bits in all its |
| 180 * (non-flag) result registers. The mask should include 1s in the positions | 232 * (non-flag) result registers. The mask should include 1s in the positions |
| 181 * that should be cleared. | 233 * that should be cleared. |
| 182 */ | 234 */ |
| 183 virtual bool clears_bits(Instruction i, uint32_t mask) const { | 235 virtual bool clears_bits(Instruction i, uint32_t mask) const { |
| 184 UNREFERENCED_PARAMETER(i); | 236 UNREFERENCED_PARAMETER(i); |
| 185 UNREFERENCED_PARAMETER(mask); | 237 UNREFERENCED_PARAMETER(mask); |
| 186 return false; | 238 return false; |
| 187 } | 239 } |
| 188 | 240 |
| 189 /* | 241 /* |
| 190 * Checks that an instruction will set Z if certain bits in r (chosen by 1s in | 242 * Checks that an instruction will set Z if certain bits in r (chosen by 1s in |
| 191 * the mask) are clear. | 243 * the mask) are clear. |
| 192 * | 244 * |
| 193 * Note that the inverse does not hold: the actual instruction i may require | 245 * Note that the inverse does not hold: the actual instruction i may require |
| 194 * *more* bits to be clear to set Z. This is fine. | 246 * *more* bits to be clear to set Z. This is fine. |
| 195 */ | 247 */ |
| 196 virtual bool sets_Z_if_bits_clear(Instruction i, | 248 virtual bool sets_Z_if_bits_clear(Instruction i, |
| 197 Register r, | 249 Register r, |
| 198 uint32_t mask) const { | 250 uint32_t mask) const { |
| 199 UNREFERENCED_PARAMETER(i); | 251 UNREFERENCED_PARAMETER(i); |
| 200 UNREFERENCED_PARAMETER(r); | 252 UNREFERENCED_PARAMETER(r); |
| 201 UNREFERENCED_PARAMETER(mask); | 253 UNREFERENCED_PARAMETER(mask); |
| 202 return false; | 254 return false; |
| 203 } | 255 } |
| 204 | 256 |
| 257 /* | |
| 258 * Generates the appropriate it condition set for this instruction. | |
| 259 * All entries after a NONE is hit should be zero. | |
| 260 * Default return is that no IT is in effect. | |
| 261 * There are exactly 4 entries, encoded as a bitpacked 2-bit element array. | |
| 262 */ | |
| 263 virtual ITCond it_sequence(Instruction i) const { | |
| 264 UNREFERENCED_PARAMETER(i); | |
| 265 return 0; | |
| 266 } | |
| 267 | |
| 268 /* | |
| 269 * Determines under what conditions an instruction is safe to have in an IT | |
| 270 * block for CPU sanity. Usually, most instructions are. | |
| 271 */ | |
| 272 virtual ITSafety it_safe(Instruction i) const { | |
| 273 UNREFERENCED_PARAMETER(i); | |
| 274 return ALWAYS; | |
| 275 } | |
| 276 | |
| 277 /* | |
| 278 * Calculate the condition code. This used to be done by Instruction, | |
| 279 * but Thumb has some special cases, so we hook here for potential override. | |
| 280 */ | |
| 281 virtual Instruction::Condition condition(Instruction i) const { | |
| 282 return i.condition(); | |
| 283 } | |
| 284 | |
| 205 protected: | 285 protected: |
| 206 ClassDecoder() {} | 286 ClassDecoder() {} |
| 207 virtual ~ClassDecoder() {} | 287 virtual ~ClassDecoder() {} |
| 208 }; | 288 }; |
| 209 | 289 |
| 210 /* | 290 /* |
| 291 * Base class for thumb decoders, has different default behavior for conditions | |
| 292 */ | |
| 293 class ClassDecoderT : public ClassDecoder { | |
| 294 public: | |
| 295 virtual ~ClassDecoderT() {} | |
| 296 virtual Instruction::Condition condition(Instruction i) const { | |
| 297 UNREFERENCED_PARAMETER(i); | |
| 298 return Instruction::UNCONDITIONAL; | |
| 299 } | |
| 300 }; | |
| 301 | |
| 302 /* | |
| 211 * Represents an instruction that is forbidden under all circumstances, so we | 303 * Represents an instruction that is forbidden under all circumstances, so we |
| 212 * didn't bother decoding it further. | 304 * didn't bother decoding it further. |
| 213 */ | 305 */ |
| 214 class Forbidden : public ClassDecoder { | 306 class Forbidden : public ClassDecoder { |
| 215 public: | 307 public: |
| 216 virtual ~Forbidden() {} | 308 virtual ~Forbidden() {} |
| 217 | 309 |
| 218 virtual SafetyLevel safety(Instruction i) const { | 310 virtual SafetyLevel safety(Instruction i) const { |
| 219 UNREFERENCED_PARAMETER(i); | 311 UNREFERENCED_PARAMETER(i); |
| 220 return FORBIDDEN; | 312 return FORBIDDEN; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 * code isn't expected to use it, but it's not unsafe, and there are cases where | 421 * code isn't expected to use it, but it's not unsafe, and there are cases where |
| 330 * we may generate it. | 422 * we may generate it. |
| 331 */ | 423 */ |
| 332 class Breakpoint : public Roadblock { | 424 class Breakpoint : public Roadblock { |
| 333 public: | 425 public: |
| 334 virtual ~Breakpoint() {} | 426 virtual ~Breakpoint() {} |
| 335 | 427 |
| 336 virtual bool is_literal_pool_head(Instruction i) const; | 428 virtual bool is_literal_pool_head(Instruction i) const; |
| 337 }; | 429 }; |
| 338 | 430 |
| 431 class ThumbBreakpoint : public Breakpoint { | |
| 432 public: | |
| 433 virtual ~ThumbBreakpoint() {} | |
| 434 | |
| 435 virtual bool is_literal_pool_head(Instruction i) const; | |
| 436 }; | |
| 437 | |
| 438 | |
| 339 /* | 439 /* |
| 340 * Models the most common class of data processing instructions. We use this | 440 * Models the most common class of data processing instructions. We use this |
| 341 * for any operation that | 441 * for any operation that |
| 342 * - writes a single register, specified in 15:12; | 442 * - writes a single register, specified in 15:12; |
| 343 * - does not write memory, | 443 * - does not write memory, |
| 344 * - should not be permitted to cause a jump by writing r15, | 444 * - should not be permitted to cause a jump by writing r15, |
| 345 * - writes flags when bit 20 is set. | 445 * - writes flags when bit 20 is set. |
| 346 */ | 446 */ |
| 347 class DataProc : public ClassDecoder { | 447 class DataProc : public ClassDecoder { |
| 348 public: | 448 public: |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 return MAY_BE_SAFE; | 861 return MAY_BE_SAFE; |
| 762 } | 862 } |
| 763 virtual RegisterList defs(Instruction i) const; | 863 virtual RegisterList defs(Instruction i) const; |
| 764 virtual bool is_relative_branch(Instruction i) const { | 864 virtual bool is_relative_branch(Instruction i) const { |
| 765 UNREFERENCED_PARAMETER(i); | 865 UNREFERENCED_PARAMETER(i); |
| 766 return true; | 866 return true; |
| 767 } | 867 } |
| 768 virtual int32_t branch_target_offset(Instruction i) const; | 868 virtual int32_t branch_target_offset(Instruction i) const; |
| 769 }; | 869 }; |
| 770 | 870 |
| 871 /* Thumb Classes */ | |
| 872 | |
| 873 class Def3 : public ClassDecoderT { | |
|
Karl
2011/08/30 19:53:52
Not thrilled with the use of T suffix for thumb (w
| |
| 874 public: | |
| 875 virtual ~Def3() {} | |
| 876 | |
| 877 virtual SafetyLevel safety(Instruction i) const; | |
| 878 virtual RegisterList defs(Instruction i) const; | |
| 879 }; | |
| 880 | |
| 881 class Def8_10 : public ClassDecoderT { | |
| 882 public: | |
| 883 virtual ~Def8_10() {} | |
| 884 | |
| 885 virtual SafetyLevel safety(Instruction i) const; | |
| 886 virtual RegisterList defs(Instruction i) const; | |
| 887 }; | |
| 888 | |
| 889 class MemOpThumb : public ClassDecoderT { | |
| 890 public: | |
| 891 virtual ~MemOpThumb() {} | |
| 892 | |
| 893 virtual SafetyLevel safety(Instruction i) const; | |
| 894 virtual RegisterList defs(Instruction i) const { | |
| 895 UNREFERENCED_PARAMETER(i); | |
| 896 return kRegisterNone; | |
| 897 } | |
| 898 | |
| 899 virtual Register base_address_register(Instruction i) const; | |
| 900 }; | |
| 901 | |
| 902 class MemOpThumbLoad : public MemOpThumb { | |
| 903 public: | |
| 904 virtual ~MemOpThumbLoad() {} | |
| 905 | |
| 906 virtual RegisterList defs(Instruction i) const; | |
| 907 }; | |
| 908 | |
| 909 class MemOpThumbStore : public MemOpThumb { | |
| 910 public: | |
| 911 virtual ~MemOpThumbStore() {} | |
| 912 | |
| 913 virtual bool writes_memory(Instruction i) const { | |
| 914 UNREFERENCED_PARAMETER(i); | |
| 915 return true; | |
| 916 } | |
| 917 }; | |
| 918 | |
| 919 class SPMod : public ClassDecoderT { | |
| 920 public: | |
| 921 virtual ~SPMod() {} | |
| 922 virtual SafetyLevel safety(Instruction i) const { | |
| 923 UNREFERENCED_PARAMETER(i); | |
| 924 return MAY_BE_SAFE; | |
| 925 } | |
| 926 virtual RegisterList defs(Instruction i) const { | |
| 927 UNREFERENCED_PARAMETER(i); | |
| 928 return kRegisterStack; | |
| 929 } | |
| 930 }; | |
| 931 | |
| 932 // mrm BiC3, OrMask3, Mask3 are dummies atm, and could be replaced by | |
| 933 // Def3, its only potential purpose is to allow registerwise | |
| 934 // bitmasking, which is not a current feature. | |
| 935 class BiC3 : public Def3 { | |
| 936 public: | |
| 937 virtual ~BiC3() {} | |
| 938 }; | |
| 939 | |
| 940 class Mask3 : public Def3 { | |
| 941 public: | |
| 942 virtual ~Mask3() {} | |
| 943 }; | |
| 944 | |
| 945 class OrMask3 : public Def3 { | |
| 946 public: | |
| 947 virtual ~OrMask3() {} | |
| 948 }; | |
| 949 | |
| 950 class Cmp : public ClassDecoderT { | |
| 951 public : | |
| 952 virtual ~Cmp() {} | |
| 953 virtual SafetyLevel safety(Instruction i) const { | |
| 954 UNREFERENCED_PARAMETER(i); | |
| 955 return MAY_BE_SAFE; | |
| 956 } | |
| 957 virtual RegisterList defs(Instruction i) const { | |
| 958 UNREFERENCED_PARAMETER(i); | |
| 959 return kRegisterNone; | |
| 960 } | |
| 961 // mrm may want logic for cmp sandboxing, but not atm | |
| 962 // This would be a superclass for that, not the target class | |
| 963 }; | |
| 964 | |
| 965 class CmpBrZ : public ClassDecoderT { | |
| 966 public: | |
| 967 virtual ~CmpBrZ() {} | |
| 968 virtual SafetyLevel safety(Instruction i) const { | |
| 969 UNREFERENCED_PARAMETER(i); | |
| 970 return MAY_BE_SAFE; | |
| 971 } | |
| 972 virtual RegisterList defs(Instruction i) const { | |
| 973 UNREFERENCED_PARAMETER(i); | |
| 974 return kRegisterPc; | |
| 975 } | |
| 976 virtual bool is_relative_branch(Instruction i) const { | |
| 977 UNREFERENCED_PARAMETER(i); | |
| 978 return true; | |
| 979 } | |
| 980 virtual ITSafety it_safe(Instruction i) const { | |
| 981 UNREFERENCED_PARAMETER(i); | |
| 982 return NEVER; | |
| 983 } | |
| 984 virtual int32_t branch_target_offset(Instruction i) const; | |
| 985 }; | |
| 986 | |
| 987 class PushMult : public ClassDecoderT { | |
| 988 public: | |
| 989 virtual ~PushMult() {} | |
| 990 virtual SafetyLevel safety(Instruction i) const { | |
| 991 UNREFERENCED_PARAMETER(i); | |
| 992 return MAY_BE_SAFE; | |
| 993 } | |
| 994 virtual RegisterList defs(Instruction i) const { | |
| 995 UNREFERENCED_PARAMETER(i); | |
| 996 return kRegisterStack; | |
| 997 } | |
| 998 virtual Register base_address_register(Instruction i) const { | |
| 999 UNREFERENCED_PARAMETER(i); | |
| 1000 return kRegisterStack; | |
| 1001 } | |
| 1002 virtual RegisterList immediate_addressing_defs(Instruction i) const { | |
| 1003 return base_address_register(i); | |
| 1004 } | |
| 1005 virtual bool writes_memory(Instruction i) const { | |
| 1006 UNREFERENCED_PARAMETER(i); | |
| 1007 return true; | |
| 1008 } | |
| 1009 }; | |
| 1010 | |
| 1011 class PopMult : public PushMult { | |
| 1012 public: | |
| 1013 virtual ~PopMult() {} | |
| 1014 virtual RegisterList defs(Instruction i) const; | |
| 1015 }; | |
| 1016 | |
| 1017 class BranchT : public ClassDecoder { | |
|
Karl
2011/08/30 19:53:52
Again, why not Thumb suffix?
| |
| 1018 public: | |
| 1019 virtual ~BranchT() {} | |
| 1020 virtual SafetyLevel safety(Instruction i) const { | |
| 1021 UNREFERENCED_PARAMETER(i); | |
| 1022 return MAY_BE_SAFE; | |
| 1023 } | |
| 1024 virtual RegisterList defs(Instruction i) const { | |
| 1025 UNREFERENCED_PARAMETER(i); | |
| 1026 return kRegisterPc; | |
| 1027 } | |
| 1028 virtual bool is_relative_branch(Instruction i) const { | |
| 1029 UNREFERENCED_PARAMETER(i); | |
| 1030 return true; | |
| 1031 } | |
| 1032 virtual ITSafety it_safe(Instruction i) const { | |
| 1033 UNREFERENCED_PARAMETER(i); | |
| 1034 return END; | |
| 1035 } | |
| 1036 }; | |
| 1037 | |
| 1038 class BranchTCond : public BranchT { | |
| 1039 public: | |
| 1040 virtual ~BranchTCond() {} | |
| 1041 virtual SafetyLevel safety(Instruction i) const; | |
| 1042 virtual ITSafety it_safe(Instruction i) const { | |
| 1043 UNREFERENCED_PARAMETER(i); | |
| 1044 return NEVER; | |
| 1045 } | |
| 1046 }; | |
| 1047 | |
| 1048 class BranchT1 : public BranchTCond { | |
| 1049 virtual int32_t branch_target_offset(Instruction i) const; | |
| 1050 virtual Instruction::Condition condition(Instruction i) const; | |
| 1051 }; | |
| 1052 | |
| 1053 class BranchT2 : public BranchT { | |
| 1054 public: | |
| 1055 virtual ~BranchT2() {} | |
| 1056 virtual int32_t branch_target_offset(Instruction i) const; | |
| 1057 }; | |
| 1058 | |
| 1059 class BranchT3 : public BranchTCond { | |
| 1060 public: | |
| 1061 virtual ~BranchT3() {} | |
| 1062 virtual int32_t branch_target_offset(Instruction i) const; | |
| 1063 virtual Instruction::Condition condition(Instruction i) const; | |
| 1064 }; | |
| 1065 | |
| 1066 class BranchT4 : public BranchT { | |
| 1067 public: | |
| 1068 virtual ~BranchT4() {} | |
| 1069 virtual int32_t branch_target_offset(Instruction i) const; | |
| 1070 }; | |
| 1071 | |
| 1072 class STMT1 : public ClassDecoderT { | |
| 1073 public: | |
| 1074 virtual ~STMT1() {} | |
| 1075 virtual SafetyLevel safety(Instruction i) const { | |
| 1076 UNREFERENCED_PARAMETER(i); | |
| 1077 return MAY_BE_SAFE; | |
| 1078 } | |
| 1079 virtual RegisterList immediate_addressing_defs(Instruction i) const; | |
| 1080 virtual RegisterList defs(Instruction i) const; | |
| 1081 virtual Register base_address_register(Instruction i) const; | |
| 1082 virtual bool writes_memory(Instruction i) const { | |
| 1083 UNREFERENCED_PARAMETER(i); | |
| 1084 return true; | |
| 1085 } | |
| 1086 }; | |
| 1087 | |
| 1088 class LDMT1 : public STMT1 { | |
| 1089 public: | |
| 1090 virtual ~LDMT1() {} | |
| 1091 virtual RegisterList defs(Instruction i) const; | |
| 1092 virtual bool writes_memory(Instruction i) const { | |
| 1093 UNREFERENCED_PARAMETER(i); | |
| 1094 return false; | |
| 1095 } | |
| 1096 }; | |
| 1097 | |
| 1098 class LDRLitT1 : public ClassDecoderT { | |
| 1099 public: | |
| 1100 virtual ~LDRLitT1() {} | |
| 1101 virtual SafetyLevel safety(Instruction i) const { | |
| 1102 UNREFERENCED_PARAMETER(i); | |
| 1103 return MAY_BE_SAFE; | |
| 1104 } | |
| 1105 virtual RegisterList defs(Instruction i) const; | |
| 1106 }; | |
| 1107 | |
| 1108 class ADRT1 : public ClassDecoderT { | |
| 1109 public: | |
| 1110 virtual ~ADRT1() {} | |
| 1111 virtual SafetyLevel safety(Instruction i) const { | |
| 1112 UNREFERENCED_PARAMETER(i); | |
| 1113 return MAY_BE_SAFE; | |
| 1114 } | |
| 1115 virtual RegisterList defs(Instruction i) const; | |
| 1116 }; | |
| 1117 | |
| 1118 class MemOpSPThumbStore : public ClassDecoderT { | |
| 1119 public: | |
| 1120 virtual ~MemOpSPThumbStore() {} | |
| 1121 virtual SafetyLevel safety(Instruction i) const { | |
| 1122 UNREFERENCED_PARAMETER(i); | |
| 1123 return MAY_BE_SAFE; | |
| 1124 } | |
| 1125 virtual bool writes_memory(Instruction i) const { | |
| 1126 UNREFERENCED_PARAMETER(i); | |
| 1127 return true; | |
| 1128 } | |
| 1129 virtual RegisterList defs(Instruction i) const { | |
| 1130 UNREFERENCED_PARAMETER(i); | |
| 1131 return kRegisterNone; | |
| 1132 } | |
| 1133 virtual Register base_address_register(Instruction i) const { | |
| 1134 UNREFERENCED_PARAMETER(i); | |
| 1135 return kRegisterStack; | |
| 1136 } | |
| 1137 }; | |
| 1138 | |
| 1139 class MemOpSPThumbLoad : public ClassDecoderT { | |
| 1140 public: | |
| 1141 virtual ~MemOpSPThumbLoad() {} | |
| 1142 virtual SafetyLevel safety(Instruction i) const { | |
| 1143 UNREFERENCED_PARAMETER(i); | |
| 1144 return MAY_BE_SAFE; | |
| 1145 } | |
| 1146 virtual RegisterList defs(Instruction i) const; | |
| 1147 virtual Register base_address_register(Instruction i) const { | |
| 1148 UNREFERENCED_PARAMETER(i); | |
| 1149 return kRegisterStack; | |
| 1150 } | |
| 1151 }; | |
| 1152 | |
| 1153 class DPMImm : public ClassDecoderT { | |
| 1154 public: | |
| 1155 virtual ~DPMImm() {} | |
| 1156 virtual SafetyLevel safety(Instruction i) const { | |
| 1157 UNREFERENCED_PARAMETER(i); | |
| 1158 return MAY_BE_SAFE; | |
| 1159 } | |
| 1160 virtual RegisterList defs(Instruction i) const; | |
| 1161 }; | |
| 1162 | |
| 1163 class BicModImmT : public DPMImm { | |
| 1164 public: | |
| 1165 virtual ~BicModImmT() {} | |
| 1166 virtual bool clears_bits(Instruction i, uint32_t mask) const; | |
| 1167 }; | |
| 1168 | |
| 1169 class OrrModImmT : public DPMImm { | |
| 1170 public: | |
| 1171 virtual ~OrrModImmT() {} | |
| 1172 virtual bool sets_bits(Instruction i, uint32_t mask) const; | |
| 1173 }; | |
| 1174 | |
| 1175 class MovT : public Def3 { | |
| 1176 public: | |
| 1177 virtual ~MovT() {} | |
| 1178 virtual RegisterList defs(Instruction i) const; | |
| 1179 }; | |
| 1180 | |
| 1181 class BXT : public ClassDecoderT { | |
| 1182 public: | |
| 1183 virtual ~BXT() {} | |
| 1184 virtual SafetyLevel safety(Instruction i) const { | |
| 1185 UNREFERENCED_PARAMETER(i); | |
| 1186 return MAY_BE_SAFE; | |
| 1187 } | |
| 1188 virtual RegisterList defs(Instruction i) const { | |
| 1189 UNREFERENCED_PARAMETER(i); | |
| 1190 return kRegisterPc; | |
| 1191 } | |
| 1192 Register branch_target_register(Instruction i) const; | |
| 1193 virtual ITSafety it_safe(Instruction i) const { | |
| 1194 UNREFERENCED_PARAMETER(i); | |
| 1195 return END; | |
| 1196 } | |
| 1197 }; | |
| 1198 | |
| 1199 class BLXT : public BXT { | |
| 1200 public: | |
| 1201 virtual ~BLXT() {} | |
| 1202 virtual RegisterList defs(Instruction i) const { | |
| 1203 UNREFERENCED_PARAMETER(i); | |
| 1204 return kRegisterPc + kRegisterLink; | |
| 1205 } | |
| 1206 }; | |
| 1207 | |
| 1208 class BLT : public ClassDecoderT { | |
| 1209 public: | |
| 1210 virtual ~BLT() {} | |
| 1211 virtual SafetyLevel safety(Instruction i) const { | |
| 1212 UNREFERENCED_PARAMETER(i); | |
| 1213 return MAY_BE_SAFE; | |
| 1214 } | |
| 1215 virtual RegisterList defs(Instruction i) const { | |
| 1216 UNREFERENCED_PARAMETER(i); | |
| 1217 return kRegisterPc + kRegisterLink; | |
| 1218 } | |
| 1219 virtual bool is_relative_branch(Instruction i) const { | |
| 1220 UNREFERENCED_PARAMETER(i); | |
| 1221 return true; | |
| 1222 } | |
| 1223 virtual int32_t branch_target_offset(Instruction i) const; | |
| 1224 virtual ITSafety it_safe(Instruction i) const { | |
| 1225 UNREFERENCED_PARAMETER(i); | |
| 1226 return END; | |
| 1227 } | |
| 1228 }; | |
| 1229 | |
| 1230 class IT : public ClassDecoderT { | |
| 1231 public: | |
| 1232 virtual ~IT() {} | |
| 1233 virtual SafetyLevel safety(Instruction i) const { | |
| 1234 UNREFERENCED_PARAMETER(i); | |
| 1235 return MAY_BE_SAFE; | |
| 1236 } | |
| 1237 virtual ITSafety it_safe(Instruction i) const { | |
| 1238 UNREFERENCED_PARAMETER(i); | |
| 1239 return NEVER; | |
| 1240 } | |
| 1241 virtual RegisterList defs(Instruction i) const { | |
| 1242 UNREFERENCED_PARAMETER(i); | |
| 1243 return kRegisterNone; | |
| 1244 } | |
| 1245 virtual Instruction::Condition condition(Instruction i) const; | |
| 1246 virtual ITCond it_sequence(Instruction i) const; | |
| 1247 }; | |
| 1248 | |
| 1249 class STMTD : public ClassDecoderT { | |
| 1250 public: | |
| 1251 virtual ~STMTD() {} | |
| 1252 virtual SafetyLevel safety(Instruction i) const { | |
| 1253 UNREFERENCED_PARAMETER(i); | |
| 1254 return MAY_BE_SAFE; | |
| 1255 } | |
| 1256 virtual RegisterList defs(Instruction i) const; | |
| 1257 virtual bool writes_memory(Instruction i) const { | |
| 1258 UNREFERENCED_PARAMETER(i); | |
| 1259 return true; | |
| 1260 } | |
| 1261 virtual Register base_address_register(Instruction i) const; | |
| 1262 virtual RegisterList immediate_addressing_defs(Instruction i) const; | |
| 1263 }; | |
| 1264 | |
| 1265 class LDMTD : public STMTD { | |
| 1266 public: | |
| 1267 virtual ~LDMTD() {} | |
| 1268 virtual RegisterList defs(Instruction i) const; | |
| 1269 virtual bool writes_memory(Instruction i) const { | |
| 1270 UNREFERENCED_PARAMETER(i); | |
| 1271 return false; | |
| 1272 } | |
| 1273 }; | |
| 1274 | |
| 1275 class StrS : public STMTD { | |
| 1276 public: | |
| 1277 virtual ~StrS() {} | |
| 1278 virtual Register base_address_register(Instruction i) const; | |
| 1279 virtual RegisterList defs(Instruction i) const; | |
| 1280 }; | |
| 1281 | |
| 1282 class LDRImmT3 : public ClassDecoderT { | |
| 1283 public: | |
| 1284 virtual ~LDRImmT3() {} | |
| 1285 virtual SafetyLevel safety(Instruction i) const { | |
| 1286 UNREFERENCED_PARAMETER(i); | |
| 1287 return MAY_BE_SAFE; | |
| 1288 } | |
| 1289 virtual RegisterList defs(Instruction i) const { | |
| 1290 UNREFERENCED_PARAMETER(i); | |
| 1291 return kRegisterNone; | |
| 1292 } | |
| 1293 virtual Register base_address_register(Instruction i) const; | |
| 1294 }; | |
| 1295 | |
| 1296 class LDRImmT4 : public LDRImmT3 { | |
| 1297 public: | |
| 1298 virtual ~LDRImmT4() {} | |
| 1299 virtual RegisterList immediate_addressing_defs(Instruction i) const; | |
| 1300 virtual RegisterList defs(Instruction i) const; | |
| 1301 }; | |
| 1302 | |
| 1303 class Def31_18 : public Def3 { | |
| 1304 public: | |
| 1305 virtual ~Def31_18() {} | |
| 1306 virtual RegisterList defs(Instruction i) const; | |
| 1307 }; | |
| 1308 | |
| 1309 class StrEx : public Def3 { | |
| 1310 public: | |
| 1311 virtual ~StrEx() {} | |
| 1312 virtual RegisterList defs(Instruction i) const; | |
| 1313 virtual RegisterList immediate_addressing_defs(Instruction i) const; | |
| 1314 virtual bool writes_memory(Instruction i) const { | |
| 1315 UNREFERENCED_PARAMETER(i); | |
| 1316 return true; | |
| 1317 } | |
| 1318 virtual Register base_address_register(Instruction i) const; | |
| 1319 }; | |
| 1320 | |
| 1321 class LdrEx : public StrEx { | |
| 1322 public: | |
| 1323 virtual ~LdrEx() {} | |
| 1324 virtual RegisterList defs(Instruction i) const; | |
| 1325 virtual bool writes_memory(Instruction i) const { | |
| 1326 UNREFERENCED_PARAMETER(i); | |
| 1327 return false; | |
| 1328 } | |
| 1329 }; | |
| 1330 | |
| 1331 class StrD : public StrEx { | |
| 1332 public: | |
| 1333 virtual ~StrD() {} | |
| 1334 virtual RegisterList defs(Instruction i) const; | |
| 1335 }; | |
| 1336 | |
| 1337 class LdrD : public LdrEx { | |
| 1338 public: | |
| 1339 virtual ~LdrD() {} | |
| 1340 virtual RegisterList defs(Instruction i) const; | |
| 1341 }; | |
| 1342 | |
| 1343 class StrExD : public StrEx { | |
| 1344 public: | |
| 1345 virtual ~StrExD() {} | |
| 1346 virtual RegisterList immediate_addressing_defs(Instruction i) const { | |
| 1347 UNREFERENCED_PARAMETER(i); | |
| 1348 return kRegisterNone; // Writeback not available | |
| 1349 } | |
| 1350 }; | |
| 1351 | |
| 1352 class LdrExD : public LdrD { | |
| 1353 public: | |
| 1354 virtual ~LdrExD() {} | |
| 1355 virtual RegisterList immediate_addressing_defs(Instruction i) const { | |
| 1356 UNREFERENCED_PARAMETER(i); | |
| 1357 return kRegisterNone; // Writeback not available | |
| 1358 } | |
| 1359 }; | |
| 1360 | |
| 1361 class Def27_24 : public Def3 { | |
| 1362 public: | |
| 1363 virtual ~Def27_24() {} | |
| 1364 virtual RegisterList defs(Instruction i) const; | |
| 1365 }; | |
| 1366 | |
| 1367 /* Unimplemented Thumb instructions go here */ | |
| 1368 #define THUMB_TODO(x) class x : public Forbidden {}; | |
| 1369 THUMB_TODO(Unimplemented) | |
| 771 } // namespace | 1370 } // namespace |
| 772 | 1371 |
| 773 #endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H | 1372 #endif // NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_ARM_V2_INST_CLASSES_H |
| OLD | NEW |