Index: src/trusted/validator_arm/inst_classes.cc |
diff --git a/src/trusted/validator_arm/inst_classes.cc b/src/trusted/validator_arm/inst_classes.cc |
index 9b7a9bac7692a0445e363f82d5b42382b6cee436..fa87798ebd3bf940371b53708f167b9bc2be5ac1 100644 |
--- a/src/trusted/validator_arm/inst_classes.cc |
+++ b/src/trusted/validator_arm/inst_classes.cc |
@@ -5,7 +5,8 @@ |
*/ |
#include "native_client/src/trusted/validator_arm/inst_classes.h" |
- |
+// TODO(mrm) remove when debug is gone |
+#include <stdio.h> |
/* |
* Implementations of instruction classes, for those not completely defined in |
* the header. |
@@ -419,4 +420,274 @@ int32_t Branch::branch_target_offset(const Instruction i) const { |
return offset + 8; // because r15 reads as 8 bytes ahead |
} |
+/* Thumb Functions */ |
+SafetyLevel Def3::safety(Instruction i) const { |
+ /* If it tries to write to PC, unsafe */ |
+ if (defs(i)[kRegisterPc]) { |
+ return FORBIDDEN_OPERANDS; |
+ } |
+ return MAY_BE_SAFE; |
+} |
+ |
+RegisterList Def3::defs(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+SafetyLevel Def8_10::safety(Instruction i) const { |
+ // TODO(mrm) should be encoding impossible, check |
+ if (defs(i)[kRegisterPc]) { |
+ return FORBIDDEN_OPERANDS; |
+ } |
+ return MAY_BE_SAFE; |
+} |
+ |
+RegisterList Def8_10::defs(Instruction i) const { |
+ return i.reg(10, 8); |
+} |
+ |
+SafetyLevel MemOpThumb::safety(Instruction i) const { |
+ // Don't let addressing writeback alter PC. |
+ // TODO(mrm): Check if this is possible, we may be able to remove this. |
+ if (defs(i)[kRegisterPc]) return FORBIDDEN_OPERANDS; |
+ |
+ return MAY_BE_SAFE; |
+} |
+ |
+Register MemOpThumb::base_address_register(Instruction i) const { |
+ return i.reg(5, 3); |
+} |
+ |
+RegisterList MemOpThumbLoad::defs(Instruction i) const { |
+ return i.reg(2, 0); |
+} |
+ |
+// TODO(mrm) double check, this is suspect |
+// Specifically, double check if I need to +4 things? |
+int32_t CmpBrZ::branch_target_offset(Instruction i) const { |
+ return int32_t ((i.bits(9, 9) << 6) & (i.bits(7, 3) << 1)); |
+} |
+ |
+RegisterList PopMult::defs(Instruction i) const { |
+ return RegisterList(i.bits(7, 0)) + kRegisterStack; |
+} |
+ |
+SafetyLevel BranchTCond::safety(Instruction i) const { |
+ if ((condition(i) & 14) != 14) |
+ return MAY_BE_SAFE; |
+ return FORBIDDEN_OPERANDS; |
+} |
+ |
+// TODO(mrm) Check if I need to +4 |
+int32_t BranchT1::branch_target_offset(Instruction i) const { |
+ // Sign extend and left shift by one |
+ return ((int32_t)(i.bits(7, 0) << 24)) >> 23; |
+} |
+ |
+// TODO(mrm) write test |
+Instruction::Condition BranchT1::condition(Instruction i) const { |
+ return (Instruction::Condition)i.bits(11, 8); |
+} |
+ |
+// TODO(mrm) Check if I need to +4 |
+int32_t BranchT2::branch_target_offset(Instruction i) const { |
+ // Sign extend and left shift by one. |
+ return ((int32_t)(i.bits(10, 0) << 21)) >> 20; |
+} |
+ |
+// TODO(mrm) Check if I need to +4 |
+int32_t BranchT3::branch_target_offset(Instruction i) const { |
+ // Construct the value |
+ uint32_t val = ((((((((i.bit(10) << 1) | i.bit(27)) << 1) | i.bit(29)) << 6) |
+ | i.bits(5, 0)) << 11) | i.bits(26, 16)) << 1; |
Karl
2011/08/30 19:53:52
My head huts trying to figure out what this statem
|
+ // Sign extend it. |
+ return ((int32_t)(val << 9)) >> 9; |
Karl
2011/08/30 19:53:52
Again, there must be some knowledge here that I do
|
+} |
+ |
+Instruction::Condition BranchT3::condition(Instruction i) const { |
+ return (Instruction::Condition)i.bits(9, 6); |
+} |
+ |
+int32_t get_stretched_immediate(Instruction i) { |
+ uint32_t s = i.bit(10); |
+ uint32_t i1 = (~(i.bit(27) ^ s)) & 1; |
+ uint32_t i2 = (~(i.bit(29) ^ s)) & 1; |
+ // Construct the value |
+ uint32_t val = ((((((((i.bit(10) << 1) | i1) << 1) | i2) << 10) |
+ | i.bits(9, 0)) << 11) | i.bits(26, 16)) << 1; |
Karl
2011/08/30 19:53:52
Again, a better comment might be added here.
|
+ // Sign extend it, adjust for pc shift |
+ return (((int32_t)(val << 9)) >> 9); |
+} |
+ |
+int32_t BranchT4::branch_target_offset(Instruction i) const { |
+ return get_stretched_immediate(i) + 4; |
+} |
+ |
+// TODO(mrm) LDMT1/STMT1 could be cleaned up |
+RegisterList LDMT1::defs(Instruction i) const { |
+ return RegisterList(i.bits(7, 0)); |
+} |
+ |
+RegisterList STMT1::defs(Instruction i) const { |
+ return RegisterList(i.bits(7, 0)) + i.reg(10, 8); |
+} |
+ |
+RegisterList STMT1::immediate_addressing_defs(Instruction i) const { |
+ return i.reg(10, 8); |
+} |
+ |
+Register STMT1::base_address_register(Instruction i) const { |
+ return i.reg(10, 8); |
+} |
+ |
+RegisterList LDRLitT1::defs(Instruction i) const { |
+ return i.reg(10, 8); |
+} |
+ |
+RegisterList ADRT1::defs(Instruction i) const { |
+ return i.reg(10, 8); |
+} |
+ |
+RegisterList MemOpSPThumbLoad::defs(Instruction i) const { |
+ return i.reg(10, 8); |
+} |
+ |
+RegisterList DPMImm::defs(Instruction i) const { |
+ return i.reg(27, 24); |
+} |
+ |
+uint32_t get_thumb_modified_immediate(Instruction i) { |
+ uint32_t raw = i.bits(23, 16); |
+ uint8_t shift_mode = (((i.bits(10, 10) << 3) | i.bits(30, 28)) << 1) |
+ | i.bits(23, 23); |
+ switch (shift_mode >> 1) { |
+ case 0: return raw; |
+ case 1: return (raw << 16) | raw; |
+ case 2: return ((raw << 16) | raw) << 8; |
+ case 3: return (((((raw << 8) | raw) << 8) | raw) << 8) | raw; |
+ default: return (raw | (1 << 7)) << (31 - 7 - (shift_mode - 8)); |
+ }; |
+} |
+ |
+bool BicModImmT::clears_bits(Instruction i, uint32_t mask) const { |
+ return (get_thumb_modified_immediate(i) & mask) == mask; |
+} |
+ |
+bool OrrModImmT::sets_bits(Instruction i, uint32_t mask) const { |
+ return get_thumb_modified_immediate(i) == mask; |
+} |
+ |
+RegisterList MovT::defs(Instruction i) const { |
+ return Register((i.bits(7, 7) << 3) | i.bits(2, 0)); |
+} |
+ |
+Register BXT::branch_target_register(Instruction i) const { |
+ return i.reg(6, 3); |
+} |
+ |
+int32_t BLT::branch_target_offset(Instruction i) const { |
+ return get_stretched_immediate(i); |
+} |
+ |
+ITCond IT::it_sequence(Instruction i) const { |
+ uint8_t firstmask = i.bit(4); |
+ ITCond base = it_set(0, THEN, 0); |
+ uint8_t maskdex = 0; |
+ while (i.bit(maskdex) == 0) |
+ maskdex++; |
+ // TODO(mrm) Add a guard to the parse table to make sure the mask is never 0 |
Karl
2011/08/30 19:53:52
This scares me. What if the value is all zero?
|
+ maskdex++; |
+ for (uint8_t conddex = 1; maskdex < 4; maskdex++, conddex++) { |
+ base = it_set(conddex, i.bit(maskdex) == firstmask ? THEN : ELSE, base); |
+ } |
+ return base; |
+} |
+ |
+Instruction::Condition IT::condition(Instruction i) const { |
+ return (Instruction::Condition)i.bits(7, 4); |
+} |
+ |
+RegisterList STMTD::defs(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+Register STMTD::base_address_register(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+RegisterList STMTD::immediate_addressing_defs(Instruction i) const { |
+ return base_address_register(i); |
+} |
+ |
+RegisterList LDMTD::defs(Instruction i) const { |
+ return i.reg(3, 0) + RegisterList(i.bits(12, 0)); |
+} |
+ |
+Register StrS::base_address_register(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+// Note that while this doesn't always write something to i.reg(3, 0), it is |
+// safe to pretend that it does. |
+RegisterList StrS::defs(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+Register LDRImmT3::base_address_register(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+RegisterList LDRImmT4::defs(Instruction i) const { |
+ if (i.bit(8 + 16)) { |
+ return base_address_register(i); // Writeback |
+ } else { |
+ return kRegisterNone; |
+ } |
+} |
+ |
+RegisterList LDRImmT4::immediate_addressing_defs(Instruction i) const { |
+ return defs(i); |
+} |
+ |
+RegisterList Def31_18::defs(Instruction i) const { |
+ return i.reg(31, 18); |
+} |
+ |
+RegisterList StrEx::defs(Instruction i) const { |
+ return immediate_addressing_defs(i) + i.reg(11 + 16, 8 + 16); |
+} |
+ |
+RegisterList StrEx::immediate_addressing_defs(Instruction i) const { |
+ if (i.bit(5)) |
+ return base_address_register(i); |
+ return kRegisterNone; |
+} |
+ |
+Register StrEx::base_address_register(Instruction i) const { |
+ return i.reg(3, 0); |
+} |
+ |
+RegisterList LdrEx::defs(Instruction i) const { |
+ return immediate_addressing_defs(i) + i.reg(15 + 16, 12 + 16); |
Karl
2011/08/30 19:53:52
I notice that numbers like 8/16 are used a lot. It
|
+} |
+ |
+RegisterList StrD::defs(Instruction i) const { |
+ return immediate_addressing_defs(i); |
+} |
+ |
+RegisterList LdrD::defs(Instruction i) const { |
+ return immediate_addressing_defs(i) + i.reg(11 + 16, 8 + 16) |
+ + i.reg(15 + 16, 12 + 16); |
+} |
+ |
+RegisterList Def27_24::defs(Instruction i) const { |
+ return i.reg(27, 24); |
+} |
+ |
+bool ThumbBreakpoint::is_literal_pool_head(Instruction i) const { |
+ UNREFERENCED_PARAMETER(i); |
+ return true; //TODO We ideally want to think about conditions, but due to the |
+ //rule that IT cannot straddle a boundary, and this has to start |
+ //a bundle, we're fine. |
+} |
+ |
} // namespace |