| 1 | /* gdb-if.c -- sim interface to GDB. |
| 2 | |
| 3 | Copyright (C) 2008-2020 Free Software Foundation, Inc. |
| 4 | Contributed by Red Hat, Inc. |
| 5 | |
| 6 | This file is part of the GNU simulators. |
| 7 | |
| 8 | This program is free software; you can redistribute it and/or modify |
| 9 | it under the terms of the GNU General Public License as published by |
| 10 | the Free Software Foundation; either version 3 of the License, or |
| 11 | (at your option) any later version. |
| 12 | |
| 13 | This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. |
| 17 | |
| 18 | You should have received a copy of the GNU General Public License |
| 19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 20 | |
| 21 | #include "config.h" |
| 22 | #include <stdio.h> |
| 23 | #include <assert.h> |
| 24 | #include <signal.h> |
| 25 | #include <string.h> |
| 26 | #include <ctype.h> |
| 27 | #include <stdlib.h> |
| 28 | |
| 29 | #include "ansidecl.h" |
| 30 | #include "gdb/callback.h" |
| 31 | #include "gdb/remote-sim.h" |
| 32 | #include "gdb/signals.h" |
| 33 | #include "gdb/sim-rx.h" |
| 34 | |
| 35 | #include "cpu.h" |
| 36 | #include "mem.h" |
| 37 | #include "load.h" |
| 38 | #include "syscalls.h" |
| 39 | #include "err.h" |
| 40 | #include "trace.h" |
| 41 | |
| 42 | /* Ideally, we'd wrap up all the minisim's data structures in an |
| 43 | object and pass that around. However, neither GDB nor run needs |
| 44 | that ability. |
| 45 | |
| 46 | So we just have one instance, that lives in global variables, and |
| 47 | each time we open it, we re-initialize it. */ |
| 48 | struct sim_state |
| 49 | { |
| 50 | const char *message; |
| 51 | }; |
| 52 | |
| 53 | static struct sim_state the_minisim = { |
| 54 | "This is the sole rx minisim instance. See libsim.a's global variables." |
| 55 | }; |
| 56 | |
| 57 | static int rx_sim_is_open; |
| 58 | |
| 59 | SIM_DESC |
| 60 | sim_open (SIM_OPEN_KIND kind, |
| 61 | struct host_callback_struct *callback, |
| 62 | struct bfd *abfd, char * const *argv) |
| 63 | { |
| 64 | if (rx_sim_is_open) |
| 65 | fprintf (stderr, "rx minisim: re-opened sim\n"); |
| 66 | |
| 67 | /* The 'run' interface doesn't use this function, so we don't care |
| 68 | about KIND; it's always SIM_OPEN_DEBUG. */ |
| 69 | if (kind != SIM_OPEN_DEBUG) |
| 70 | fprintf (stderr, "rx minisim: sim_open KIND != SIM_OPEN_DEBUG: %d\n", |
| 71 | kind); |
| 72 | |
| 73 | set_callbacks (callback); |
| 74 | |
| 75 | /* We don't expect any command-line arguments. */ |
| 76 | |
| 77 | init_mem (); |
| 78 | init_regs (); |
| 79 | execution_error_init_debugger (); |
| 80 | |
| 81 | sim_disasm_init (abfd); |
| 82 | rx_sim_is_open = 1; |
| 83 | return &the_minisim; |
| 84 | } |
| 85 | |
| 86 | static void |
| 87 | check_desc (SIM_DESC sd) |
| 88 | { |
| 89 | if (sd != &the_minisim) |
| 90 | fprintf (stderr, "rx minisim: desc != &the_minisim\n"); |
| 91 | } |
| 92 | |
| 93 | void |
| 94 | sim_close (SIM_DESC sd, int quitting) |
| 95 | { |
| 96 | check_desc (sd); |
| 97 | |
| 98 | /* Not much to do. At least free up our memory. */ |
| 99 | init_mem (); |
| 100 | |
| 101 | rx_sim_is_open = 0; |
| 102 | } |
| 103 | |
| 104 | static bfd * |
| 105 | open_objfile (const char *filename) |
| 106 | { |
| 107 | bfd *prog = bfd_openr (filename, 0); |
| 108 | |
| 109 | if (!prog) |
| 110 | { |
| 111 | fprintf (stderr, "Can't read %s\n", filename); |
| 112 | return 0; |
| 113 | } |
| 114 | |
| 115 | if (!bfd_check_format (prog, bfd_object)) |
| 116 | { |
| 117 | fprintf (stderr, "%s not a rx program\n", filename); |
| 118 | return 0; |
| 119 | } |
| 120 | |
| 121 | return prog; |
| 122 | } |
| 123 | |
| 124 | static struct swap_list |
| 125 | { |
| 126 | bfd_vma start, end; |
| 127 | struct swap_list *next; |
| 128 | } *swap_list = NULL; |
| 129 | |
| 130 | static void |
| 131 | free_swap_list (void) |
| 132 | { |
| 133 | while (swap_list) |
| 134 | { |
| 135 | struct swap_list *next = swap_list->next; |
| 136 | free (swap_list); |
| 137 | swap_list = next; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | /* When running in big endian mode, we must do an additional |
| 142 | byte swap of memory areas used to hold instructions. See |
| 143 | the comment preceding rx_load in load.c to see why this is |
| 144 | so. |
| 145 | |
| 146 | Construct a list of memory areas that must be byte swapped. |
| 147 | This list will be consulted when either reading or writing |
| 148 | memory. */ |
| 149 | |
| 150 | static void |
| 151 | build_swap_list (struct bfd *abfd) |
| 152 | { |
| 153 | asection *s; |
| 154 | free_swap_list (); |
| 155 | |
| 156 | /* Nothing to do when in little endian mode. */ |
| 157 | if (!rx_big_endian) |
| 158 | return; |
| 159 | |
| 160 | for (s = abfd->sections; s; s = s->next) |
| 161 | { |
| 162 | if ((s->flags & SEC_LOAD) && (s->flags & SEC_CODE)) |
| 163 | { |
| 164 | struct swap_list *sl; |
| 165 | bfd_size_type size; |
| 166 | |
| 167 | size = bfd_section_size (s); |
| 168 | if (size <= 0) |
| 169 | continue; |
| 170 | |
| 171 | sl = malloc (sizeof (struct swap_list)); |
| 172 | assert (sl != NULL); |
| 173 | sl->next = swap_list; |
| 174 | sl->start = bfd_section_lma (s); |
| 175 | sl->end = sl->start + size; |
| 176 | swap_list = sl; |
| 177 | } |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | static int |
| 182 | addr_in_swap_list (bfd_vma addr) |
| 183 | { |
| 184 | struct swap_list *s; |
| 185 | |
| 186 | for (s = swap_list; s; s = s->next) |
| 187 | { |
| 188 | if (s->start <= addr && addr < s->end) |
| 189 | return 1; |
| 190 | } |
| 191 | return 0; |
| 192 | } |
| 193 | |
| 194 | SIM_RC |
| 195 | sim_load (SIM_DESC sd, const char *prog, struct bfd *abfd, int from_tty) |
| 196 | { |
| 197 | check_desc (sd); |
| 198 | |
| 199 | if (!abfd) |
| 200 | abfd = open_objfile (prog); |
| 201 | if (!abfd) |
| 202 | return SIM_RC_FAIL; |
| 203 | |
| 204 | rx_load (abfd, get_callbacks ()); |
| 205 | build_swap_list (abfd); |
| 206 | |
| 207 | return SIM_RC_OK; |
| 208 | } |
| 209 | |
| 210 | SIM_RC |
| 211 | sim_create_inferior (SIM_DESC sd, struct bfd *abfd, |
| 212 | char * const *argv, char * const *env) |
| 213 | { |
| 214 | check_desc (sd); |
| 215 | |
| 216 | if (abfd) |
| 217 | { |
| 218 | rx_load (abfd, NULL); |
| 219 | build_swap_list (abfd); |
| 220 | } |
| 221 | |
| 222 | return SIM_RC_OK; |
| 223 | } |
| 224 | |
| 225 | int |
| 226 | sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) |
| 227 | { |
| 228 | int i; |
| 229 | |
| 230 | check_desc (sd); |
| 231 | |
| 232 | if (mem == 0) |
| 233 | return 0; |
| 234 | |
| 235 | execution_error_clear_last_error (); |
| 236 | |
| 237 | for (i = 0; i < length; i++) |
| 238 | { |
| 239 | bfd_vma addr = mem + i; |
| 240 | int do_swap = addr_in_swap_list (addr); |
| 241 | buf[i] = mem_get_qi (addr ^ (do_swap ? 3 : 0)); |
| 242 | |
| 243 | if (execution_error_get_last_error () != SIM_ERR_NONE) |
| 244 | return i; |
| 245 | } |
| 246 | |
| 247 | return length; |
| 248 | } |
| 249 | |
| 250 | int |
| 251 | sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length) |
| 252 | { |
| 253 | int i; |
| 254 | |
| 255 | check_desc (sd); |
| 256 | |
| 257 | execution_error_clear_last_error (); |
| 258 | |
| 259 | for (i = 0; i < length; i++) |
| 260 | { |
| 261 | bfd_vma addr = mem + i; |
| 262 | int do_swap = addr_in_swap_list (addr); |
| 263 | mem_put_qi (addr ^ (do_swap ? 3 : 0), buf[i]); |
| 264 | |
| 265 | if (execution_error_get_last_error () != SIM_ERR_NONE) |
| 266 | return i; |
| 267 | } |
| 268 | |
| 269 | return length; |
| 270 | } |
| 271 | |
| 272 | /* Read the LENGTH bytes at BUF as an little-endian value. */ |
| 273 | static DI |
| 274 | get_le (unsigned char *buf, int length) |
| 275 | { |
| 276 | DI acc = 0; |
| 277 | while (--length >= 0) |
| 278 | acc = (acc << 8) + buf[length]; |
| 279 | |
| 280 | return acc; |
| 281 | } |
| 282 | |
| 283 | /* Read the LENGTH bytes at BUF as a big-endian value. */ |
| 284 | static DI |
| 285 | get_be (unsigned char *buf, int length) |
| 286 | { |
| 287 | DI acc = 0; |
| 288 | while (length-- > 0) |
| 289 | acc = (acc << 8) + *buf++; |
| 290 | |
| 291 | return acc; |
| 292 | } |
| 293 | |
| 294 | /* Store VAL as a little-endian value in the LENGTH bytes at BUF. */ |
| 295 | static void |
| 296 | put_le (unsigned char *buf, int length, DI val) |
| 297 | { |
| 298 | int i; |
| 299 | |
| 300 | for (i = 0; i < length; i++) |
| 301 | { |
| 302 | buf[i] = val & 0xff; |
| 303 | val >>= 8; |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | /* Store VAL as a big-endian value in the LENGTH bytes at BUF. */ |
| 308 | static void |
| 309 | put_be (unsigned char *buf, int length, DI val) |
| 310 | { |
| 311 | int i; |
| 312 | |
| 313 | for (i = length-1; i >= 0; i--) |
| 314 | { |
| 315 | buf[i] = val & 0xff; |
| 316 | val >>= 8; |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | |
| 321 | static int |
| 322 | check_regno (enum sim_rx_regnum regno) |
| 323 | { |
| 324 | return 0 <= regno && regno < sim_rx_num_regs; |
| 325 | } |
| 326 | |
| 327 | static size_t |
| 328 | reg_size (enum sim_rx_regnum regno) |
| 329 | { |
| 330 | size_t size; |
| 331 | |
| 332 | switch (regno) |
| 333 | { |
| 334 | case sim_rx_r0_regnum: |
| 335 | size = sizeof (regs.r[0]); |
| 336 | break; |
| 337 | case sim_rx_r1_regnum: |
| 338 | size = sizeof (regs.r[1]); |
| 339 | break; |
| 340 | case sim_rx_r2_regnum: |
| 341 | size = sizeof (regs.r[2]); |
| 342 | break; |
| 343 | case sim_rx_r3_regnum: |
| 344 | size = sizeof (regs.r[3]); |
| 345 | break; |
| 346 | case sim_rx_r4_regnum: |
| 347 | size = sizeof (regs.r[4]); |
| 348 | break; |
| 349 | case sim_rx_r5_regnum: |
| 350 | size = sizeof (regs.r[5]); |
| 351 | break; |
| 352 | case sim_rx_r6_regnum: |
| 353 | size = sizeof (regs.r[6]); |
| 354 | break; |
| 355 | case sim_rx_r7_regnum: |
| 356 | size = sizeof (regs.r[7]); |
| 357 | break; |
| 358 | case sim_rx_r8_regnum: |
| 359 | size = sizeof (regs.r[8]); |
| 360 | break; |
| 361 | case sim_rx_r9_regnum: |
| 362 | size = sizeof (regs.r[9]); |
| 363 | break; |
| 364 | case sim_rx_r10_regnum: |
| 365 | size = sizeof (regs.r[10]); |
| 366 | break; |
| 367 | case sim_rx_r11_regnum: |
| 368 | size = sizeof (regs.r[11]); |
| 369 | break; |
| 370 | case sim_rx_r12_regnum: |
| 371 | size = sizeof (regs.r[12]); |
| 372 | break; |
| 373 | case sim_rx_r13_regnum: |
| 374 | size = sizeof (regs.r[13]); |
| 375 | break; |
| 376 | case sim_rx_r14_regnum: |
| 377 | size = sizeof (regs.r[14]); |
| 378 | break; |
| 379 | case sim_rx_r15_regnum: |
| 380 | size = sizeof (regs.r[15]); |
| 381 | break; |
| 382 | case sim_rx_isp_regnum: |
| 383 | size = sizeof (regs.r_isp); |
| 384 | break; |
| 385 | case sim_rx_usp_regnum: |
| 386 | size = sizeof (regs.r_usp); |
| 387 | break; |
| 388 | case sim_rx_intb_regnum: |
| 389 | size = sizeof (regs.r_intb); |
| 390 | break; |
| 391 | case sim_rx_pc_regnum: |
| 392 | size = sizeof (regs.r_pc); |
| 393 | break; |
| 394 | case sim_rx_ps_regnum: |
| 395 | size = sizeof (regs.r_psw); |
| 396 | break; |
| 397 | case sim_rx_bpc_regnum: |
| 398 | size = sizeof (regs.r_bpc); |
| 399 | break; |
| 400 | case sim_rx_bpsw_regnum: |
| 401 | size = sizeof (regs.r_bpsw); |
| 402 | break; |
| 403 | case sim_rx_fintv_regnum: |
| 404 | size = sizeof (regs.r_fintv); |
| 405 | break; |
| 406 | case sim_rx_fpsw_regnum: |
| 407 | size = sizeof (regs.r_fpsw); |
| 408 | break; |
| 409 | case sim_rx_acc_regnum: |
| 410 | size = sizeof (regs.r_acc); |
| 411 | break; |
| 412 | default: |
| 413 | size = 0; |
| 414 | break; |
| 415 | } |
| 416 | return size; |
| 417 | } |
| 418 | |
| 419 | int |
| 420 | sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) |
| 421 | { |
| 422 | size_t size; |
| 423 | DI val; |
| 424 | |
| 425 | check_desc (sd); |
| 426 | |
| 427 | if (!check_regno (regno)) |
| 428 | return 0; |
| 429 | |
| 430 | size = reg_size (regno); |
| 431 | |
| 432 | if (length != size) |
| 433 | return 0; |
| 434 | |
| 435 | switch (regno) |
| 436 | { |
| 437 | case sim_rx_r0_regnum: |
| 438 | val = get_reg (0); |
| 439 | break; |
| 440 | case sim_rx_r1_regnum: |
| 441 | val = get_reg (1); |
| 442 | break; |
| 443 | case sim_rx_r2_regnum: |
| 444 | val = get_reg (2); |
| 445 | break; |
| 446 | case sim_rx_r3_regnum: |
| 447 | val = get_reg (3); |
| 448 | break; |
| 449 | case sim_rx_r4_regnum: |
| 450 | val = get_reg (4); |
| 451 | break; |
| 452 | case sim_rx_r5_regnum: |
| 453 | val = get_reg (5); |
| 454 | break; |
| 455 | case sim_rx_r6_regnum: |
| 456 | val = get_reg (6); |
| 457 | break; |
| 458 | case sim_rx_r7_regnum: |
| 459 | val = get_reg (7); |
| 460 | break; |
| 461 | case sim_rx_r8_regnum: |
| 462 | val = get_reg (8); |
| 463 | break; |
| 464 | case sim_rx_r9_regnum: |
| 465 | val = get_reg (9); |
| 466 | break; |
| 467 | case sim_rx_r10_regnum: |
| 468 | val = get_reg (10); |
| 469 | break; |
| 470 | case sim_rx_r11_regnum: |
| 471 | val = get_reg (11); |
| 472 | break; |
| 473 | case sim_rx_r12_regnum: |
| 474 | val = get_reg (12); |
| 475 | break; |
| 476 | case sim_rx_r13_regnum: |
| 477 | val = get_reg (13); |
| 478 | break; |
| 479 | case sim_rx_r14_regnum: |
| 480 | val = get_reg (14); |
| 481 | break; |
| 482 | case sim_rx_r15_regnum: |
| 483 | val = get_reg (15); |
| 484 | break; |
| 485 | case sim_rx_isp_regnum: |
| 486 | val = get_reg (isp); |
| 487 | break; |
| 488 | case sim_rx_usp_regnum: |
| 489 | val = get_reg (usp); |
| 490 | break; |
| 491 | case sim_rx_intb_regnum: |
| 492 | val = get_reg (intb); |
| 493 | break; |
| 494 | case sim_rx_pc_regnum: |
| 495 | val = get_reg (pc); |
| 496 | break; |
| 497 | case sim_rx_ps_regnum: |
| 498 | val = get_reg (psw); |
| 499 | break; |
| 500 | case sim_rx_bpc_regnum: |
| 501 | val = get_reg (bpc); |
| 502 | break; |
| 503 | case sim_rx_bpsw_regnum: |
| 504 | val = get_reg (bpsw); |
| 505 | break; |
| 506 | case sim_rx_fintv_regnum: |
| 507 | val = get_reg (fintv); |
| 508 | break; |
| 509 | case sim_rx_fpsw_regnum: |
| 510 | val = get_reg (fpsw); |
| 511 | break; |
| 512 | case sim_rx_acc_regnum: |
| 513 | val = ((DI) get_reg (acchi) << 32) | get_reg (acclo); |
| 514 | break; |
| 515 | default: |
| 516 | fprintf (stderr, "rx minisim: unrecognized register number: %d\n", |
| 517 | regno); |
| 518 | return -1; |
| 519 | } |
| 520 | |
| 521 | if (rx_big_endian) |
| 522 | put_be (buf, length, val); |
| 523 | else |
| 524 | put_le (buf, length, val); |
| 525 | |
| 526 | return size; |
| 527 | } |
| 528 | |
| 529 | int |
| 530 | sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length) |
| 531 | { |
| 532 | size_t size; |
| 533 | DI val; |
| 534 | |
| 535 | check_desc (sd); |
| 536 | |
| 537 | if (!check_regno (regno)) |
| 538 | return -1; |
| 539 | |
| 540 | size = reg_size (regno); |
| 541 | |
| 542 | if (length != size) |
| 543 | return -1; |
| 544 | |
| 545 | if (rx_big_endian) |
| 546 | val = get_be (buf, length); |
| 547 | else |
| 548 | val = get_le (buf, length); |
| 549 | |
| 550 | switch (regno) |
| 551 | { |
| 552 | case sim_rx_r0_regnum: |
| 553 | put_reg (0, val); |
| 554 | break; |
| 555 | case sim_rx_r1_regnum: |
| 556 | put_reg (1, val); |
| 557 | break; |
| 558 | case sim_rx_r2_regnum: |
| 559 | put_reg (2, val); |
| 560 | break; |
| 561 | case sim_rx_r3_regnum: |
| 562 | put_reg (3, val); |
| 563 | break; |
| 564 | case sim_rx_r4_regnum: |
| 565 | put_reg (4, val); |
| 566 | break; |
| 567 | case sim_rx_r5_regnum: |
| 568 | put_reg (5, val); |
| 569 | break; |
| 570 | case sim_rx_r6_regnum: |
| 571 | put_reg (6, val); |
| 572 | break; |
| 573 | case sim_rx_r7_regnum: |
| 574 | put_reg (7, val); |
| 575 | break; |
| 576 | case sim_rx_r8_regnum: |
| 577 | put_reg (8, val); |
| 578 | break; |
| 579 | case sim_rx_r9_regnum: |
| 580 | put_reg (9, val); |
| 581 | break; |
| 582 | case sim_rx_r10_regnum: |
| 583 | put_reg (10, val); |
| 584 | break; |
| 585 | case sim_rx_r11_regnum: |
| 586 | put_reg (11, val); |
| 587 | break; |
| 588 | case sim_rx_r12_regnum: |
| 589 | put_reg (12, val); |
| 590 | break; |
| 591 | case sim_rx_r13_regnum: |
| 592 | put_reg (13, val); |
| 593 | break; |
| 594 | case sim_rx_r14_regnum: |
| 595 | put_reg (14, val); |
| 596 | break; |
| 597 | case sim_rx_r15_regnum: |
| 598 | put_reg (15, val); |
| 599 | break; |
| 600 | case sim_rx_isp_regnum: |
| 601 | put_reg (isp, val); |
| 602 | break; |
| 603 | case sim_rx_usp_regnum: |
| 604 | put_reg (usp, val); |
| 605 | break; |
| 606 | case sim_rx_intb_regnum: |
| 607 | put_reg (intb, val); |
| 608 | break; |
| 609 | case sim_rx_pc_regnum: |
| 610 | put_reg (pc, val); |
| 611 | break; |
| 612 | case sim_rx_ps_regnum: |
| 613 | put_reg (psw, val); |
| 614 | break; |
| 615 | case sim_rx_bpc_regnum: |
| 616 | put_reg (bpc, val); |
| 617 | break; |
| 618 | case sim_rx_bpsw_regnum: |
| 619 | put_reg (bpsw, val); |
| 620 | break; |
| 621 | case sim_rx_fintv_regnum: |
| 622 | put_reg (fintv, val); |
| 623 | break; |
| 624 | case sim_rx_fpsw_regnum: |
| 625 | put_reg (fpsw, val); |
| 626 | break; |
| 627 | case sim_rx_acc_regnum: |
| 628 | put_reg (acclo, val & 0xffffffff); |
| 629 | put_reg (acchi, (val >> 32) & 0xffffffff); |
| 630 | break; |
| 631 | default: |
| 632 | fprintf (stderr, "rx minisim: unrecognized register number: %d\n", |
| 633 | regno); |
| 634 | return 0; |
| 635 | } |
| 636 | |
| 637 | return size; |
| 638 | } |
| 639 | |
| 640 | void |
| 641 | sim_info (SIM_DESC sd, int verbose) |
| 642 | { |
| 643 | check_desc (sd); |
| 644 | |
| 645 | printf ("The rx minisim doesn't collect any statistics.\n"); |
| 646 | } |
| 647 | |
| 648 | static volatile int stop; |
| 649 | static enum sim_stop reason; |
| 650 | int siggnal; |
| 651 | |
| 652 | |
| 653 | /* Given a signal number used by the RX bsp (that is, newlib), |
| 654 | return a target signal number used by GDB. */ |
| 655 | static int |
| 656 | rx_signal_to_gdb_signal (int rx) |
| 657 | { |
| 658 | switch (rx) |
| 659 | { |
| 660 | case 4: |
| 661 | return GDB_SIGNAL_ILL; |
| 662 | |
| 663 | case 5: |
| 664 | return GDB_SIGNAL_TRAP; |
| 665 | |
| 666 | case 10: |
| 667 | return GDB_SIGNAL_BUS; |
| 668 | |
| 669 | case 11: |
| 670 | return GDB_SIGNAL_SEGV; |
| 671 | |
| 672 | case 24: |
| 673 | return GDB_SIGNAL_XCPU; |
| 674 | |
| 675 | case 2: |
| 676 | return GDB_SIGNAL_INT; |
| 677 | |
| 678 | case 8: |
| 679 | return GDB_SIGNAL_FPE; |
| 680 | |
| 681 | case 6: |
| 682 | return GDB_SIGNAL_ABRT; |
| 683 | } |
| 684 | |
| 685 | return 0; |
| 686 | } |
| 687 | |
| 688 | |
| 689 | /* Take a step return code RC and set up the variables consulted by |
| 690 | sim_stop_reason appropriately. */ |
| 691 | void |
| 692 | handle_step (int rc) |
| 693 | { |
| 694 | if (execution_error_get_last_error () != SIM_ERR_NONE) |
| 695 | { |
| 696 | reason = sim_stopped; |
| 697 | siggnal = GDB_SIGNAL_SEGV; |
| 698 | } |
| 699 | if (RX_STEPPED (rc) || RX_HIT_BREAK (rc)) |
| 700 | { |
| 701 | reason = sim_stopped; |
| 702 | siggnal = GDB_SIGNAL_TRAP; |
| 703 | } |
| 704 | else if (RX_STOPPED (rc)) |
| 705 | { |
| 706 | reason = sim_stopped; |
| 707 | siggnal = rx_signal_to_gdb_signal (RX_STOP_SIG (rc)); |
| 708 | } |
| 709 | else |
| 710 | { |
| 711 | assert (RX_EXITED (rc)); |
| 712 | reason = sim_exited; |
| 713 | siggnal = RX_EXIT_STATUS (rc); |
| 714 | } |
| 715 | } |
| 716 | |
| 717 | |
| 718 | void |
| 719 | sim_resume (SIM_DESC sd, int step, int sig_to_deliver) |
| 720 | { |
| 721 | int rc; |
| 722 | |
| 723 | check_desc (sd); |
| 724 | |
| 725 | if (sig_to_deliver != 0) |
| 726 | { |
| 727 | fprintf (stderr, |
| 728 | "Warning: the rx minisim does not implement " |
| 729 | "signal delivery yet.\n" "Resuming with no signal.\n"); |
| 730 | } |
| 731 | |
| 732 | execution_error_clear_last_error (); |
| 733 | |
| 734 | if (step) |
| 735 | { |
| 736 | rc = setjmp (decode_jmp_buf); |
| 737 | if (rc == 0) |
| 738 | rc = decode_opcode (); |
| 739 | handle_step (rc); |
| 740 | } |
| 741 | else |
| 742 | { |
| 743 | /* We don't clear 'stop' here, because then we would miss |
| 744 | interrupts that arrived on the way here. Instead, we clear |
| 745 | the flag in sim_stop_reason, after GDB has disabled the |
| 746 | interrupt signal handler. */ |
| 747 | for (;;) |
| 748 | { |
| 749 | if (stop) |
| 750 | { |
| 751 | stop = 0; |
| 752 | reason = sim_stopped; |
| 753 | siggnal = GDB_SIGNAL_INT; |
| 754 | break; |
| 755 | } |
| 756 | |
| 757 | rc = setjmp (decode_jmp_buf); |
| 758 | if (rc == 0) |
| 759 | rc = decode_opcode (); |
| 760 | |
| 761 | if (execution_error_get_last_error () != SIM_ERR_NONE) |
| 762 | { |
| 763 | reason = sim_stopped; |
| 764 | siggnal = GDB_SIGNAL_SEGV; |
| 765 | break; |
| 766 | } |
| 767 | |
| 768 | if (!RX_STEPPED (rc)) |
| 769 | { |
| 770 | handle_step (rc); |
| 771 | break; |
| 772 | } |
| 773 | } |
| 774 | } |
| 775 | } |
| 776 | |
| 777 | int |
| 778 | sim_stop (SIM_DESC sd) |
| 779 | { |
| 780 | stop = 1; |
| 781 | |
| 782 | return 1; |
| 783 | } |
| 784 | |
| 785 | void |
| 786 | sim_stop_reason (SIM_DESC sd, enum sim_stop *reason_p, int *sigrc_p) |
| 787 | { |
| 788 | check_desc (sd); |
| 789 | |
| 790 | *reason_p = reason; |
| 791 | *sigrc_p = siggnal; |
| 792 | } |
| 793 | |
| 794 | void |
| 795 | sim_do_command (SIM_DESC sd, const char *cmd) |
| 796 | { |
| 797 | const char *args; |
| 798 | char *p = strdup (cmd); |
| 799 | |
| 800 | check_desc (sd); |
| 801 | |
| 802 | /* Skip leading whitespace. */ |
| 803 | while (isspace (*p)) |
| 804 | p++; |
| 805 | |
| 806 | /* Find the extent of the command word. */ |
| 807 | for (p = cmd; *p; p++) |
| 808 | if (isspace (*p)) |
| 809 | break; |
| 810 | |
| 811 | /* Null-terminate the command word, and record the start of any |
| 812 | further arguments. */ |
| 813 | if (*p) |
| 814 | { |
| 815 | *p = '\0'; |
| 816 | args = p + 1; |
| 817 | while (isspace (*args)) |
| 818 | args++; |
| 819 | } |
| 820 | else |
| 821 | args = p; |
| 822 | |
| 823 | if (strcmp (cmd, "trace") == 0) |
| 824 | { |
| 825 | if (strcmp (args, "on") == 0) |
| 826 | trace = 1; |
| 827 | else if (strcmp (args, "off") == 0) |
| 828 | trace = 0; |
| 829 | else |
| 830 | printf ("The 'sim trace' command expects 'on' or 'off' " |
| 831 | "as an argument.\n"); |
| 832 | } |
| 833 | else if (strcmp (cmd, "verbose") == 0) |
| 834 | { |
| 835 | if (strcmp (args, "on") == 0) |
| 836 | verbose = 1; |
| 837 | else if (strcmp (args, "noisy") == 0) |
| 838 | verbose = 2; |
| 839 | else if (strcmp (args, "off") == 0) |
| 840 | verbose = 0; |
| 841 | else |
| 842 | printf ("The 'sim verbose' command expects 'on', 'noisy', or 'off'" |
| 843 | " as an argument.\n"); |
| 844 | } |
| 845 | else |
| 846 | printf ("The 'sim' command expects either 'trace' or 'verbose'" |
| 847 | " as a subcommand.\n"); |
| 848 | |
| 849 | free (p); |
| 850 | } |
| 851 | |
| 852 | char ** |
| 853 | sim_complete_command (SIM_DESC sd, const char *text, const char *word) |
| 854 | { |
| 855 | return NULL; |
| 856 | } |