Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index d12ddbfaa71f04c02d2c243a8dc90e71283a0987..f870edd33b65859ddc0f672ddd899402b56eaf5d 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -26,7 +26,7 @@ |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
#include <stdlib.h> |
- |
+#include <cstdarg> |
#include "v8.h" |
#include "disasm.h" |
@@ -1416,8 +1416,12 @@ void Simulator::DecodeType01(Instr* instr) { |
case CMN: { |
if (instr->HasS()) { |
- Format(instr, "cmn'cond 'rn, 'shift_rm"); |
- Format(instr, "cmn'cond 'rn, 'imm"); |
+ // Format(instr, "cmn'cond 'rn, 'shift_rm"); |
+ // Format(instr, "cmn'cond 'rn, 'imm"); |
+ alu_out = rn_val + shifter_operand; |
+ SetNZFlags(alu_out); |
+ SetCFlag(!CarryFrom(rn_val, shifter_operand)); |
+ SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
} else { |
ASSERT(type == 0); |
int rm = instr->RmField(); |
@@ -1566,6 +1570,7 @@ void Simulator::DecodeType2(Instr* instr) { |
void Simulator::DecodeType3(Instr* instr) { |
+ ASSERT(instr->Bit(4) == 0); |
int rd = instr->RdField(); |
int rn = instr->RnField(); |
int32_t rn_val = get_register(rn); |
@@ -1605,7 +1610,12 @@ void Simulator::DecodeType3(Instr* instr) { |
} |
} |
if (instr->HasB()) { |
- UNIMPLEMENTED(); |
+ if (instr->HasL()) { |
+ uint8_t byte = ReadB(addr); |
+ set_register(rd, byte); |
+ } else { |
+ UNIMPLEMENTED(); |
+ } |
} else { |
if (instr->HasL()) { |
set_register(rd, ReadW(addr, instr)); |
@@ -1654,14 +1664,75 @@ void Simulator::DecodeType7(Instr* instr) { |
} |
+void Simulator::DecodeUnconditional(Instr* instr) { |
+ if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 && instr->HasL()) { |
+ // Load halfword instruction, either register or immediate offset. |
+ int rd = instr->RdField(); |
+ int rn = instr->RnField(); |
+ int32_t rn_val = get_register(rn); |
+ int32_t addr = 0; |
+ int32_t offset; |
+ if (instr->Bit(22) == 0) { |
+ // Register offset. |
+ int rm = instr->RmField(); |
+ offset = get_register(rm); |
+ } else { |
+ // Immediate offset |
+ offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4); |
+ } |
+ switch (instr->PUField()) { |
+ case 0: { |
+ // Post index, negative. |
+ ASSERT(!instr->HasW()); |
+ addr = rn_val; |
+ rn_val -= offset; |
+ set_register(rn, rn_val); |
+ break; |
+ } |
+ case 1: { |
+ // Post index, positive. |
+ ASSERT(!instr->HasW()); |
+ addr = rn_val; |
+ rn_val += offset; |
+ set_register(rn, rn_val); |
+ break; |
+ } |
+ case 2: { |
+ // Pre index or offset, negative. |
+ rn_val -= offset; |
+ addr = rn_val; |
+ if (instr->HasW()) { |
+ set_register(rn, rn_val); |
+ } |
+ break; |
+ } |
+ case 3: { |
+ // Pre index or offset, positive. |
+ rn_val += offset; |
+ addr = rn_val; |
+ if (instr->HasW()) { |
+ set_register(rn, rn_val); |
+ } |
+ break; |
+ } |
+ default: { |
+ // The PU field is a 2-bit field. |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
+ // Not sign extending, so load as unsigned. |
+ uint16_t halfword = ReadH(addr, instr); |
+ set_register(rd, halfword); |
+ } else { |
+ UNIMPLEMENTED(); |
+ } |
+} |
+ |
+ |
// Executes the current instruction. |
void Simulator::InstructionDecode(Instr* instr) { |
pc_modified_ = false; |
- if (instr->ConditionField() == special_condition) { |
- Debugger dbg(this); |
- dbg.Stop(instr); |
- return; |
- } |
if (::v8::internal::FLAG_trace_sim) { |
disasm::NameConverter converter; |
disasm::Disassembler dasm(converter); |
@@ -1671,7 +1742,9 @@ void Simulator::InstructionDecode(Instr* instr) { |
reinterpret_cast<byte*>(instr)); |
PrintF(" 0x%x %s\n", instr, buffer.start()); |
} |
- if (ConditionallyExecute(instr)) { |
+ if (instr->ConditionField() == special_condition) { |
+ DecodeUnconditional(instr); |
+ } else if (ConditionallyExecute(instr)) { |
switch (instr->TypeField()) { |
case 0: |
case 1: { |
@@ -1747,19 +1820,35 @@ void Simulator::Execute() { |
} |
-Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, |
- int32_t p3, int32_t p4) { |
- // Setup parameters |
- set_register(r0, p0); |
- set_register(r1, p1); |
- set_register(r2, p2); |
- set_register(r3, p3); |
- intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp)); |
- *(--stack_pointer) = p4; |
- set_register(sp, reinterpret_cast<int32_t>(stack_pointer)); |
+int32_t Simulator::Call(byte* entry, int argument_count, ...) { |
+ va_list parameters; |
+ va_start(parameters, argument_count); |
+ // Setup arguments |
+ |
+ // First four arguments passed in registers. |
+ ASSERT(argument_count >= 4); |
+ set_register(r0, va_arg(parameters, int32_t)); |
+ set_register(r1, va_arg(parameters, int32_t)); |
+ set_register(r2, va_arg(parameters, int32_t)); |
+ set_register(r3, va_arg(parameters, int32_t)); |
+ |
+ // Remaining arguments passed on stack. |
+ int original_stack = get_register(sp); |
+ // Compute position of stack on entry to generated code. |
+ int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)); |
+ if (OS::ActivationFrameAlignment() != 0) { |
+ entry_stack &= -OS::ActivationFrameAlignment(); |
+ } |
+ // Store remaining arguments on stack, from low to high memory. |
+ intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); |
+ for (int i = 4; i < argument_count; i++) { |
+ stack_argument[i - 4] = va_arg(parameters, int32_t); |
+ } |
+ va_end(parameters); |
+ set_register(sp, entry_stack); |
// Prepare to execute the code at entry |
- set_register(pc, entry); |
+ set_register(pc, reinterpret_cast<int32_t>(entry)); |
// Put down marker for end of simulation. The simulator will stop simulation |
// when the PC reaches this value. By saving the "end simulation" value into |
// the LR the simulation stops when returning to this call point. |
@@ -1793,14 +1882,14 @@ Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, |
Execute(); |
// Check that the callee-saved registers have been preserved. |
- CHECK_EQ(get_register(r4), callee_saved_value); |
- CHECK_EQ(get_register(r5), callee_saved_value); |
- CHECK_EQ(get_register(r6), callee_saved_value); |
- CHECK_EQ(get_register(r7), callee_saved_value); |
- CHECK_EQ(get_register(r8), callee_saved_value); |
- CHECK_EQ(get_register(r9), callee_saved_value); |
- CHECK_EQ(get_register(r10), callee_saved_value); |
- CHECK_EQ(get_register(r11), callee_saved_value); |
+ CHECK_EQ(callee_saved_value, get_register(r4)); |
+ CHECK_EQ(callee_saved_value, get_register(r5)); |
+ CHECK_EQ(callee_saved_value, get_register(r6)); |
+ CHECK_EQ(callee_saved_value, get_register(r7)); |
+ CHECK_EQ(callee_saved_value, get_register(r8)); |
+ CHECK_EQ(callee_saved_value, get_register(r9)); |
+ CHECK_EQ(callee_saved_value, get_register(r10)); |
+ CHECK_EQ(callee_saved_value, get_register(r11)); |
// Restore callee-saved registers with the original value. |
set_register(r4, r4_val); |
@@ -1812,8 +1901,12 @@ Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, |
set_register(r10, r10_val); |
set_register(r11, r11_val); |
- int result = get_register(r0); |
- return reinterpret_cast<Object*>(result); |
+ // Pop stack passed arguments. |
+ CHECK_EQ(entry_stack, get_register(sp)); |
+ set_register(sp, original_stack); |
+ |
+ int32_t result = get_register(r0); |
+ return result; |
} |
} } // namespace assembler::arm |