| Index: src/arm/simulator-arm.cc | 
| diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc | 
| index 238632aea011818abbd0910608c91062109adf65..807c6047e94a4d2ee99b628e3cca182856bea5aa 100644 | 
| --- a/src/arm/simulator-arm.cc | 
| +++ b/src/arm/simulator-arm.cc | 
| @@ -919,6 +919,54 @@ void Simulator::set_dw_register(int dreg, const int* dbl) { | 
| } | 
|  | 
|  | 
| +void Simulator::get_d_register(int dreg, uint64_t* value) { | 
| +  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); | 
| +  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value)); | 
| +} | 
| + | 
| + | 
| +void Simulator::set_d_register(int dreg, const uint64_t* value) { | 
| +  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); | 
| +  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value)); | 
| +} | 
| + | 
| + | 
| +void Simulator::get_d_register(int dreg, uint32_t* value) { | 
| +  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); | 
| +  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2); | 
| +} | 
| + | 
| + | 
| +void Simulator::set_d_register(int dreg, const uint32_t* value) { | 
| +  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); | 
| +  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2); | 
| +} | 
| + | 
| + | 
| +void Simulator::get_q_register(int qreg, uint64_t* value) { | 
| +  ASSERT((qreg >= 0) && (qreg < num_q_registers)); | 
| +  memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2); | 
| +} | 
| + | 
| + | 
| +void Simulator::set_q_register(int qreg, const uint64_t* value) { | 
| +  ASSERT((qreg >= 0) && (qreg < num_q_registers)); | 
| +  memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2); | 
| +} | 
| + | 
| + | 
| +void Simulator::get_q_register(int qreg, uint32_t* value) { | 
| +  ASSERT((qreg >= 0) && (qreg < num_q_registers)); | 
| +  memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4); | 
| +} | 
| + | 
| + | 
| +void Simulator::set_q_register(int qreg, const uint32_t* value) { | 
| +  ASSERT((qreg >= 0) && (qreg < num_q_registers)); | 
| +  memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4); | 
| +} | 
| + | 
| + | 
| // Raw access to the PC register. | 
| void Simulator::set_pc(int32_t value) { | 
| pc_modified_ = true; | 
| @@ -2596,36 +2644,148 @@ void Simulator::DecodeType3(Instruction* instr) { | 
| break; | 
| } | 
| case ia_x: { | 
| -      if (instr->HasW()) { | 
| -        ASSERT(instr->Bits(5, 4) == 0x1); | 
| - | 
| -        if (instr->Bit(22) == 0x1) {  // USAT. | 
| -          int32_t sat_pos = instr->Bits(20, 16); | 
| -          int32_t sat_val = (1 << sat_pos) - 1; | 
| -          int32_t shift = instr->Bits(11, 7); | 
| -          int32_t shift_type = instr->Bit(6); | 
| -          int32_t rm_val = get_register(instr->RmValue()); | 
| -          if (shift_type == 0) {  // LSL | 
| -            rm_val <<= shift; | 
| -          } else {  // ASR | 
| -            rm_val >>= shift; | 
| +      if (instr->Bit(4) == 0) { | 
| +        // Memop. | 
| +      } else { | 
| +        if (instr->Bit(5) == 0) { | 
| +          switch (instr->Bits(22, 21)) { | 
| +            case 0: | 
| +              if (instr->Bit(20) == 0) { | 
| +                if (instr->Bit(6) == 0) { | 
| +                  // Pkhbt. | 
| +                  uint32_t rn_val = get_register(rn); | 
| +                  uint32_t rm_val = get_register(instr->RmValue()); | 
| +                  int32_t shift = instr->Bits(11, 7); | 
| +                  rm_val <<= shift; | 
| +                  set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U)); | 
| +                } else { | 
| +                  // Pkhtb. | 
| +                  uint32_t rn_val = get_register(rn); | 
| +                  int32_t rm_val = get_register(instr->RmValue()); | 
| +                  int32_t shift = instr->Bits(11, 7); | 
| +                  if (shift == 0) { | 
| +                    shift = 32; | 
| +                  } | 
| +                  rm_val >>= shift; | 
| +                  set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF)); | 
| +                } | 
| +              } else { | 
| +                UNIMPLEMENTED(); | 
| +              } | 
| +              break; | 
| +            case 1: | 
| +              UNIMPLEMENTED(); | 
| +              break; | 
| +            case 2: | 
| +              UNIMPLEMENTED(); | 
| +              break; | 
| +            case 3: { | 
| +              // Usat. | 
| +              int32_t sat_pos = instr->Bits(20, 16); | 
| +              int32_t sat_val = (1 << sat_pos) - 1; | 
| +              int32_t shift = instr->Bits(11, 7); | 
| +              int32_t shift_type = instr->Bit(6); | 
| +              int32_t rm_val = get_register(instr->RmValue()); | 
| +              if (shift_type == 0) {  // LSL | 
| +                rm_val <<= shift; | 
| +              } else {  // ASR | 
| +                rm_val >>= shift; | 
| +              } | 
| +              // If saturation occurs, the Q flag should be set in the CPSR. | 
| +              // There is no Q flag yet, and no instruction (MRS) to read the | 
| +              // CPSR directly. | 
| +              if (rm_val > sat_val) { | 
| +                rm_val = sat_val; | 
| +              } else if (rm_val < 0) { | 
| +                rm_val = 0; | 
| +              } | 
| +              set_register(rd, rm_val); | 
| +              break; | 
| +            } | 
| } | 
| -          // If saturation occurs, the Q flag should be set in the CPSR. | 
| -          // There is no Q flag yet, and no instruction (MRS) to read the | 
| -          // CPSR directly. | 
| -          if (rm_val > sat_val) { | 
| -            rm_val = sat_val; | 
| -          } else if (rm_val < 0) { | 
| -            rm_val = 0; | 
| +        } else { | 
| +          switch (instr->Bits(22, 21)) { | 
| +            case 0: | 
| +              UNIMPLEMENTED(); | 
| +              break; | 
| +            case 1: | 
| +              UNIMPLEMENTED(); | 
| +              break; | 
| +            case 2: | 
| +              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { | 
| +                if (instr->Bits(19, 16) == 0xF) { | 
| +                  // Uxtb16. | 
| +                  uint32_t rm_val = get_register(instr->RmValue()); | 
| +                  int32_t rotate = instr->Bits(11, 10); | 
| +                  switch (rotate) { | 
| +                    case 0: | 
| +                      break; | 
| +                    case 1: | 
| +                      rm_val = (rm_val >> 8) | (rm_val << 24); | 
| +                      break; | 
| +                    case 2: | 
| +                      rm_val = (rm_val >> 16) | (rm_val << 16); | 
| +                      break; | 
| +                    case 3: | 
| +                      rm_val = (rm_val >> 24) | (rm_val << 8); | 
| +                      break; | 
| +                  } | 
| +                  set_register(rd, | 
| +                               (rm_val & 0xFF) | (rm_val & 0xFF0000)); | 
| +                } else { | 
| +                  UNIMPLEMENTED(); | 
| +                } | 
| +              } else { | 
| +                UNIMPLEMENTED(); | 
| +              } | 
| +              break; | 
| +            case 3: | 
| +              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { | 
| +                if (instr->Bits(19, 16) == 0xF) { | 
| +                  // Uxtb. | 
| +                  uint32_t rm_val = get_register(instr->RmValue()); | 
| +                  int32_t rotate = instr->Bits(11, 10); | 
| +                  switch (rotate) { | 
| +                    case 0: | 
| +                      break; | 
| +                    case 1: | 
| +                      rm_val = (rm_val >> 8) | (rm_val << 24); | 
| +                      break; | 
| +                    case 2: | 
| +                      rm_val = (rm_val >> 16) | (rm_val << 16); | 
| +                      break; | 
| +                    case 3: | 
| +                      rm_val = (rm_val >> 24) | (rm_val << 8); | 
| +                      break; | 
| +                  } | 
| +                  set_register(rd, (rm_val & 0xFF)); | 
| +                } else { | 
| +                  // Uxtab. | 
| +                  uint32_t rn_val = get_register(rn); | 
| +                  uint32_t rm_val = get_register(instr->RmValue()); | 
| +                  int32_t rotate = instr->Bits(11, 10); | 
| +                  switch (rotate) { | 
| +                    case 0: | 
| +                      break; | 
| +                    case 1: | 
| +                      rm_val = (rm_val >> 8) | (rm_val << 24); | 
| +                      break; | 
| +                    case 2: | 
| +                      rm_val = (rm_val >> 16) | (rm_val << 16); | 
| +                      break; | 
| +                    case 3: | 
| +                      rm_val = (rm_val >> 24) | (rm_val << 8); | 
| +                      break; | 
| +                  } | 
| +                  set_register(rd, rn_val + (rm_val & 0xFF)); | 
| +                } | 
| +              } else { | 
| +                UNIMPLEMENTED(); | 
| +              } | 
| +              break; | 
| } | 
| -          set_register(rd, rm_val); | 
| -        } else {  // SSAT. | 
| -          UNIMPLEMENTED(); | 
| } | 
| return; | 
| -      } else { | 
| -        Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); | 
| -        UNIMPLEMENTED(); | 
| } | 
| break; | 
| } | 
| @@ -3349,6 +3509,156 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { | 
| } | 
|  | 
|  | 
| +void Simulator::DecodeSpecialCondition(Instruction* instr) { | 
| +  switch (instr->SpecialValue()) { | 
| +    case 5: | 
| +      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && | 
| +          (instr->Bit(4) == 1)) { | 
| +        // vmovl signed | 
| +        int Vd = (instr->Bit(22) << 4) | instr->VdValue(); | 
| +        int Vm = (instr->Bit(5) << 4) | instr->VmValue(); | 
| +        int imm3 = instr->Bits(21, 19); | 
| +        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); | 
| +        int esize = 8 * imm3; | 
| +        int elements = 64 / esize; | 
| +        int8_t from[8]; | 
| +        get_d_register(Vm, reinterpret_cast<uint64_t*>(from)); | 
| +        int16_t to[8]; | 
| +        int e = 0; | 
| +        while (e < elements) { | 
| +          to[e] = from[e]; | 
| +          e++; | 
| +        } | 
| +        set_q_register(Vd, reinterpret_cast<uint64_t*>(to)); | 
| +      } else { | 
| +        UNIMPLEMENTED(); | 
| +      } | 
| +      break; | 
| +    case 7: | 
| +      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && | 
| +          (instr->Bit(4) == 1)) { | 
| +        // vmovl unsigned | 
| +        int Vd = (instr->Bit(22) << 4) | instr->VdValue(); | 
| +        int Vm = (instr->Bit(5) << 4) | instr->VmValue(); | 
| +        int imm3 = instr->Bits(21, 19); | 
| +        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); | 
| +        int esize = 8 * imm3; | 
| +        int elements = 64 / esize; | 
| +        uint8_t from[8]; | 
| +        get_d_register(Vm, reinterpret_cast<uint64_t*>(from)); | 
| +        uint16_t to[8]; | 
| +        int e = 0; | 
| +        while (e < elements) { | 
| +          to[e] = from[e]; | 
| +          e++; | 
| +        } | 
| +        set_q_register(Vd, reinterpret_cast<uint64_t*>(to)); | 
| +      } else { | 
| +        UNIMPLEMENTED(); | 
| +      } | 
| +      break; | 
| +    case 8: | 
| +      if (instr->Bits(21, 20) == 0) { | 
| +        // vst1 | 
| +        int Vd = (instr->Bit(22) << 4) | instr->VdValue(); | 
| +        int Rn = instr->VnValue(); | 
| +        int type = instr->Bits(11, 8); | 
| +        int Rm = instr->VmValue(); | 
| +        int32_t address = get_register(Rn); | 
| +        int regs = 0; | 
| +        switch (type) { | 
| +          case nlt_1: | 
| +            regs = 1; | 
| +            break; | 
| +          case nlt_2: | 
| +            regs = 2; | 
| +            break; | 
| +          case nlt_3: | 
| +            regs = 3; | 
| +            break; | 
| +          case nlt_4: | 
| +            regs = 4; | 
| +            break; | 
| +          default: | 
| +            UNIMPLEMENTED(); | 
| +            break; | 
| +        } | 
| +        int r = 0; | 
| +        while (r < regs) { | 
| +          uint32_t data[2]; | 
| +          get_d_register(Vd + r, data); | 
| +          WriteW(address, data[0], instr); | 
| +          WriteW(address + 4, data[1], instr); | 
| +          address += 8; | 
| +          r++; | 
| +        } | 
| +        if (Rm != 15) { | 
| +          if (Rm == 13) { | 
| +            set_register(Rn, address); | 
| +          } else { | 
| +            set_register(Rn, get_register(Rn) + get_register(Rm)); | 
| +          } | 
| +        } | 
| +      } else if (instr->Bits(21, 20) == 2) { | 
| +        // vld1 | 
| +        int Vd = (instr->Bit(22) << 4) | instr->VdValue(); | 
| +        int Rn = instr->VnValue(); | 
| +        int type = instr->Bits(11, 8); | 
| +        int Rm = instr->VmValue(); | 
| +        int32_t address = get_register(Rn); | 
| +        int regs = 0; | 
| +        switch (type) { | 
| +          case nlt_1: | 
| +            regs = 1; | 
| +            break; | 
| +          case nlt_2: | 
| +            regs = 2; | 
| +            break; | 
| +          case nlt_3: | 
| +            regs = 3; | 
| +            break; | 
| +          case nlt_4: | 
| +            regs = 4; | 
| +            break; | 
| +          default: | 
| +            UNIMPLEMENTED(); | 
| +            break; | 
| +        } | 
| +        int r = 0; | 
| +        while (r < regs) { | 
| +          uint32_t data[2]; | 
| +          data[0] = ReadW(address, instr); | 
| +          data[1] = ReadW(address + 4, instr); | 
| +          set_d_register(Vd + r, data); | 
| +          address += 8; | 
| +          r++; | 
| +        } | 
| +        if (Rm != 15) { | 
| +          if (Rm == 13) { | 
| +            set_register(Rn, address); | 
| +          } else { | 
| +            set_register(Rn, get_register(Rn) + get_register(Rm)); | 
| +          } | 
| +        } | 
| +      } else { | 
| +        UNIMPLEMENTED(); | 
| +      } | 
| +      break; | 
| +    case 0xA: | 
| +    case 0xB: | 
| +      if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { | 
| +        // pld: ignore instruction. | 
| +      } else { | 
| +        UNIMPLEMENTED(); | 
| +      } | 
| +      break; | 
| +    default: | 
| +      UNIMPLEMENTED(); | 
| +      break; | 
| +  } | 
| +} | 
| + | 
| + | 
| // Executes the current instruction. | 
| void Simulator::InstructionDecode(Instruction* instr) { | 
| if (v8::internal::FLAG_check_icache) { | 
| @@ -3365,7 +3675,7 @@ void Simulator::InstructionDecode(Instruction* instr) { | 
| PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); | 
| } | 
| if (instr->ConditionField() == kSpecialCondition) { | 
| -    UNIMPLEMENTED(); | 
| +    DecodeSpecialCondition(instr); | 
| } else if (ConditionallyExecute(instr)) { | 
| switch (instr->TypeValue()) { | 
| case 0: | 
|  |