Chromium Code Reviews| 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 |
|
bsy
2011/09/21 22:32:17
mrm
jasonwkim
2011/09/26 21:35:52
all mrm fixed
|
| +#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 */ |
|
Karl
2011/09/19 19:56:05
Thumb2?
jasonwkim
2011/09/26 21:35:52
Thumb is more correct in this case
|
| +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; |
| + // Sign extend it. |
| + return ((int32_t)(val << 9)) >> 9; |
| +} |
| + |
| +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; |
| + // 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 |
| + 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); |
| +} |
| + |
| +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 |