| Index: runtime/vm/simulator_arm64.cc
|
| ===================================================================
|
| --- runtime/vm/simulator_arm64.cc (revision 35439)
|
| +++ runtime/vm/simulator_arm64.cc (working copy)
|
| @@ -131,7 +131,7 @@
|
| R16, R17, R18, R19, R20, R21, R22, R23,
|
| R24, R25, R26, R27, R28, R29, R30,
|
|
|
| - IP0, IP1, PP, CTX, FP, LR, SP, ZR,
|
| + IP0, IP1, PP, CTX, FP, LR, R31, ZR,
|
| };
|
| ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
|
| for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
|
| @@ -146,6 +146,10 @@
|
| bool SimulatorDebugger::GetValue(char* desc, int64_t* value) {
|
| Register reg = LookupCpuRegisterByName(desc);
|
| if (reg != kNoRegister) {
|
| + if (reg == ZR) {
|
| + *value = 0;
|
| + return true;
|
| + }
|
| *value = sim_->get_register(reg);
|
| return true;
|
| }
|
| @@ -592,7 +596,7 @@
|
| // and if not, will likely take a number of additional cycles to execute,
|
| // so let's just not generate any.
|
| void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) {
|
| - char buffer[64];
|
| + char buffer[128];
|
| snprintf(buffer, sizeof(buffer),
|
| "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr);
|
| SimulatorDebugger dbg(this);
|
| @@ -604,8 +608,10 @@
|
|
|
|
|
| void Simulator::UnimplementedInstruction(Instr* instr) {
|
| - char buffer[64];
|
| - snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
|
| + char buffer[128];
|
| + snprintf(buffer, sizeof(buffer),
|
| + "Unimplemented instruction: at %p, last_pc=0x%"Px"\n",
|
| + instr, get_last_pc());
|
| SimulatorDebugger dbg(this);
|
| dbg.Stop(instr, buffer);
|
| FATAL("Cannot continue execution after unimplemented instruction.");
|
| @@ -1010,7 +1016,13 @@
|
|
|
|
|
| bool Simulator::ConditionallyExecute(Instr* instr) {
|
| - switch (instr->ConditionField()) {
|
| + Condition cond;
|
| + if (instr->IsConditionalSelectOp()) {
|
| + cond = instr->SelectConditionField();
|
| + } else {
|
| + cond = instr->ConditionField();
|
| + }
|
| + switch (cond) {
|
| case EQ: return z_flag_;
|
| case NE: return !z_flag_;
|
| case CS: return c_flag_;
|
| @@ -1818,6 +1830,36 @@
|
| }
|
|
|
|
|
| +void Simulator::DecodeConditionalSelect(Instr* instr) {
|
| + if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 0)) {
|
| + // Format(instr, "mov'sf'cond 'rd, 'rn, 'rm");
|
| + const Register rd = instr->RdField();
|
| + const Register rn = instr->RnField();
|
| + const Register rm = instr->RmField();
|
| + if (instr->SFField() == 1) {
|
| + int64_t res = 0;
|
| + if (ConditionallyExecute(instr)) {
|
| + res = get_register(rn, instr->RnMode());
|
| + } else {
|
| + res = get_register(rm, R31IsZR);
|
| + }
|
| + set_register(rd, res, instr->RdMode());
|
| + } else {
|
| + int32_t res = 0;
|
| + if (ConditionallyExecute(instr)) {
|
| + res = get_wregister(rn, instr->RnMode());
|
| + } else {
|
| + res = get_wregister(rm, R31IsZR);
|
| + }
|
| + set_wregister(rd, res, instr->RdMode());
|
| + }
|
| +
|
| + } else {
|
| + UnimplementedInstruction(instr);
|
| + }
|
| +}
|
| +
|
| +
|
| void Simulator::DecodeDPRegister(Instr* instr) {
|
| if (instr->IsAddSubShiftExtOp()) {
|
| DecodeAddSubShiftExt(instr);
|
| @@ -1827,6 +1869,8 @@
|
| DecodeMiscDP2Source(instr);
|
| } else if (instr->IsMiscDP3SourceOp()) {
|
| DecodeMiscDP3Source(instr);
|
| + } else if (instr->IsConditionalSelectOp()) {
|
| + DecodeConditionalSelect(instr);
|
| } else {
|
| UnimplementedInstruction(instr);
|
| }
|
| @@ -1862,9 +1906,10 @@
|
| DecodeDPRegister(instr);
|
| } else if (instr->IsDPSimd1Op()) {
|
| DecodeDPSimd1(instr);
|
| + } else if (instr->IsDPSimd2Op()) {
|
| + DecodeDPSimd2(instr);
|
| } else {
|
| - ASSERT(instr->IsDPSimd2Op());
|
| - DecodeDPSimd2(instr);
|
| + UnimplementedInstruction(instr);
|
| }
|
|
|
| if (!pc_modified_) {
|
|
|