| 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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } | 262 } |
| 263 | 263 |
| 264 | 264 |
| 265 SafetyLevel StrImmediate::safety(const Instruction i) const { | 265 SafetyLevel StrImmediate::safety(const Instruction i) const { |
| 266 // Arm restrictions for this instruction. | 266 // Arm restrictions for this instruction. |
| 267 if (t.reg(i).Equals(kRegisterPc)) { | 267 if (t.reg(i).Equals(kRegisterPc)) { |
| 268 return UNPREDICTABLE; | 268 return UNPREDICTABLE; |
| 269 } | 269 } |
| 270 | 270 |
| 271 if (HasWriteBack(i) && | 271 if (HasWriteBack(i) && |
| 272 (n.reg(i).Equals(kRegisterPc) || n.reg(i).Equals(t.reg(i)))) { | 272 (n.reg(i).Equals(kRegisterPc))) { |
| 273 // NOTE: The manual states that that it is also unpredictable |
| 274 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 275 // may not check for this. For the moment, we are changing |
| 276 // the code to ignore this case for stores. |
| 277 // TODO(karl): Should we not allow this? |
| 273 return UNPREDICTABLE; | 278 return UNPREDICTABLE; |
| 274 } | 279 } |
| 275 | 280 |
| 276 // Don't let addressing writeback alter PC (NaCl constraint). | 281 // Don't let addressing writeback alter PC (NaCl constraint). |
| 277 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 282 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 278 | 283 |
| 279 return MAY_BE_SAFE; | 284 return MAY_BE_SAFE; |
| 280 } | 285 } |
| 281 | 286 |
| 282 SafetyLevel StrImmediateDouble::safety(const Instruction i) const { | 287 SafetyLevel StrImmediateDouble::safety(const Instruction i) const { |
| 283 // Arm double width restrictions for this instruction. | 288 // Arm double width restrictions for this instruction. |
| 284 if (!t.IsEven(i)) { | 289 if (!t.IsEven(i)) { |
| 285 return UNDEFINED; | 290 return UNDEFINED; |
| 286 } | 291 } |
| 287 | 292 |
| 288 if (t2.reg(i).Equals(kRegisterPc)) { | 293 if (t2.reg(i).Equals(kRegisterPc)) { |
| 289 return UNPREDICTABLE; | 294 return UNPREDICTABLE; |
| 290 } | 295 } |
| 291 | 296 |
| 292 if (HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { | 297 // NOTE: The manual states that that it is also unpredictable |
| 293 return UNPREDICTABLE; | 298 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 294 } | 299 // may not check for this. For the moment, we are changing |
| 300 // the code to ignore this case for stores. |
| 301 // TODO(karl): Should we not allow this? |
| 302 // if (HasWriteBack(i) && n.reg(i).Equals(t2.reg(i))) { |
| 303 // return UNPREDICTABLE; |
| 304 // } |
| 295 | 305 |
| 296 // Now apply non-double width restrictions for this instruction. | 306 // Now apply non-double width restrictions for this instruction. |
| 297 return StrImmediate::safety(i); | 307 return StrImmediate::safety(i); |
| 298 } | 308 } |
| 299 | 309 |
| 300 SafetyLevel StoreRegister::safety(const Instruction i) const { | 310 SafetyLevel StoreRegister::safety(const Instruction i) const { |
| 301 if (PreindexingFlag(i)) { | 311 if (PreindexingFlag(i)) { |
| 302 // Computes base address by adding two registers -- cannot predict! | 312 // Computes base address by adding two registers -- cannot predict! |
| 303 return FORBIDDEN; | 313 return FORBIDDEN; |
| 304 } | 314 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 329 // to it, so it is not safe. (NaCl constraint). | 339 // to it, so it is not safe. (NaCl constraint). |
| 330 return FORBIDDEN; | 340 return FORBIDDEN; |
| 331 } | 341 } |
| 332 | 342 |
| 333 // Arm restrictions for this instruction. | 343 // Arm restrictions for this instruction. |
| 334 if (RegisterList(t.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { | 344 if (RegisterList(t.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { |
| 335 return UNPREDICTABLE; | 345 return UNPREDICTABLE; |
| 336 } | 346 } |
| 337 | 347 |
| 338 if (HasWriteBack(i) && | 348 if (HasWriteBack(i) && |
| 339 (n.reg(i).Equals(kRegisterPc) || n.reg(i).Equals(t.reg(i)))) { | 349 (n.reg(i).Equals(kRegisterPc))) { |
| 350 // NOTE: The manual states that that it is also unpredictable |
| 351 // when HasWriteBack(i) and Rn=Rt. However, the compilers |
| 352 // may not check for this. For the moment, we are changing |
| 353 // the code to ignore this case for stores. |
| 354 // TODO(karl): Should we not allow this? |
| 340 return UNPREDICTABLE; | 355 return UNPREDICTABLE; |
| 341 } | 356 } |
| 342 | 357 |
| 343 // Don't let addressing writeback alter PC (NaCl constraint). | 358 // Don't let addressing writeback alter PC (NaCl constraint). |
| 344 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; | 359 if (defs(i).Contains(kRegisterPc)) return FORBIDDEN_OPERANDS; |
| 345 | 360 |
| 346 return MAY_BE_SAFE; | 361 return MAY_BE_SAFE; |
| 347 } | 362 } |
| 348 | 363 |
| 349 SafetyLevel StoreExclusive::safety(const Instruction i) const { | 364 SafetyLevel StoreExclusive::safety(const Instruction i) const { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 // Arm double width restrictions for this instruction. | 525 // Arm double width restrictions for this instruction. |
| 511 if (!t.IsEven(i)) { | 526 if (!t.IsEven(i)) { |
| 512 return UNDEFINED; | 527 return UNDEFINED; |
| 513 } | 528 } |
| 514 | 529 |
| 515 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { | 530 if (RegisterList(t2.reg(i)).Add(m.reg(i)).Contains(kRegisterPc)) { |
| 516 return UNPREDICTABLE; | 531 return UNPREDICTABLE; |
| 517 } | 532 } |
| 518 | 533 |
| 519 if (HasWriteBack(i) && | 534 if (HasWriteBack(i) && |
| 520 (n.reg(i).Equals(kRegisterPc) || n.reg(i).Equals(t.reg(i)) || | 535 (n.reg(i).Equals(kRegisterPc))) { |
| 521 n.reg(i).Equals(t2.reg(i)))) { | 536 // NOTE: The manual states that that it is also unpredictable |
| 537 // when HasWriteBack(i) and Rn=Rt or Rn=Rt2. However, the compilers |
| 538 // may not check for this. For the moment, we are changing |
| 539 // the code to ignore this case for stores. |
| 540 // TODO(karl): Should we not allow this? |
| 522 return UNPREDICTABLE; | 541 return UNPREDICTABLE; |
| 523 } | 542 } |
| 524 | 543 |
| 525 // Now apply non-double width restrictions for this instruction. | 544 // Now apply non-double width restrictions for this instruction. |
| 526 return StrRegister::safety(i); | 545 return StrRegister::safety(i); |
| 527 } | 546 } |
| 528 | 547 |
| 529 Register LoadExclusive::base_address_register(const Instruction i) const { | 548 Register LoadExclusive::base_address_register(const Instruction i) const { |
| 530 return Rn(i); | 549 return Rn(i); |
| 531 } | 550 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 Add(PreindexingFlag(i) ? kRegisterLink : kRegisterNone); | 691 Add(PreindexingFlag(i) ? kRegisterLink : kRegisterNone); |
| 673 } | 692 } |
| 674 | 693 |
| 675 int32_t Branch::branch_target_offset(const Instruction i) const { | 694 int32_t Branch::branch_target_offset(const Instruction i) const { |
| 676 // Sign extend and shift left 2: | 695 // Sign extend and shift left 2: |
| 677 int32_t offset = (int32_t)(i.Bits(23, 0) << 8) >> 6; | 696 int32_t offset = (int32_t)(i.Bits(23, 0) << 8) >> 6; |
| 678 return offset + 8; // because r15 reads as 8 bytes ahead | 697 return offset + 8; // because r15 reads as 8 bytes ahead |
| 679 } | 698 } |
| 680 | 699 |
| 681 } // namespace | 700 } // namespace |
| OLD | NEW |