OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
6 #include <setjmp.h> | 6 #include <setjmp.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
10 #if defined(TARGET_ARCH_ARM64) | 10 #if defined(TARGET_ARCH_ARM64) |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 ~SimulatorDebugger(); | 86 ~SimulatorDebugger(); |
87 | 87 |
88 void Stop(Instr* instr, const char* message); | 88 void Stop(Instr* instr, const char* message); |
89 void Debug(); | 89 void Debug(); |
90 char* ReadLine(const char* prompt); | 90 char* ReadLine(const char* prompt); |
91 | 91 |
92 private: | 92 private: |
93 Simulator* sim_; | 93 Simulator* sim_; |
94 | 94 |
95 bool GetValue(char* desc, int64_t* value); | 95 bool GetValue(char* desc, int64_t* value); |
96 // TODO(zra): GetVValue for doubles. | 96 bool GetDValue(char* desc, int64_t* value); |
97 // TODO(zra): Breakpoints. | 97 // TODO(zra): Breakpoints. |
98 }; | 98 }; |
99 | 99 |
100 | 100 |
101 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 101 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
102 sim_ = sim; | 102 sim_ = sim; |
103 } | 103 } |
104 | 104 |
105 | 105 |
106 SimulatorDebugger::~SimulatorDebugger() { | 106 SimulatorDebugger::~SimulatorDebugger() { |
(...skipping 29 matching lines...) Expand all Loading... |
136 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 136 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
137 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 137 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
138 if (strcmp(kNames[i], name) == 0) { | 138 if (strcmp(kNames[i], name) == 0) { |
139 return kRegisters[i]; | 139 return kRegisters[i]; |
140 } | 140 } |
141 } | 141 } |
142 return kNoRegister; | 142 return kNoRegister; |
143 } | 143 } |
144 | 144 |
145 | 145 |
| 146 static VRegister LookupVRegisterByName(const char* name) { |
| 147 int reg_nr = -1; |
| 148 bool ok = SScanF(name, "v%d", ®_nr); |
| 149 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfVRegisters)) { |
| 150 return static_cast<VRegister>(reg_nr); |
| 151 } |
| 152 return kNoVRegister; |
| 153 } |
| 154 |
| 155 |
146 bool SimulatorDebugger::GetValue(char* desc, int64_t* value) { | 156 bool SimulatorDebugger::GetValue(char* desc, int64_t* value) { |
147 Register reg = LookupCpuRegisterByName(desc); | 157 Register reg = LookupCpuRegisterByName(desc); |
148 if (reg != kNoRegister) { | 158 if (reg != kNoRegister) { |
149 if (reg == ZR) { | 159 if (reg == ZR) { |
150 *value = 0; | 160 *value = 0; |
151 return true; | 161 return true; |
152 } | 162 } |
153 *value = sim_->get_register(reg); | 163 *value = sim_->get_register(reg); |
154 return true; | 164 return true; |
155 } | 165 } |
(...skipping 12 matching lines...) Expand all Loading... |
168 return true; | 178 return true; |
169 } | 179 } |
170 bool retval = SScanF(desc, "0x%"Px64, value) == 1; | 180 bool retval = SScanF(desc, "0x%"Px64, value) == 1; |
171 if (!retval) { | 181 if (!retval) { |
172 retval = SScanF(desc, "%"Px64, value) == 1; | 182 retval = SScanF(desc, "%"Px64, value) == 1; |
173 } | 183 } |
174 return retval; | 184 return retval; |
175 } | 185 } |
176 | 186 |
177 | 187 |
| 188 bool SimulatorDebugger::GetDValue(char* desc, int64_t* value) { |
| 189 VRegister vreg = LookupVRegisterByName(desc); |
| 190 if (vreg != kNoVRegister) { |
| 191 *value = sim_->get_vregisterd(vreg); |
| 192 return true; |
| 193 } |
| 194 if (desc[0] == '*') { |
| 195 int64_t addr; |
| 196 if (GetValue(desc + 1, &addr)) { |
| 197 if (Simulator::IsIllegalAddress(addr)) { |
| 198 return false; |
| 199 } |
| 200 *value = *(reinterpret_cast<int64_t*>(addr)); |
| 201 return true; |
| 202 } |
| 203 } |
| 204 return false; |
| 205 } |
| 206 |
| 207 |
178 void SimulatorDebugger::Debug() { | 208 void SimulatorDebugger::Debug() { |
179 intptr_t last_pc = -1; | 209 intptr_t last_pc = -1; |
180 bool done = false; | 210 bool done = false; |
181 | 211 |
182 #define COMMAND_SIZE 63 | 212 #define COMMAND_SIZE 63 |
183 #define ARG_SIZE 255 | 213 #define ARG_SIZE 255 |
184 | 214 |
185 #define STR(a) #a | 215 #define STR(a) #a |
186 #define XSTR(a) STR(a) | 216 #define XSTR(a) STR(a) |
187 | 217 |
(...skipping 30 matching lines...) Expand all Loading... |
218 "%" XSTR(ARG_SIZE) "s " | 248 "%" XSTR(ARG_SIZE) "s " |
219 "%" XSTR(ARG_SIZE) "s", | 249 "%" XSTR(ARG_SIZE) "s", |
220 cmd, arg1, arg2); | 250 cmd, arg1, arg2); |
221 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 251 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
222 OS::Print("c/cont -- continue execution\n" | 252 OS::Print("c/cont -- continue execution\n" |
223 "disasm -- disassemble instrs at current pc location\n" | 253 "disasm -- disassemble instrs at current pc location\n" |
224 " other variants are:\n" | 254 " other variants are:\n" |
225 " disasm <address>\n" | 255 " disasm <address>\n" |
226 " disasm <address> <number_of_instructions>\n" | 256 " disasm <address> <number_of_instructions>\n" |
227 " by default 10 instrs are disassembled\n" | 257 " by default 10 instrs are disassembled\n" |
| 258 "flags -- print flag values\n" |
228 "gdb -- transfer control to gdb\n" | 259 "gdb -- transfer control to gdb\n" |
229 "h/help -- print this help string\n" | 260 "h/help -- print this help string\n" |
230 "p/print <reg or value or *addr> -- print integer value\n" | 261 "p/print <reg or value or *addr> -- print integer value\n" |
| 262 "pd/printdouble <dreg or *addr> -- print double value\n" |
231 "po/printobject <*reg or *addr> -- print object\n" | 263 "po/printobject <*reg or *addr> -- print object\n" |
232 "si/stepi -- single step an instruction\n" | 264 "si/stepi -- single step an instruction\n" |
233 "q/quit -- Quit the debugger and exit the program\n"); | 265 "q/quit -- Quit the debugger and exit the program\n"); |
234 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 266 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
235 OS::Print("Quitting\n"); | 267 OS::Print("Quitting\n"); |
236 OS::Exit(0); | 268 OS::Exit(0); |
237 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 269 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
238 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 270 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
239 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 271 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
240 // Execute the one instruction we broke at with breakpoints disabled. | 272 // Execute the one instruction we broke at with breakpoints disabled. |
241 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 273 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
242 // Leave the debugger shell. | 274 // Leave the debugger shell. |
243 done = true; | 275 done = true; |
244 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 276 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
245 if (args == 2) { | 277 if (args == 2) { |
246 int64_t value; | 278 int64_t value; |
247 if (GetValue(arg1, &value)) { | 279 if (GetValue(arg1, &value)) { |
248 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value); | 280 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value); |
249 } else { | 281 } else { |
250 OS::Print("%s unrecognized\n", arg1); | 282 OS::Print("%s unrecognized\n", arg1); |
251 } | 283 } |
252 } else { | 284 } else { |
253 OS::Print("print <reg or value or *addr>\n"); | 285 OS::Print("print <reg or value or *addr>\n"); |
254 } | 286 } |
| 287 } else if ((strcmp(cmd, "pd") == 0) || |
| 288 (strcmp(cmd, "printdouble") == 0)) { |
| 289 if (args == 2) { |
| 290 int64_t long_value; |
| 291 if (GetDValue(arg1, &long_value)) { |
| 292 double dvalue = bit_cast<double, int64_t>(long_value); |
| 293 OS::Print("%s: %"Pu64" 0x%"Px64" %.8g\n", |
| 294 arg1, long_value, long_value, dvalue); |
| 295 } else { |
| 296 OS::Print("%s unrecognized\n", arg1); |
| 297 } |
| 298 } else { |
| 299 OS::Print("printdouble <dreg or *addr>\n"); |
| 300 } |
255 } else if ((strcmp(cmd, "po") == 0) || | 301 } else if ((strcmp(cmd, "po") == 0) || |
256 (strcmp(cmd, "printobject") == 0)) { | 302 (strcmp(cmd, "printobject") == 0)) { |
257 if (args == 2) { | 303 if (args == 2) { |
258 int64_t value; | 304 int64_t value; |
259 // Make the dereferencing '*' optional. | 305 // Make the dereferencing '*' optional. |
260 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || | 306 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || |
261 GetValue(arg1, &value)) { | 307 GetValue(arg1, &value)) { |
262 if (Isolate::Current()->heap()->Contains(value)) { | 308 if (Isolate::Current()->heap()->Contains(value)) { |
263 OS::Print("%s: \n", arg1); | 309 OS::Print("%s: \n", arg1); |
264 #if defined(DEBUG) | 310 #if defined(DEBUG) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 // If start isn't a valid address, warn and use PC instead | 346 // If start isn't a valid address, warn and use PC instead |
301 OS::Print("First argument yields invalid address: 0x%"Px64"\n", | 347 OS::Print("First argument yields invalid address: 0x%"Px64"\n", |
302 start); | 348 start); |
303 OS::Print("Using PC instead\n"); | 349 OS::Print("Using PC instead\n"); |
304 start = sim_->get_pc(); | 350 start = sim_->get_pc(); |
305 } | 351 } |
306 end = start + (length * Instr::kInstrSize); | 352 end = start + (length * Instr::kInstrSize); |
307 } | 353 } |
308 } | 354 } |
309 Disassembler::Disassemble(start, end); | 355 Disassembler::Disassemble(start, end); |
| 356 } else if (strcmp(cmd, "flags") == 0) { |
| 357 OS::Print("APSR: "); |
| 358 OS::Print("N flag: %d; ", sim_->n_flag_); |
| 359 OS::Print("Z flag: %d; ", sim_->z_flag_); |
| 360 OS::Print("C flag: %d; ", sim_->c_flag_); |
| 361 OS::Print("V flag: %d\n", sim_->v_flag_); |
| 362 OS::Print("FPSCR: "); |
| 363 OS::Print("N flag: %d; ", sim_->fp_n_flag_); |
| 364 OS::Print("Z flag: %d; ", sim_->fp_z_flag_); |
| 365 OS::Print("C flag: %d; ", sim_->fp_c_flag_); |
| 366 OS::Print("V flag: %d\n", sim_->fp_v_flag_); |
310 } else if (strcmp(cmd, "gdb") == 0) { | 367 } else if (strcmp(cmd, "gdb") == 0) { |
311 OS::Print("relinquishing control to gdb\n"); | 368 OS::Print("relinquishing control to gdb\n"); |
312 OS::DebugBreak(); | 369 OS::DebugBreak(); |
313 OS::Print("regaining control from gdb\n"); | 370 OS::Print("regaining control from gdb\n"); |
314 } else { | 371 } else { |
315 OS::Print("Unknown command: %s\n", cmd); | 372 OS::Print("Unknown command: %s\n", cmd); |
316 } | 373 } |
317 } | 374 } |
318 delete[] line; | 375 delete[] line; |
319 } | 376 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 // Setup architecture state. | 468 // Setup architecture state. |
412 // All registers are initialized to zero to start with. | 469 // All registers are initialized to zero to start with. |
413 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 470 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
414 registers_[i] = 0; | 471 registers_[i] = 0; |
415 } | 472 } |
416 n_flag_ = false; | 473 n_flag_ = false; |
417 z_flag_ = false; | 474 z_flag_ = false; |
418 c_flag_ = false; | 475 c_flag_ = false; |
419 v_flag_ = false; | 476 v_flag_ = false; |
420 | 477 |
| 478 for (int i = 0; i < kNumberOfVRegisters; i++) { |
| 479 vregisters_[i].lo = 0; |
| 480 vregisters_[i].hi = 0; |
| 481 } |
| 482 fp_n_flag_ = false; |
| 483 fp_z_flag_ = false; |
| 484 fp_c_flag_ = false; |
| 485 fp_v_flag_ = false; |
| 486 |
421 // The sp is initialized to point to the bottom (high address) of the | 487 // The sp is initialized to point to the bottom (high address) of the |
422 // allocated stack area. | 488 // allocated stack area. |
423 registers_[R31] = StackTop(); | 489 registers_[R31] = StackTop(); |
424 // The lr and pc are initialized to a known bad value that will cause an | 490 // The lr and pc are initialized to a known bad value that will cause an |
425 // access violation if the simulator ever tries to execute it. | 491 // access violation if the simulator ever tries to execute it. |
426 registers_[LR] = kBadLR; | 492 registers_[LR] = kBadLR; |
427 pc_ = kBadLR; | 493 pc_ = kBadLR; |
428 } | 494 } |
429 | 495 |
430 | 496 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { | 618 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { |
553 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 619 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
554 if ((reg == R31) && (r31t == R31IsZR)) { | 620 if ((reg == R31) && (r31t == R31IsZR)) { |
555 return 0; | 621 return 0; |
556 } else { | 622 } else { |
557 return registers_[reg]; | 623 return registers_[reg]; |
558 } | 624 } |
559 } | 625 } |
560 | 626 |
561 | 627 |
| 628 int64_t Simulator::get_vregisterd(VRegister reg) { |
| 629 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
| 630 return vregisters_[reg].lo; |
| 631 } |
| 632 |
| 633 |
| 634 void Simulator::set_vregisterd(VRegister reg, int64_t value) { |
| 635 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
| 636 vregisters_[reg].lo = value; |
| 637 vregisters_[reg].hi = 0; |
| 638 } |
| 639 |
| 640 |
562 // Raw access to the PC register. | 641 // Raw access to the PC register. |
563 void Simulator::set_pc(int64_t value) { | 642 void Simulator::set_pc(int64_t value) { |
564 pc_modified_ = true; | 643 pc_modified_ = true; |
565 last_pc_ = pc_; | 644 last_pc_ = pc_; |
566 pc_ = value; | 645 pc_ = value; |
567 } | 646 } |
568 | 647 |
569 | 648 |
570 // Raw access to the pc. | 649 // Raw access to the pc. |
571 int64_t Simulator::get_pc() const { | 650 int64_t Simulator::get_pc() const { |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 void Simulator::SetVFlag(bool val) { | 915 void Simulator::SetVFlag(bool val) { |
837 v_flag_ = val; | 916 v_flag_ = val; |
838 } | 917 } |
839 | 918 |
840 | 919 |
841 void Simulator::DecodeMoveWide(Instr* instr) { | 920 void Simulator::DecodeMoveWide(Instr* instr) { |
842 const Register rd = instr->RdField(); | 921 const Register rd = instr->RdField(); |
843 const int hw = instr->HWField(); | 922 const int hw = instr->HWField(); |
844 const int64_t shift = hw << 4; | 923 const int64_t shift = hw << 4; |
845 const int64_t shifted_imm = | 924 const int64_t shifted_imm = |
846 static_cast<uint64_t>(instr->Imm16Field()) << shift; | 925 static_cast<int64_t>(instr->Imm16Field()) << shift; |
847 | 926 |
848 if (instr->SFField()) { | 927 if (instr->SFField()) { |
849 if (instr->Bits(29, 2) == 0) { | 928 if (instr->Bits(29, 2) == 0) { |
850 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); | 929 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
851 set_register(rd, ~shifted_imm, instr->RdMode()); | 930 set_register(rd, ~shifted_imm, instr->RdMode()); |
852 } else if (instr->Bits(29, 2) == 2) { | 931 } else if (instr->Bits(29, 2) == 2) { |
853 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); | 932 // Format(instr, "movz'sf 'rd, 'imm16 'hw"); |
854 set_register(rd, shifted_imm, instr->RdMode()); | 933 set_register(rd, shifted_imm, instr->RdMode()); |
855 } else if (instr->Bits(29, 2) == 3) { | 934 } else if (instr->Bits(29, 2) == 3) { |
856 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); | 935 // Format(instr, "movk'sf 'rd, 'imm16 'hw"); |
(...skipping 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 UnimplementedInstruction(instr); | 1971 UnimplementedInstruction(instr); |
1893 } | 1972 } |
1894 } | 1973 } |
1895 | 1974 |
1896 | 1975 |
1897 void Simulator::DecodeDPSimd1(Instr* instr) { | 1976 void Simulator::DecodeDPSimd1(Instr* instr) { |
1898 UnimplementedInstruction(instr); | 1977 UnimplementedInstruction(instr); |
1899 } | 1978 } |
1900 | 1979 |
1901 | 1980 |
| 1981 void Simulator::DecodeFPImm(Instr* instr) { |
| 1982 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) || |
| 1983 (instr->Bits(5, 5) != 0)) { |
| 1984 UnimplementedInstruction(instr); |
| 1985 return; |
| 1986 } |
| 1987 if (instr->Bit(22) == 1) { |
| 1988 // Double. |
| 1989 // Format(instr, "fmovd 'vd, #'immd"); |
| 1990 const VRegister vd = instr->VdField(); |
| 1991 const int64_t immd = Instr::VFPExpandImm(instr->Imm8Field()); |
| 1992 set_vregisterd(vd, immd); |
| 1993 } else { |
| 1994 // Single. |
| 1995 UnimplementedInstruction(instr); |
| 1996 } |
| 1997 } |
| 1998 |
| 1999 |
| 2000 void Simulator::DecodeFPIntCvt(Instr* instr) { |
| 2001 if ((instr->SFField() != 1) || (instr->Bit(29) != 0) || |
| 2002 (instr->Bits(22, 2) != 1)) { |
| 2003 UnimplementedInstruction(instr); |
| 2004 return; |
| 2005 } |
| 2006 if (instr->Bits(16, 3) == 6) { |
| 2007 // Format(instr, "fmovrd 'rd, 'vn"); |
| 2008 const VRegister vn = instr->VnField(); |
| 2009 const Register rd = instr->RdField(); |
| 2010 const int64_t vn_val = get_vregisterd(vn); |
| 2011 set_register(rd, vn_val, R31IsZR); |
| 2012 } else if (instr->Bits(16, 3) == 7) { |
| 2013 // Format(instr, "fmovdr 'vd, 'rn"); |
| 2014 const VRegister vd = instr->VdField(); |
| 2015 const Register rn = instr->RnField(); |
| 2016 const int64_t rn_val = get_register(rn, R31IsZR); |
| 2017 set_vregisterd(vd, rn_val); |
| 2018 } else { |
| 2019 UnimplementedInstruction(instr); |
| 2020 } |
| 2021 } |
| 2022 |
| 2023 |
| 2024 void Simulator::DecodeFP(Instr* instr) { |
| 2025 if (instr->IsFPImmOp()) { |
| 2026 DecodeFPImm(instr); |
| 2027 } else if (instr->IsFPIntCvtOp()) { |
| 2028 DecodeFPIntCvt(instr); |
| 2029 } else { |
| 2030 UnimplementedInstruction(instr); |
| 2031 } |
| 2032 } |
| 2033 |
| 2034 |
1902 void Simulator::DecodeDPSimd2(Instr* instr) { | 2035 void Simulator::DecodeDPSimd2(Instr* instr) { |
1903 UnimplementedInstruction(instr); | 2036 if (instr->IsFPOp()) { |
| 2037 DecodeFP(instr); |
| 2038 } else { |
| 2039 UnimplementedInstruction(instr); |
| 2040 } |
1904 } | 2041 } |
1905 | 2042 |
1906 | 2043 |
1907 // Executes the current instruction. | 2044 // Executes the current instruction. |
1908 void Simulator::InstructionDecode(Instr* instr) { | 2045 void Simulator::InstructionDecode(Instr* instr) { |
1909 pc_modified_ = false; | 2046 pc_modified_ = false; |
1910 if (FLAG_trace_sim) { | 2047 if (FLAG_trace_sim) { |
1911 const uword start = reinterpret_cast<uword>(instr); | 2048 const uword start = reinterpret_cast<uword>(instr); |
1912 const uword end = start + Instr::kInstrSize; | 2049 const uword end = start + Instr::kInstrSize; |
1913 Disassembler::Disassemble(start, end); | 2050 Disassembler::Disassemble(start, end); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1970 program_counter = get_pc(); | 2107 program_counter = get_pc(); |
1971 } | 2108 } |
1972 } | 2109 } |
1973 } | 2110 } |
1974 | 2111 |
1975 | 2112 |
1976 int64_t Simulator::Call(int64_t entry, | 2113 int64_t Simulator::Call(int64_t entry, |
1977 int64_t parameter0, | 2114 int64_t parameter0, |
1978 int64_t parameter1, | 2115 int64_t parameter1, |
1979 int64_t parameter2, | 2116 int64_t parameter2, |
1980 int64_t parameter3) { | 2117 int64_t parameter3, |
| 2118 bool fp_return, |
| 2119 bool fp_args) { |
1981 // Save the SP register before the call so we can restore it. | 2120 // Save the SP register before the call so we can restore it. |
1982 intptr_t sp_before_call = get_register(R31, R31IsSP); | 2121 intptr_t sp_before_call = get_register(R31, R31IsSP); |
1983 | 2122 |
1984 // Setup parameters. | 2123 // Setup parameters. |
1985 set_register(R0, parameter0); | 2124 if (fp_args) { |
1986 set_register(R1, parameter1); | 2125 set_vregisterd(V0, parameter0); |
1987 set_register(R2, parameter2); | 2126 set_vregisterd(V1, parameter1); |
1988 set_register(R3, parameter3); | 2127 set_vregisterd(V2, parameter2); |
| 2128 set_vregisterd(V3, parameter3); |
| 2129 } else { |
| 2130 set_register(R0, parameter0); |
| 2131 set_register(R1, parameter1); |
| 2132 set_register(R2, parameter2); |
| 2133 set_register(R3, parameter3); |
| 2134 } |
1989 | 2135 |
1990 // Make sure the activation frames are properly aligned. | 2136 // Make sure the activation frames are properly aligned. |
1991 intptr_t stack_pointer = sp_before_call; | 2137 intptr_t stack_pointer = sp_before_call; |
1992 if (OS::ActivationFrameAlignment() > 1) { | 2138 if (OS::ActivationFrameAlignment() > 1) { |
1993 stack_pointer = | 2139 stack_pointer = |
1994 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment()); | 2140 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment()); |
1995 } | 2141 } |
1996 set_register(R31, stack_pointer, R31IsSP); | 2142 set_register(R31, stack_pointer, R31IsSP); |
1997 | 2143 |
1998 // Prepare to execute the code at entry. | 2144 // Prepare to execute the code at entry. |
1999 set_pc(entry); | 2145 set_pc(entry); |
2000 // Put down marker for end of simulation. The simulator will stop simulation | 2146 // Put down marker for end of simulation. The simulator will stop simulation |
2001 // when the PC reaches this value. By saving the "end simulation" value into | 2147 // when the PC reaches this value. By saving the "end simulation" value into |
2002 // the LR the simulation stops when returning to this call point. | 2148 // the LR the simulation stops when returning to this call point. |
2003 set_register(LR, kEndSimulatingPC); | 2149 set_register(LR, kEndSimulatingPC); |
2004 | 2150 |
2005 // Remember the values of callee-saved registers. | 2151 // Remember the values of callee-saved registers, and set them up with a |
2006 int64_t r19_val = get_register(R19); | 2152 // known value so that we are able to check that they are preserved |
2007 int64_t r20_val = get_register(R20); | 2153 // properly across Dart execution. |
2008 int64_t r21_val = get_register(R21); | 2154 int64_t preserved_vals[kAbiPreservedCpuRegCount]; |
2009 int64_t r22_val = get_register(R22); | 2155 int64_t callee_saved_value = icount_; |
2010 int64_t r23_val = get_register(R23); | 2156 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { |
2011 int64_t r24_val = get_register(R24); | 2157 const Register r = static_cast<Register>(i); |
2012 int64_t r25_val = get_register(R25); | 2158 preserved_vals[i - kAbiFirstPreservedCpuReg] = get_register(r); |
2013 int64_t r26_val = get_register(R26); | 2159 set_register(r, callee_saved_value); |
2014 int64_t r27_val = get_register(R27); | 2160 } |
2015 int64_t r28_val = get_register(R28); | |
2016 int64_t r29_val = get_register(R29); | |
2017 | 2161 |
2018 // Setup the callee-saved registers with a known value. To be able to check | 2162 // Only the bottom half of the V registers must be preserved. |
2019 // that they are preserved properly across dart execution. | 2163 int64_t preserved_dvals[kAbiPreservedFpuRegCount]; |
2020 int64_t callee_saved_value = icount_; | 2164 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { |
2021 set_register(R19, callee_saved_value); | 2165 const VRegister r = static_cast<VRegister>(i); |
2022 set_register(R20, callee_saved_value); | 2166 preserved_dvals[i - kAbiFirstPreservedFpuReg] = get_vregisterd(r); |
2023 set_register(R21, callee_saved_value); | 2167 set_vregisterd(r, callee_saved_value); |
2024 set_register(R22, callee_saved_value); | 2168 } |
2025 set_register(R23, callee_saved_value); | |
2026 set_register(R24, callee_saved_value); | |
2027 set_register(R25, callee_saved_value); | |
2028 set_register(R26, callee_saved_value); | |
2029 set_register(R27, callee_saved_value); | |
2030 set_register(R28, callee_saved_value); | |
2031 set_register(R29, callee_saved_value); | |
2032 | 2169 |
2033 // Start the simulation | 2170 // Start the simulation |
2034 Execute(); | 2171 Execute(); |
2035 | 2172 |
2036 // Check that the callee-saved registers have been preserved. | 2173 // Check that the callee-saved registers have been preserved, |
2037 ASSERT(callee_saved_value == get_register(R19)); | 2174 // and restore them with the original value |
2038 ASSERT(callee_saved_value == get_register(R20)); | 2175 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { |
2039 ASSERT(callee_saved_value == get_register(R21)); | 2176 const Register r = static_cast<Register>(i); |
2040 ASSERT(callee_saved_value == get_register(R22)); | 2177 ASSERT(callee_saved_value == get_register(r)); |
2041 ASSERT(callee_saved_value == get_register(R23)); | 2178 set_register(r, preserved_vals[i - kAbiFirstPreservedCpuReg]); |
2042 ASSERT(callee_saved_value == get_register(R24)); | 2179 } |
2043 ASSERT(callee_saved_value == get_register(R25)); | |
2044 ASSERT(callee_saved_value == get_register(R26)); | |
2045 ASSERT(callee_saved_value == get_register(R27)); | |
2046 ASSERT(callee_saved_value == get_register(R28)); | |
2047 ASSERT(callee_saved_value == get_register(R29)); | |
2048 | 2180 |
2049 // Restore callee-saved registers with the original value. | 2181 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { |
2050 set_register(R19, r19_val); | 2182 const VRegister r = static_cast<VRegister>(i); |
2051 set_register(R20, r20_val); | 2183 ASSERT(callee_saved_value == get_vregisterd(r)); |
2052 set_register(R21, r21_val); | 2184 set_vregisterd(r, preserved_dvals[i - kAbiFirstPreservedFpuReg]); |
2053 set_register(R22, r22_val); | 2185 } |
2054 set_register(R23, r23_val); | |
2055 set_register(R24, r24_val); | |
2056 set_register(R25, r25_val); | |
2057 set_register(R26, r26_val); | |
2058 set_register(R27, r27_val); | |
2059 set_register(R28, r28_val); | |
2060 set_register(R29, r29_val); | |
2061 | 2186 |
2062 // Restore the SP register and return R0. | 2187 // Restore the SP register and return R0. |
2063 set_register(R31, sp_before_call, R31IsSP); | 2188 set_register(R31, sp_before_call, R31IsSP); |
2064 int64_t return_value; | 2189 int64_t return_value; |
2065 return_value = get_register(R0); | 2190 if (fp_return) { |
| 2191 return_value = get_vregisterd(V0); |
| 2192 } else { |
| 2193 return_value = get_register(R0); |
| 2194 } |
2066 return return_value; | 2195 return return_value; |
2067 } | 2196 } |
2068 | 2197 |
2069 | 2198 |
2070 void Simulator::Longjmp(uword pc, | 2199 void Simulator::Longjmp(uword pc, |
2071 uword sp, | 2200 uword sp, |
2072 uword fp, | 2201 uword fp, |
2073 RawObject* raw_exception, | 2202 RawObject* raw_exception, |
2074 RawObject* raw_stacktrace) { | 2203 RawObject* raw_stacktrace) { |
2075 // Walk over all setjmp buffers (simulated --> C++ transitions) | 2204 // Walk over all setjmp buffers (simulated --> C++ transitions) |
(...skipping 23 matching lines...) Expand all Loading... |
2099 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 2228 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
2100 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 2229 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
2101 buf->Longjmp(); | 2230 buf->Longjmp(); |
2102 } | 2231 } |
2103 | 2232 |
2104 } // namespace dart | 2233 } // namespace dart |
2105 | 2234 |
2106 #endif // !defined(HOST_ARCH_ARM64) | 2235 #endif // !defined(HOST_ARCH_ARM64) |
2107 | 2236 |
2108 #endif // defined TARGET_ARCH_ARM64 | 2237 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |