diff options
Diffstat (limited to 'src/3rdparty/v8/src/arm/simulator-arm.cc')
-rw-r--r-- | src/3rdparty/v8/src/arm/simulator-arm.cc | 284 |
1 files changed, 125 insertions, 159 deletions
diff --git a/src/3rdparty/v8/src/arm/simulator-arm.cc b/src/3rdparty/v8/src/arm/simulator-arm.cc index 629c209..bd7f1bd 100644 --- a/src/3rdparty/v8/src/arm/simulator-arm.cc +++ b/src/3rdparty/v8/src/arm/simulator-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -276,7 +276,7 @@ void ArmDebugger::Debug() { // make them invisible to all commands. UndoBreakpoints(); - while (!done) { + while (!done && !sim_->has_bad_pc()) { if (last_pc != sim_->get_pc()) { disasm::NameConverter converter; disasm::Disassembler dasm(converter); @@ -945,73 +945,31 @@ unsigned int Simulator::get_s_register(int sreg) const { } -void Simulator::set_s_register_from_float(int sreg, const float flt) { - ASSERT((sreg >= 0) && (sreg < num_s_registers)); - // Read the bits from the single precision floating point value - // into the unsigned integer element of vfp_register[] given by index=sreg. - char buffer[sizeof(vfp_register[0])]; - memcpy(buffer, &flt, sizeof(vfp_register[0])); - memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0])); -} - - -void Simulator::set_s_register_from_sinteger(int sreg, const int sint) { - ASSERT((sreg >= 0) && (sreg < num_s_registers)); - // Read the bits from the integer value into the unsigned integer element of - // vfp_register[] given by index=sreg. - char buffer[sizeof(vfp_register[0])]; - memcpy(buffer, &sint, sizeof(vfp_register[0])); - memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0])); -} - - -void Simulator::set_d_register_from_double(int dreg, const double& dbl) { - ASSERT((dreg >= 0) && (dreg < num_d_registers)); - // Read the bits from the double precision floating point value into the two - // consecutive unsigned integer elements of vfp_register[] given by index - // 2*sreg and 2*sreg+1. - char buffer[2 * sizeof(vfp_register[0])]; - memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0])); - memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0])); -} +template<class InputType, int register_size> +void Simulator::SetVFPRegister(int reg_index, const InputType& value) { + ASSERT(reg_index >= 0); + if (register_size == 1) ASSERT(reg_index < num_s_registers); + if (register_size == 2) ASSERT(reg_index < num_d_registers); - -float Simulator::get_float_from_s_register(int sreg) { - ASSERT((sreg >= 0) && (sreg < num_s_registers)); - - float sm_val = 0.0; - // Read the bits from the unsigned integer vfp_register[] array - // into the single precision floating point value and return it. - char buffer[sizeof(vfp_register[0])]; - memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0])); - memcpy(&sm_val, buffer, sizeof(vfp_register[0])); - return(sm_val); + char buffer[register_size * sizeof(vfp_register[0])]; + memcpy(buffer, &value, register_size * sizeof(vfp_register[0])); + memcpy(&vfp_register[reg_index * register_size], buffer, + register_size * sizeof(vfp_register[0])); } -int Simulator::get_sinteger_from_s_register(int sreg) { - ASSERT((sreg >= 0) && (sreg < num_s_registers)); - - int sm_val = 0; - // Read the bits from the unsigned integer vfp_register[] array - // into the single precision floating point value and return it. - char buffer[sizeof(vfp_register[0])]; - memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0])); - memcpy(&sm_val, buffer, sizeof(vfp_register[0])); - return(sm_val); -} +template<class ReturnType, int register_size> +ReturnType Simulator::GetFromVFPRegister(int reg_index) { + ASSERT(reg_index >= 0); + if (register_size == 1) ASSERT(reg_index < num_s_registers); + if (register_size == 2) ASSERT(reg_index < num_d_registers); - -double Simulator::get_double_from_d_register(int dreg) { - ASSERT((dreg >= 0) && (dreg < num_d_registers)); - - double dm_val = 0.0; - // Read the bits from the unsigned integer vfp_register[] array - // into the double precision floating point value and return it. - char buffer[2 * sizeof(vfp_register[0])]; - memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0])); - memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0])); - return(dm_val); + ReturnType value = 0; + char buffer[register_size * sizeof(vfp_register[0])]; + memcpy(buffer, &vfp_register[register_size * reg_index], + register_size * sizeof(vfp_register[0])); + memcpy(&value, buffer, register_size * sizeof(vfp_register[0])); + return value; } @@ -1108,111 +1066,83 @@ void Simulator::TrashCallerSaveRegisters() { int Simulator::ReadW(int32_t addr, Instruction* instr) { -#if V8_TARGET_CAN_READ_UNALIGNED - intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); - return *ptr; -#else - if ((addr & 3) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) { intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); return *ptr; + } else { + PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); + UNIMPLEMENTED(); + return 0; } - PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", - addr, - reinterpret_cast<intptr_t>(instr)); - UNIMPLEMENTED(); - return 0; -#endif } void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { -#if V8_TARGET_CAN_READ_UNALIGNED - intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); - *ptr = value; - return; -#else - if ((addr & 3) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) { intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); *ptr = value; - return; + } else { + PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); + UNIMPLEMENTED(); } - PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", - addr, - reinterpret_cast<intptr_t>(instr)); - UNIMPLEMENTED(); -#endif } uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { -#if V8_TARGET_CAN_READ_UNALIGNED - uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); - return *ptr; -#else - if ((addr & 1) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); return *ptr; + } else { + PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" + V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); + UNIMPLEMENTED(); + return 0; } - PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", - addr, - reinterpret_cast<intptr_t>(instr)); - UNIMPLEMENTED(); - return 0; -#endif } int16_t Simulator::ReadH(int32_t addr, Instruction* instr) { -#if V8_TARGET_CAN_READ_UNALIGNED - int16_t* ptr = reinterpret_cast<int16_t*>(addr); - return *ptr; -#else - if ((addr & 1) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { int16_t* ptr = reinterpret_cast<int16_t*>(addr); return *ptr; + } else { + PrintF("Unaligned signed halfword read at 0x%08x\n", addr); + UNIMPLEMENTED(); + return 0; } - PrintF("Unaligned signed halfword read at 0x%08x\n", addr); - UNIMPLEMENTED(); - return 0; -#endif } void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { -#if V8_TARGET_CAN_READ_UNALIGNED - uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); - *ptr = value; - return; -#else - if ((addr & 1) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); *ptr = value; - return; + } else { + PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" + V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); + UNIMPLEMENTED(); } - PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", - addr, - reinterpret_cast<intptr_t>(instr)); - UNIMPLEMENTED(); -#endif } void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { -#if V8_TARGET_CAN_READ_UNALIGNED - int16_t* ptr = reinterpret_cast<int16_t*>(addr); - *ptr = value; - return; -#else - if ((addr & 1) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { int16_t* ptr = reinterpret_cast<int16_t*>(addr); *ptr = value; - return; + } else { + PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); + UNIMPLEMENTED(); } - PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", - addr, - reinterpret_cast<intptr_t>(instr)); - UNIMPLEMENTED(); -#endif } @@ -1241,37 +1171,26 @@ void Simulator::WriteB(int32_t addr, int8_t value) { int32_t* Simulator::ReadDW(int32_t addr) { -#if V8_TARGET_CAN_READ_UNALIGNED - int32_t* ptr = reinterpret_cast<int32_t*>(addr); - return ptr; -#else - if ((addr & 3) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) { int32_t* ptr = reinterpret_cast<int32_t*>(addr); return ptr; + } else { + PrintF("Unaligned read at 0x%08x\n", addr); + UNIMPLEMENTED(); + return 0; } - PrintF("Unaligned read at 0x%08x\n", addr); - UNIMPLEMENTED(); - return 0; -#endif } void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) { -#if V8_TARGET_CAN_READ_UNALIGNED - int32_t* ptr = reinterpret_cast<int32_t*>(addr); - *ptr++ = value1; - *ptr = value2; - return; -#else - if ((addr & 3) == 0) { + if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) { int32_t* ptr = reinterpret_cast<int32_t*>(addr); *ptr++ = value1; *ptr = value2; - return; + } else { + PrintF("Unaligned write at 0x%08x\n", addr); + UNIMPLEMENTED(); } - PrintF("Unaligned write at 0x%08x\n", addr); - UNIMPLEMENTED(); -#endif } @@ -1468,7 +1387,14 @@ int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) { } case ROR: { - UNIMPLEMENTED(); + if (shift_amount == 0) { + *carry_out = c_flag_; + } else { + uint32_t left = static_cast<uint32_t>(result) >> shift_amount; + uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount); + result = right | left; + *carry_out = (static_cast<uint32_t>(result) >> 31) != 0; + } break; } @@ -1540,7 +1466,14 @@ int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) { } case ROR: { - UNIMPLEMENTED(); + if (shift_amount == 0) { + *carry_out = c_flag_; + } else { + uint32_t left = static_cast<uint32_t>(result) >> shift_amount; + uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount); + result = right | left; + *carry_out = (static_cast<uint32_t>(result) >> 31) != 0; + } break; } @@ -2028,11 +1961,23 @@ void Simulator::DecodeType01(Instruction* instr) { SetNZFlags(alu_out); } } else { - // The MLA instruction description (A 4.1.28) refers to the order - // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the - // Rn field to encode the Rd register and the Rd field to encode - // the Rn register. - Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); + int rd = instr->RdValue(); + int32_t acc_value = get_register(rd); + if (instr->Bit(22) == 0) { + // The MLA instruction description (A 4.1.28) refers to the order + // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the + // Rn field to encode the Rd register and the Rd field to encode + // the Rn register. + // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); + int32_t mul_out = rm_val * rs_val; + int32_t result = acc_value + mul_out; + set_register(rn, result); + } else { + // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); + int32_t mul_out = rm_val * rs_val; + int32_t result = acc_value - mul_out; + set_register(rn, result); + } } } else { // The signed/long multiply instructions use the terms RdHi and RdLo @@ -2252,6 +2197,8 @@ void Simulator::DecodeType01(Instruction* instr) { PrintF("%08x\n", instr->InstructionBits()); UNIMPLEMENTED(); } + } else if ((type == 1) && instr->IsNopType1()) { + // NOP. } else { int rd = instr->RdValue(); int rn = instr->RnValue(); @@ -2408,7 +2355,7 @@ void Simulator::DecodeType01(Instruction* instr) { // Format(instr, "cmn'cond 'rn, 'imm"); alu_out = rn_val + shifter_operand; SetNZFlags(alu_out); - SetCFlag(!CarryFrom(rn_val, shifter_operand)); + SetCFlag(CarryFrom(rn_val, shifter_operand)); SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); } else { // Other instructions matching this pattern are handled in the @@ -2588,6 +2535,25 @@ void Simulator::DecodeType3(Instruction* instr) { break; } case db_x: { + if (FLAG_enable_sudiv) { + if (!instr->HasW()) { + if (instr->Bits(5, 4) == 0x1) { + if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { + // sdiv (in V8 notation matching ARM ISA format) rn = rm/rs + // Format(instr, "'sdiv'cond'b 'rn, 'rm, 'rs); + int rm = instr->RmValue(); + int32_t rm_val = get_register(rm); + int rs = instr->RsValue(); + int32_t rs_val = get_register(rs); + int32_t ret_val = 0; + ASSERT(rs_val != 0); + ret_val = rm_val/rs_val; + set_register(rn, ret_val); + return; + } + } + } + } // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); addr = rn_val - shifter_operand; if (instr->HasW()) { |