diff options
Diffstat (limited to 'src/core/gdbstub/gdbstub.cpp')
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 268 |
1 files changed, 155 insertions, 113 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 2f3ccb689..2405da0c6 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -57,9 +57,10 @@ const u32 SIGTERM = 15; | |||
| 57 | const u32 MSG_WAITALL = 8; | 57 | const u32 MSG_WAITALL = 8; |
| 58 | #endif | 58 | #endif |
| 59 | 59 | ||
| 60 | const u32 R15_REGISTER = 15; | 60 | const u32 X30_REGISTER = 30; |
| 61 | const u32 CPSR_REGISTER = 25; | 61 | const u32 SP_REGISTER = 31; |
| 62 | const u32 FPSCR_REGISTER = 58; | 62 | const u32 PC_REGISTER = 32; |
| 63 | const u32 CPSR_REGISTER = 33; | ||
| 63 | 64 | ||
| 64 | // For sample XML files see the GDB source /gdb/features | 65 | // For sample XML files see the GDB source /gdb/features |
| 65 | // GDB also wants the l character at the start | 66 | // GDB also wants the l character at the start |
| @@ -68,48 +69,62 @@ static const char* target_xml = | |||
| 68 | R"(l<?xml version="1.0"?> | 69 | R"(l<?xml version="1.0"?> |
| 69 | <!DOCTYPE target SYSTEM "gdb-target.dtd"> | 70 | <!DOCTYPE target SYSTEM "gdb-target.dtd"> |
| 70 | <target version="1.0"> | 71 | <target version="1.0"> |
| 71 | <feature name="org.gnu.gdb.arm.core"> | 72 | <feature name="org.gnu.gdb.aarch64.core"> |
| 72 | <reg name="r0" bitsize="32"/> | 73 | <reg name="x0" bitsize="64"/> |
| 73 | <reg name="r1" bitsize="32"/> | 74 | <reg name="x1" bitsize="64"/> |
| 74 | <reg name="r2" bitsize="32"/> | 75 | <reg name="x2" bitsize="64"/> |
| 75 | <reg name="r3" bitsize="32"/> | 76 | <reg name="x3" bitsize="64"/> |
| 76 | <reg name="r4" bitsize="32"/> | 77 | <reg name="x4" bitsize="64"/> |
| 77 | <reg name="r5" bitsize="32"/> | 78 | <reg name="x5" bitsize="64"/> |
| 78 | <reg name="r6" bitsize="32"/> | 79 | <reg name="x6" bitsize="64"/> |
| 79 | <reg name="r7" bitsize="32"/> | 80 | <reg name="x7" bitsize="64"/> |
| 80 | <reg name="r8" bitsize="32"/> | 81 | <reg name="x8" bitsize="64"/> |
| 81 | <reg name="r9" bitsize="32"/> | 82 | <reg name="x9" bitsize="64"/> |
| 82 | <reg name="r10" bitsize="32"/> | 83 | <reg name="x10" bitsize="64"/> |
| 83 | <reg name="r11" bitsize="32"/> | 84 | <reg name="x11" bitsize="64"/> |
| 84 | <reg name="r12" bitsize="32"/> | 85 | <reg name="x12" bitsize="64"/> |
| 85 | <reg name="sp" bitsize="32" type="data_ptr"/> | 86 | <reg name="x13" bitsize="64"/> |
| 86 | <reg name="lr" bitsize="32"/> | 87 | <reg name="x14" bitsize="64"/> |
| 87 | <reg name="pc" bitsize="32" type="code_ptr"/> | 88 | <reg name="x15" bitsize="64"/> |
| 88 | 89 | <reg name="x16" bitsize="64"/> | |
| 89 | <!-- The CPSR is register 25, rather than register 16, because | 90 | <reg name="x17" bitsize="64"/> |
| 90 | the FPA registers historically were placed between the PC | 91 | <reg name="x18" bitsize="64"/> |
| 91 | and the CPSR in the "g" packet. --> | 92 | <reg name="x19" bitsize="64"/> |
| 92 | 93 | <reg name="x20" bitsize="64"/> | |
| 93 | <reg name="cpsr" bitsize="32" regnum="25"/> | 94 | <reg name="x21" bitsize="64"/> |
| 94 | </feature> | 95 | <reg name="x22" bitsize="64"/> |
| 95 | <feature name="org.gnu.gdb.arm.vfp"> | 96 | <reg name="x23" bitsize="64"/> |
| 96 | <reg name="d0" bitsize="64" type="float"/> | 97 | <reg name="x24" bitsize="64"/> |
| 97 | <reg name="d1" bitsize="64" type="float"/> | 98 | <reg name="x25" bitsize="64"/> |
| 98 | <reg name="d2" bitsize="64" type="float"/> | 99 | <reg name="x26" bitsize="64"/> |
| 99 | <reg name="d3" bitsize="64" type="float"/> | 100 | <reg name="x27" bitsize="64"/> |
| 100 | <reg name="d4" bitsize="64" type="float"/> | 101 | <reg name="x28" bitsize="64"/> |
| 101 | <reg name="d5" bitsize="64" type="float"/> | 102 | <reg name="x29" bitsize="64"/> |
| 102 | <reg name="d6" bitsize="64" type="float"/> | 103 | <reg name="x30" bitsize="64"/> |
| 103 | <reg name="d7" bitsize="64" type="float"/> | 104 | <reg name="sp" bitsize="64" type="data_ptr"/> |
| 104 | <reg name="d8" bitsize="64" type="float"/> | 105 | |
| 105 | <reg name="d9" bitsize="64" type="float"/> | 106 | <reg name="pc" bitsize="64" type="code_ptr"/> |
| 106 | <reg name="d10" bitsize="64" type="float"/> | 107 | |
| 107 | <reg name="d11" bitsize="64" type="float"/> | 108 | <flags id="cpsr_flags" size="4"> |
| 108 | <reg name="d12" bitsize="64" type="float"/> | 109 | <field name="SP" start="0" end="0"/> |
| 109 | <reg name="d13" bitsize="64" type="float"/> | 110 | <field name="" start="1" end="1"/> |
| 110 | <reg name="d14" bitsize="64" type="float"/> | 111 | <field name="EL" start="2" end="3"/> |
| 111 | <reg name="d15" bitsize="64" type="float"/> | 112 | <field name="nRW" start="4" end="4"/> |
| 112 | <reg name="fpscr" bitsize="32" type="int" group="float"/> | 113 | <field name="" start="5" end="5"/> |
| 114 | <field name="F" start="6" end="6"/> | ||
| 115 | <field name="I" start="7" end="7"/> | ||
| 116 | <field name="A" start="8" end="8"/> | ||
| 117 | <field name="D" start="9" end="9"/> | ||
| 118 | |||
| 119 | <field name="IL" start="20" end="20"/> | ||
| 120 | <field name="SS" start="21" end="21"/> | ||
| 121 | |||
| 122 | <field name="V" start="28" end="28"/> | ||
| 123 | <field name="C" start="29" end="29"/> | ||
| 124 | <field name="Z" start="30" end="30"/> | ||
| 125 | <field name="N" start="31" end="31"/> | ||
| 126 | </flags> | ||
| 127 | <reg name="cpsr" bitsize="32" type="cpsr_flags"/> | ||
| 113 | </feature> | 128 | </feature> |
| 114 | </target> | 129 | </target> |
| 115 | )"; | 130 | )"; |
| @@ -143,12 +158,12 @@ WSADATA InitData; | |||
| 143 | struct Breakpoint { | 158 | struct Breakpoint { |
| 144 | bool active; | 159 | bool active; |
| 145 | PAddr addr; | 160 | PAddr addr; |
| 146 | u32 len; | 161 | u64 len; |
| 147 | }; | 162 | }; |
| 148 | 163 | ||
| 149 | static std::map<u32, Breakpoint> breakpoints_execute; | 164 | static std::map<u64, Breakpoint> breakpoints_execute; |
| 150 | static std::map<u32, Breakpoint> breakpoints_read; | 165 | static std::map<u64, Breakpoint> breakpoints_read; |
| 151 | static std::map<u32, Breakpoint> breakpoints_write; | 166 | static std::map<u64, Breakpoint> breakpoints_write; |
| 152 | 167 | ||
| 153 | /** | 168 | /** |
| 154 | * Turns hex string character into the equivalent byte. | 169 | * Turns hex string character into the equivalent byte. |
| @@ -198,6 +213,21 @@ static u32 HexToInt(const u8* src, size_t len) { | |||
| 198 | } | 213 | } |
| 199 | 214 | ||
| 200 | /** | 215 | /** |
| 216 | * Converts input hex string characters into an array of equivalent of u8 bytes. | ||
| 217 | * | ||
| 218 | * @param src Pointer to array of output hex string characters. | ||
| 219 | * @param len Length of src array. | ||
| 220 | */ | ||
| 221 | static u64 HexToLong(const u8* src, size_t len) { | ||
| 222 | u64 output = 0; | ||
| 223 | while (len-- > 0) { | ||
| 224 | output = (output << 4) | HexCharToValue(src[0]); | ||
| 225 | src++; | ||
| 226 | } | ||
| 227 | return output; | ||
| 228 | } | ||
| 229 | |||
| 230 | /** | ||
| 201 | * Converts input array of u8 bytes into their equivalent hex string characters. | 231 | * Converts input array of u8 bytes into their equivalent hex string characters. |
| 202 | * | 232 | * |
| 203 | * @param dest Pointer to buffer to store output hex string characters. | 233 | * @param dest Pointer to buffer to store output hex string characters. |
| @@ -234,8 +264,21 @@ static void GdbHexToMem(u8* dest, const u8* src, size_t len) { | |||
| 234 | */ | 264 | */ |
| 235 | static void IntToGdbHex(u8* dest, u32 v) { | 265 | static void IntToGdbHex(u8* dest, u32 v) { |
| 236 | for (int i = 0; i < 8; i += 2) { | 266 | for (int i = 0; i < 8; i += 2) { |
| 237 | dest[i + 1] = NibbleToHex(v >> (4 * i)); | 267 | dest[i + 1] = NibbleToHex(static_cast<u8>(v >> (4 * i))); |
| 238 | dest[i] = NibbleToHex(v >> (4 * (i + 1))); | 268 | dest[i] = NibbleToHex(static_cast<u8>(v >> (4 * (i + 1)))); |
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | /** | ||
| 273 | * Convert a u64 into a gdb-formatted hex string. | ||
| 274 | * | ||
| 275 | * @param dest Pointer to buffer to store output hex string characters. | ||
| 276 | * @param v Value to convert. | ||
| 277 | */ | ||
| 278 | static void LongToGdbHex(u8* dest, u64 v) { | ||
| 279 | for (int i = 0; i < 16; i += 2) { | ||
| 280 | dest[i + 1] = NibbleToHex(static_cast<u8>(v >> (4 * i))); | ||
| 281 | dest[i] = NibbleToHex(static_cast<u8>(v >> (4 * (i + 1)))); | ||
| 239 | } | 282 | } |
| 240 | } | 283 | } |
| 241 | 284 | ||
| @@ -255,6 +298,22 @@ static u32 GdbHexToInt(const u8* src) { | |||
| 255 | return output; | 298 | return output; |
| 256 | } | 299 | } |
| 257 | 300 | ||
| 301 | /** | ||
| 302 | * Convert a gdb-formatted hex string into a u64. | ||
| 303 | * | ||
| 304 | * @param src Pointer to hex string. | ||
| 305 | */ | ||
| 306 | static u64 GdbHexToLong(const u8* src) { | ||
| 307 | u64 output = 0; | ||
| 308 | |||
| 309 | for (int i = 0; i < 16; i += 2) { | ||
| 310 | output = (output << 4) | HexCharToValue(src[15 - i - 1]); | ||
| 311 | output = (output << 4) | HexCharToValue(src[15 - i]); | ||
| 312 | } | ||
| 313 | |||
| 314 | return output; | ||
| 315 | } | ||
| 316 | |||
| 258 | /// Read a byte from the gdb client. | 317 | /// Read a byte from the gdb client. |
| 259 | static u8 ReadByte() { | 318 | static u8 ReadByte() { |
| 260 | u8 c; | 319 | u8 c; |
| @@ -277,7 +336,7 @@ static u8 CalculateChecksum(const u8* buffer, size_t length) { | |||
| 277 | * | 336 | * |
| 278 | * @param type Type of breakpoint list. | 337 | * @param type Type of breakpoint list. |
| 279 | */ | 338 | */ |
| 280 | static std::map<u32, Breakpoint>& GetBreakpointList(BreakpointType type) { | 339 | static std::map<u64, Breakpoint>& GetBreakpointList(BreakpointType type) { |
| 281 | switch (type) { | 340 | switch (type) { |
| 282 | case BreakpointType::Execute: | 341 | case BreakpointType::Execute: |
| 283 | return breakpoints_execute; | 342 | return breakpoints_execute; |
| @@ -297,19 +356,19 @@ static std::map<u32, Breakpoint>& GetBreakpointList(BreakpointType type) { | |||
| 297 | * @param addr Address of breakpoint. | 356 | * @param addr Address of breakpoint. |
| 298 | */ | 357 | */ |
| 299 | static void RemoveBreakpoint(BreakpointType type, PAddr addr) { | 358 | static void RemoveBreakpoint(BreakpointType type, PAddr addr) { |
| 300 | std::map<u32, Breakpoint>& p = GetBreakpointList(type); | 359 | std::map<u64, Breakpoint>& p = GetBreakpointList(type); |
| 301 | 360 | ||
| 302 | auto bp = p.find(static_cast<u32>(addr)); | 361 | auto bp = p.find(static_cast<u64>(addr)); |
| 303 | if (bp != p.end()) { | 362 | if (bp != p.end()) { |
| 304 | LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: %08x bytes at %08x of type %d\n", | 363 | LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: %08x bytes at %08x of type %d\n", |
| 305 | bp->second.len, bp->second.addr, type); | 364 | bp->second.len, bp->second.addr, type); |
| 306 | p.erase(static_cast<u32>(addr)); | 365 | p.erase(static_cast<u64>(addr)); |
| 307 | } | 366 | } |
| 308 | } | 367 | } |
| 309 | 368 | ||
| 310 | BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { | 369 | BreakpointAddress GetNextBreakpointFromAddress(PAddr addr, BreakpointType type) { |
| 311 | std::map<u32, Breakpoint>& p = GetBreakpointList(type); | 370 | std::map<u64, Breakpoint>& p = GetBreakpointList(type); |
| 312 | auto next_breakpoint = p.lower_bound(static_cast<u32>(addr)); | 371 | auto next_breakpoint = p.lower_bound(static_cast<u64>(addr)); |
| 313 | BreakpointAddress breakpoint; | 372 | BreakpointAddress breakpoint; |
| 314 | 373 | ||
| 315 | if (next_breakpoint != p.end()) { | 374 | if (next_breakpoint != p.end()) { |
| @@ -328,11 +387,11 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) { | |||
| 328 | return false; | 387 | return false; |
| 329 | } | 388 | } |
| 330 | 389 | ||
| 331 | std::map<u32, Breakpoint>& p = GetBreakpointList(type); | 390 | std::map<u64, Breakpoint>& p = GetBreakpointList(type); |
| 332 | 391 | ||
| 333 | auto bp = p.find(static_cast<u32>(addr)); | 392 | auto bp = p.find(static_cast<u64>(addr)); |
| 334 | if (bp != p.end()) { | 393 | if (bp != p.end()) { |
| 335 | u32 len = bp->second.len; | 394 | u64 len = bp->second.len; |
| 336 | 395 | ||
| 337 | // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints | 396 | // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints |
| 338 | // no matter if it's a 4-byte or 2-byte instruction. When you execute a | 397 | // no matter if it's a 4-byte or 2-byte instruction. When you execute a |
| @@ -419,7 +478,7 @@ static void HandleQuery() { | |||
| 419 | SendReply("T0"); | 478 | SendReply("T0"); |
| 420 | } else if (strncmp(query, "Supported", strlen("Supported")) == 0) { | 479 | } else if (strncmp(query, "Supported", strlen("Supported")) == 0) { |
| 421 | // PacketSize needs to be large enough for target xml | 480 | // PacketSize needs to be large enough for target xml |
| 422 | SendReply("PacketSize=800;qXfer:features:read+"); | 481 | SendReply("PacketSize=2000;qXfer:features:read+"); |
| 423 | } else if (strncmp(query, "Xfer:features:read:target.xml:", | 482 | } else if (strncmp(query, "Xfer:features:read:target.xml:", |
| 424 | strlen("Xfer:features:read:target.xml:")) == 0) { | 483 | strlen("Xfer:features:read:target.xml:")) == 0) { |
| 425 | SendReply(target_xml); | 484 | SendReply(target_xml); |
| @@ -450,10 +509,7 @@ static void SendSignal(u32 signal) { | |||
| 450 | 509 | ||
| 451 | latest_signal = signal; | 510 | latest_signal = signal; |
| 452 | 511 | ||
| 453 | std::string buffer = | 512 | std::string buffer = Common::StringFromFormat("T%02x", latest_signal); |
| 454 | Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15, | ||
| 455 | htonl(static_cast<u_long>(Core::CPU().GetPC())), 13, | ||
| 456 | htonl(static_cast<u_long>(Core::CPU().GetReg(13)))); | ||
| 457 | LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); | 513 | LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); |
| 458 | SendReply(buffer.c_str()); | 514 | SendReply(buffer.c_str()); |
| 459 | } | 515 | } |
| @@ -539,16 +595,12 @@ static void ReadRegister() { | |||
| 539 | id |= HexCharToValue(command_buffer[2]); | 595 | id |= HexCharToValue(command_buffer[2]); |
| 540 | } | 596 | } |
| 541 | 597 | ||
| 542 | if (id <= R15_REGISTER) { | 598 | if (id <= SP_REGISTER) { |
| 543 | IntToGdbHex(reply, static_cast<u32>(Core::CPU().GetReg(static_cast<u64>(id)))); | 599 | LongToGdbHex(reply, Core::CPU().GetReg(static_cast<int>(id))); |
| 600 | } else if (id == PC_REGISTER) { | ||
| 601 | LongToGdbHex(reply, Core::CPU().GetPC()); | ||
| 544 | } else if (id == CPSR_REGISTER) { | 602 | } else if (id == CPSR_REGISTER) { |
| 545 | IntToGdbHex(reply, Core::CPU().GetCPSR()); | 603 | IntToGdbHex(reply, Core::CPU().GetCPSR()); |
| 546 | } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { | ||
| 547 | IntToGdbHex(reply, Core::CPU().GetVFPReg( | ||
| 548 | id - CPSR_REGISTER - | ||
| 549 | 1)); // VFP registers should start at 26, so one after CSPR_REGISTER | ||
| 550 | } else if (id == FPSCR_REGISTER) { | ||
| 551 | UNIMPLEMENTED(); | ||
| 552 | } else { | 604 | } else { |
| 553 | return SendReply("E01"); | 605 | return SendReply("E01"); |
| 554 | } | 606 | } |
| @@ -563,21 +615,19 @@ static void ReadRegisters() { | |||
| 563 | 615 | ||
| 564 | u8* bufptr = buffer; | 616 | u8* bufptr = buffer; |
| 565 | 617 | ||
| 566 | for (int reg = 0; reg <= R15_REGISTER; reg++) { | 618 | for (int reg = 0; reg <= SP_REGISTER; reg++) { |
| 567 | IntToGdbHex(bufptr + reg * CHAR_BIT, static_cast<u32>(Core::CPU().GetReg(reg))); | 619 | LongToGdbHex(bufptr + reg * 16, Core::CPU().GetReg(reg)); |
| 568 | } | 620 | } |
| 569 | 621 | ||
| 570 | bufptr += (16 * CHAR_BIT); | 622 | bufptr += (32 * 16); |
| 571 | 623 | ||
| 572 | IntToGdbHex(bufptr, Core::CPU().GetCPSR()); | 624 | LongToGdbHex(bufptr, Core::CPU().GetPC()); |
| 573 | 625 | ||
| 574 | bufptr += CHAR_BIT; | 626 | bufptr += 16; |
| 575 | 627 | ||
| 576 | for (int reg = 0; reg <= 31; reg++) { | 628 | IntToGdbHex(bufptr, Core::CPU().GetCPSR()); |
| 577 | IntToGdbHex(bufptr + reg * CHAR_BIT, Core::CPU().GetVFPReg(reg)); | ||
| 578 | } | ||
| 579 | 629 | ||
| 580 | bufptr += (32 * CHAR_BIT); | 630 | bufptr += 8; |
| 581 | 631 | ||
| 582 | SendReply(reinterpret_cast<char*>(buffer)); | 632 | SendReply(reinterpret_cast<char*>(buffer)); |
| 583 | } | 633 | } |
| @@ -593,14 +643,12 @@ static void WriteRegister() { | |||
| 593 | id |= HexCharToValue(command_buffer[2]); | 643 | id |= HexCharToValue(command_buffer[2]); |
| 594 | } | 644 | } |
| 595 | 645 | ||
| 596 | if (id <= R15_REGISTER) { | 646 | if (id <= SP_REGISTER) { |
| 597 | Core::CPU().SetReg(id, GdbHexToInt(buffer_ptr)); | 647 | Core::CPU().SetReg(id, GdbHexToLong(buffer_ptr)); |
| 648 | } else if (id == PC_REGISTER) { | ||
| 649 | Core::CPU().SetPC(GdbHexToLong(buffer_ptr)); | ||
| 598 | } else if (id == CPSR_REGISTER) { | 650 | } else if (id == CPSR_REGISTER) { |
| 599 | Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr)); | 651 | Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr)); |
| 600 | } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { | ||
| 601 | Core::CPU().SetVFPReg(id - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr)); | ||
| 602 | } else if (id == FPSCR_REGISTER) { | ||
| 603 | UNIMPLEMENTED(); | ||
| 604 | } else { | 652 | } else { |
| 605 | return SendReply("E01"); | 653 | return SendReply("E01"); |
| 606 | } | 654 | } |
| @@ -615,20 +663,14 @@ static void WriteRegisters() { | |||
| 615 | if (command_buffer[0] != 'G') | 663 | if (command_buffer[0] != 'G') |
| 616 | return SendReply("E01"); | 664 | return SendReply("E01"); |
| 617 | 665 | ||
| 618 | for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) { | 666 | for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) { |
| 619 | if (reg <= R15_REGISTER) { | 667 | if (reg <= SP_REGISTER) { |
| 620 | Core::CPU().SetReg(reg, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | 668 | Core::CPU().SetReg(reg, GdbHexToLong(buffer_ptr + i * 16)); |
| 669 | } else if (reg == PC_REGISTER) { | ||
| 670 | Core::CPU().SetPC(GdbHexToLong(buffer_ptr + i * 16)); | ||
| 621 | } else if (reg == CPSR_REGISTER) { | 671 | } else if (reg == CPSR_REGISTER) { |
| 622 | Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | 672 | Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr + i * 16)); |
| 623 | } else if (reg == CPSR_REGISTER - 1) { | 673 | } else { |
| 624 | // Dummy FPA register, ignore | ||
| 625 | } else if (reg < CPSR_REGISTER) { | ||
| 626 | // Dummy FPA registers, ignore | ||
| 627 | i += 2; | ||
| 628 | } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { | ||
| 629 | Core::CPU().SetVFPReg(reg - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | ||
| 630 | i++; // Skip padding | ||
| 631 | } else if (reg == FPSCR_REGISTER) { | ||
| 632 | UNIMPLEMENTED(); | 674 | UNIMPLEMENTED(); |
| 633 | } | 675 | } |
| 634 | } | 676 | } |
| @@ -642,13 +684,13 @@ static void ReadMemory() { | |||
| 642 | 684 | ||
| 643 | auto start_offset = command_buffer + 1; | 685 | auto start_offset = command_buffer + 1; |
| 644 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 686 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 645 | VAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 687 | VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); |
| 646 | 688 | ||
| 647 | start_offset = addr_pos + 1; | 689 | start_offset = addr_pos + 1; |
| 648 | u32 len = | 690 | u64 len = |
| 649 | HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | 691 | HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); |
| 650 | 692 | ||
| 651 | LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len); | 693 | LOG_DEBUG(Debug_GDBStub, "gdb: addr: %016llx len: %016llx\n", addr, len); |
| 652 | 694 | ||
| 653 | if (len * 2 > sizeof(reply)) { | 695 | if (len * 2 > sizeof(reply)) { |
| 654 | SendReply("E01"); | 696 | SendReply("E01"); |
| @@ -670,11 +712,11 @@ static void ReadMemory() { | |||
| 670 | static void WriteMemory() { | 712 | static void WriteMemory() { |
| 671 | auto start_offset = command_buffer + 1; | 713 | auto start_offset = command_buffer + 1; |
| 672 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 714 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 673 | VAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 715 | VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); |
| 674 | 716 | ||
| 675 | start_offset = addr_pos + 1; | 717 | start_offset = addr_pos + 1; |
| 676 | auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); | 718 | auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); |
| 677 | u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); | 719 | u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); |
| 678 | 720 | ||
| 679 | if (!Memory::IsValidVirtualAddress(addr)) { | 721 | if (!Memory::IsValidVirtualAddress(addr)) { |
| 680 | return SendReply("E00"); | 722 | return SendReply("E00"); |
| @@ -727,8 +769,8 @@ static void Continue() { | |||
| 727 | * @param addr Address of breakpoint. | 769 | * @param addr Address of breakpoint. |
| 728 | * @param len Length of breakpoint. | 770 | * @param len Length of breakpoint. |
| 729 | */ | 771 | */ |
| 730 | static bool CommitBreakpoint(BreakpointType type, PAddr addr, u32 len) { | 772 | static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) { |
| 731 | std::map<u32, Breakpoint>& p = GetBreakpointList(type); | 773 | std::map<u64, Breakpoint>& p = GetBreakpointList(type); |
| 732 | 774 | ||
| 733 | Breakpoint breakpoint; | 775 | Breakpoint breakpoint; |
| 734 | breakpoint.active = true; | 776 | breakpoint.active = true; |
| @@ -767,11 +809,11 @@ static void AddBreakpoint() { | |||
| 767 | 809 | ||
| 768 | auto start_offset = command_buffer + 3; | 810 | auto start_offset = command_buffer + 3; |
| 769 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 811 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 770 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 812 | PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); |
| 771 | 813 | ||
| 772 | start_offset = addr_pos + 1; | 814 | start_offset = addr_pos + 1; |
| 773 | u32 len = | 815 | u64 len = |
| 774 | HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | 816 | HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); |
| 775 | 817 | ||
| 776 | if (type == BreakpointType::Access) { | 818 | if (type == BreakpointType::Access) { |
| 777 | // Access is made up of Read and Write types, so add both breakpoints | 819 | // Access is made up of Read and Write types, so add both breakpoints |
| @@ -816,7 +858,7 @@ static void RemoveBreakpoint() { | |||
| 816 | 858 | ||
| 817 | auto start_offset = command_buffer + 3; | 859 | auto start_offset = command_buffer + 3; |
| 818 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 860 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 819 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 861 | PAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); |
| 820 | 862 | ||
| 821 | if (type == BreakpointType::Access) { | 863 | if (type == BreakpointType::Access) { |
| 822 | // Access is made up of Read and Write types, so add both breakpoints | 864 | // Access is made up of Read and Write types, so add both breakpoints |