| Index: src/arm/simulator-arm.cc
|
| diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
|
| index 46797d950c32ffb97c0c00cc40a814c27c23178a..7174088ced2f04673a9a33cf12b428e7fc14b17a 100644
|
| --- a/src/arm/simulator-arm.cc
|
| +++ b/src/arm/simulator-arm.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| +// Copyright 2011 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:
|
| @@ -1504,36 +1504,34 @@ static int count_bits(int bit_vector) {
|
| }
|
|
|
|
|
| -// Addressing Mode 4 - Load and Store Multiple
|
| -void Simulator::HandleRList(Instruction* instr, bool load) {
|
| +void Simulator::ProcessPUW(Instruction* instr,
|
| + int num_regs,
|
| + int reg_size,
|
| + intptr_t* start_address,
|
| + intptr_t* end_address) {
|
| int rn = instr->RnValue();
|
| int32_t rn_val = get_register(rn);
|
| - int rlist = instr->RlistValue();
|
| - int num_regs = count_bits(rlist);
|
| -
|
| - intptr_t start_address = 0;
|
| - intptr_t end_address = 0;
|
| switch (instr->PUField()) {
|
| case da_x: {
|
| UNIMPLEMENTED();
|
| break;
|
| }
|
| case ia_x: {
|
| - start_address = rn_val;
|
| - end_address = rn_val + (num_regs * 4) - 4;
|
| - rn_val = rn_val + (num_regs * 4);
|
| + *start_address = rn_val;
|
| + *end_address = rn_val + (num_regs * reg_size) - reg_size;
|
| + rn_val = rn_val + (num_regs * reg_size);
|
| break;
|
| }
|
| case db_x: {
|
| - start_address = rn_val - (num_regs * 4);
|
| - end_address = rn_val - 4;
|
| - rn_val = start_address;
|
| + *start_address = rn_val - (num_regs * reg_size);
|
| + *end_address = rn_val - reg_size;
|
| + rn_val = *start_address;
|
| break;
|
| }
|
| case ib_x: {
|
| - start_address = rn_val + 4;
|
| - end_address = rn_val + (num_regs * 4);
|
| - rn_val = end_address;
|
| + *start_address = rn_val + reg_size;
|
| + *end_address = rn_val + (num_regs * reg_size);
|
| + rn_val = *end_address;
|
| break;
|
| }
|
| default: {
|
| @@ -1544,6 +1542,17 @@ void Simulator::HandleRList(Instruction* instr, bool load) {
|
| if (instr->HasW()) {
|
| set_register(rn, rn_val);
|
| }
|
| +}
|
| +
|
| +// Addressing Mode 4 - Load and Store Multiple
|
| +void Simulator::HandleRList(Instruction* instr, bool load) {
|
| + int rlist = instr->RlistValue();
|
| + int num_regs = count_bits(rlist);
|
| +
|
| + intptr_t start_address = 0;
|
| + intptr_t end_address = 0;
|
| + ProcessPUW(instr, num_regs, kPointerSize, &start_address, &end_address);
|
| +
|
| intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
|
| int reg = 0;
|
| while (rlist != 0) {
|
| @@ -1562,6 +1571,57 @@ void Simulator::HandleRList(Instruction* instr, bool load) {
|
| }
|
|
|
|
|
| +// Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
|
| +void Simulator::HandleVList(Instruction* instr) {
|
| + VFPRegPrecision precision =
|
| + (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
|
| + int operand_size = (precision == kSinglePrecision) ? 4 : 8;
|
| +
|
| + bool load = (instr->VLValue() == 0x1);
|
| +
|
| + int vd;
|
| + int num_regs;
|
| + vd = instr->VFPDRegValue(precision);
|
| + if (precision == kSinglePrecision) {
|
| + num_regs = instr->Immed8Value();
|
| + } else {
|
| + num_regs = instr->Immed8Value() / 2;
|
| + }
|
| +
|
| + intptr_t start_address = 0;
|
| + intptr_t end_address = 0;
|
| + ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address);
|
| +
|
| + intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
|
| + for (int reg = vd; reg < vd + num_regs; reg++) {
|
| + if (precision == kSinglePrecision) {
|
| + if (load) {
|
| + set_s_register_from_sinteger(
|
| + reg, ReadW(reinterpret_cast<int32_t>(address), instr));
|
| + } else {
|
| + WriteW(reinterpret_cast<int32_t>(address),
|
| + get_sinteger_from_s_register(reg), instr);
|
| + }
|
| + address += 1;
|
| + } else {
|
| + if (load) {
|
| + set_s_register_from_sinteger(
|
| + 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr));
|
| + set_s_register_from_sinteger(
|
| + 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr));
|
| + } else {
|
| + WriteW(reinterpret_cast<int32_t>(address),
|
| + get_sinteger_from_s_register(2 * reg), instr);
|
| + WriteW(reinterpret_cast<int32_t>(address + 1),
|
| + get_sinteger_from_s_register(2 * reg + 1), instr);
|
| + }
|
| + address += 2;
|
| + }
|
| + }
|
| + ASSERT_EQ(((intptr_t)address) - operand_size, end_address);
|
| +}
|
| +
|
| +
|
| // Calls into the V8 runtime are based on this very simple interface.
|
| // Note: To be able to return two values from some calls the code in runtime.cc
|
| // uses the ObjectPair which is essentially two 32-bit values stuffed into a
|
| @@ -2945,9 +3005,17 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
|
| }
|
| break;
|
| }
|
| + case 0x4:
|
| + case 0x5:
|
| + case 0x6:
|
| + case 0x7:
|
| + case 0x9:
|
| + case 0xB:
|
| + // Load/store multiple single from memory: vldm/vstm.
|
| + HandleVList(instr);
|
| + break;
|
| default:
|
| UNIMPLEMENTED(); // Not used by V8.
|
| - break;
|
| }
|
| } else if (instr->CoprocessorValue() == 0xB) {
|
| switch (instr->OpcodeValue()) {
|
| @@ -2994,9 +3062,14 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
|
| }
|
| break;
|
| }
|
| + case 0x4:
|
| + case 0x5:
|
| + case 0x9:
|
| + // Load/store multiple double from memory: vldm/vstm.
|
| + HandleVList(instr);
|
| + break;
|
| default:
|
| UNIMPLEMENTED(); // Not used by V8.
|
| - break;
|
| }
|
| } else {
|
| UNIMPLEMENTED(); // Not used by V8.
|
|
|