14e98e3e1Schristos /* gdb-if.c -- sim interface to GDB. 24e98e3e1Schristos 3*1f4e7eb9Schristos Copyright (C) 2008-2024 Free Software Foundation, Inc. 44e98e3e1Schristos Contributed by Red Hat, Inc. 54e98e3e1Schristos 64e98e3e1Schristos This file is part of the GNU simulators. 74e98e3e1Schristos 84e98e3e1Schristos This program is free software; you can redistribute it and/or modify 94e98e3e1Schristos it under the terms of the GNU General Public License as published by 104e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 114e98e3e1Schristos (at your option) any later version. 124e98e3e1Schristos 134e98e3e1Schristos This program is distributed in the hope that it will be useful, 144e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 154e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 164e98e3e1Schristos GNU General Public License for more details. 174e98e3e1Schristos 184e98e3e1Schristos You should have received a copy of the GNU General Public License 194e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 204e98e3e1Schristos 214b169a6bSchristos /* This must come before any other includes. */ 224b169a6bSchristos #include "defs.h" 234b169a6bSchristos 244e98e3e1Schristos #include <stdio.h> 254e98e3e1Schristos #include <assert.h> 264e98e3e1Schristos #include <signal.h> 274e98e3e1Schristos #include <string.h> 284e98e3e1Schristos #include <ctype.h> 294e98e3e1Schristos #include <stdlib.h> 304e98e3e1Schristos 314e98e3e1Schristos #include "ansidecl.h" 32*1f4e7eb9Schristos #include "bfd.h" 334b169a6bSchristos #include "libiberty.h" 344b169a6bSchristos #include "sim/callback.h" 354b169a6bSchristos #include "sim/sim.h" 364e98e3e1Schristos #include "gdb/signals.h" 37*1f4e7eb9Schristos #include "sim/sim-rx.h" 384e98e3e1Schristos 394e98e3e1Schristos #include "cpu.h" 404e98e3e1Schristos #include "mem.h" 414e98e3e1Schristos #include "load.h" 424e98e3e1Schristos #include "syscalls.h" 434e98e3e1Schristos #include "err.h" 444e98e3e1Schristos #include "trace.h" 454e98e3e1Schristos 464e98e3e1Schristos /* Ideally, we'd wrap up all the minisim's data structures in an 474e98e3e1Schristos object and pass that around. However, neither GDB nor run needs 484e98e3e1Schristos that ability. 494e98e3e1Schristos 504e98e3e1Schristos So we just have one instance, that lives in global variables, and 514e98e3e1Schristos each time we open it, we re-initialize it. */ 524e98e3e1Schristos struct sim_state 534e98e3e1Schristos { 544e98e3e1Schristos const char *message; 554e98e3e1Schristos }; 564e98e3e1Schristos 574e98e3e1Schristos static struct sim_state the_minisim = { 584e98e3e1Schristos "This is the sole rx minisim instance. See libsim.a's global variables." 594e98e3e1Schristos }; 604e98e3e1Schristos 61837edd6bSchristos static int rx_sim_is_open; 624e98e3e1Schristos 634e98e3e1Schristos SIM_DESC 644e98e3e1Schristos sim_open (SIM_OPEN_KIND kind, 654e98e3e1Schristos struct host_callback_struct *callback, 66ba340e45Schristos struct bfd *abfd, char * const *argv) 674e98e3e1Schristos { 68837edd6bSchristos if (rx_sim_is_open) 694e98e3e1Schristos fprintf (stderr, "rx minisim: re-opened sim\n"); 704e98e3e1Schristos 714e98e3e1Schristos /* The 'run' interface doesn't use this function, so we don't care 724e98e3e1Schristos about KIND; it's always SIM_OPEN_DEBUG. */ 734e98e3e1Schristos if (kind != SIM_OPEN_DEBUG) 744e98e3e1Schristos fprintf (stderr, "rx minisim: sim_open KIND != SIM_OPEN_DEBUG: %d\n", 754e98e3e1Schristos kind); 764e98e3e1Schristos 774e98e3e1Schristos set_callbacks (callback); 784e98e3e1Schristos 794e98e3e1Schristos /* We don't expect any command-line arguments. */ 804e98e3e1Schristos 814e98e3e1Schristos init_mem (); 824e98e3e1Schristos init_regs (); 834e98e3e1Schristos execution_error_init_debugger (); 844e98e3e1Schristos 854e98e3e1Schristos sim_disasm_init (abfd); 86837edd6bSchristos rx_sim_is_open = 1; 874e98e3e1Schristos return &the_minisim; 884e98e3e1Schristos } 894e98e3e1Schristos 904e98e3e1Schristos static void 914e98e3e1Schristos check_desc (SIM_DESC sd) 924e98e3e1Schristos { 934e98e3e1Schristos if (sd != &the_minisim) 944e98e3e1Schristos fprintf (stderr, "rx minisim: desc != &the_minisim\n"); 954e98e3e1Schristos } 964e98e3e1Schristos 974e98e3e1Schristos void 984e98e3e1Schristos sim_close (SIM_DESC sd, int quitting) 994e98e3e1Schristos { 1004e98e3e1Schristos check_desc (sd); 1014e98e3e1Schristos 1024e98e3e1Schristos /* Not much to do. At least free up our memory. */ 1034e98e3e1Schristos init_mem (); 1044e98e3e1Schristos 105837edd6bSchristos rx_sim_is_open = 0; 1064e98e3e1Schristos } 1074e98e3e1Schristos 1084e98e3e1Schristos static bfd * 1094e98e3e1Schristos open_objfile (const char *filename) 1104e98e3e1Schristos { 1114e98e3e1Schristos bfd *prog = bfd_openr (filename, 0); 1124e98e3e1Schristos 1134e98e3e1Schristos if (!prog) 1144e98e3e1Schristos { 1154e98e3e1Schristos fprintf (stderr, "Can't read %s\n", filename); 1164e98e3e1Schristos return 0; 1174e98e3e1Schristos } 1184e98e3e1Schristos 1194e98e3e1Schristos if (!bfd_check_format (prog, bfd_object)) 1204e98e3e1Schristos { 1214e98e3e1Schristos fprintf (stderr, "%s not a rx program\n", filename); 1224e98e3e1Schristos return 0; 1234e98e3e1Schristos } 1244e98e3e1Schristos 1254e98e3e1Schristos return prog; 1264e98e3e1Schristos } 1274e98e3e1Schristos 1284e98e3e1Schristos static struct swap_list 1294e98e3e1Schristos { 1304e98e3e1Schristos bfd_vma start, end; 1314e98e3e1Schristos struct swap_list *next; 1324e98e3e1Schristos } *swap_list = NULL; 1334e98e3e1Schristos 1344e98e3e1Schristos static void 1354e98e3e1Schristos free_swap_list (void) 1364e98e3e1Schristos { 1374e98e3e1Schristos while (swap_list) 1384e98e3e1Schristos { 1394e98e3e1Schristos struct swap_list *next = swap_list->next; 1404e98e3e1Schristos free (swap_list); 1414e98e3e1Schristos swap_list = next; 1424e98e3e1Schristos } 1434e98e3e1Schristos } 1444e98e3e1Schristos 1454e98e3e1Schristos /* When running in big endian mode, we must do an additional 1464e98e3e1Schristos byte swap of memory areas used to hold instructions. See 1474e98e3e1Schristos the comment preceding rx_load in load.c to see why this is 1484e98e3e1Schristos so. 1494e98e3e1Schristos 1504e98e3e1Schristos Construct a list of memory areas that must be byte swapped. 1514e98e3e1Schristos This list will be consulted when either reading or writing 1524e98e3e1Schristos memory. */ 1534e98e3e1Schristos 1544e98e3e1Schristos static void 1554e98e3e1Schristos build_swap_list (struct bfd *abfd) 1564e98e3e1Schristos { 1574e98e3e1Schristos asection *s; 1584e98e3e1Schristos free_swap_list (); 1594e98e3e1Schristos 1604e98e3e1Schristos /* Nothing to do when in little endian mode. */ 1614e98e3e1Schristos if (!rx_big_endian) 1624e98e3e1Schristos return; 1634e98e3e1Schristos 1644e98e3e1Schristos for (s = abfd->sections; s; s = s->next) 1654e98e3e1Schristos { 1664e98e3e1Schristos if ((s->flags & SEC_LOAD) && (s->flags & SEC_CODE)) 1674e98e3e1Schristos { 1684e98e3e1Schristos struct swap_list *sl; 1694e98e3e1Schristos bfd_size_type size; 1704e98e3e1Schristos 1718dffb485Schristos size = bfd_section_size (s); 1724e98e3e1Schristos if (size <= 0) 1734e98e3e1Schristos continue; 1744e98e3e1Schristos 1754e98e3e1Schristos sl = malloc (sizeof (struct swap_list)); 1764e98e3e1Schristos assert (sl != NULL); 1774e98e3e1Schristos sl->next = swap_list; 1788dffb485Schristos sl->start = bfd_section_lma (s); 1794e98e3e1Schristos sl->end = sl->start + size; 1804e98e3e1Schristos swap_list = sl; 1814e98e3e1Schristos } 1824e98e3e1Schristos } 1834e98e3e1Schristos } 1844e98e3e1Schristos 1854e98e3e1Schristos static int 1864e98e3e1Schristos addr_in_swap_list (bfd_vma addr) 1874e98e3e1Schristos { 1884e98e3e1Schristos struct swap_list *s; 1894e98e3e1Schristos 1904e98e3e1Schristos for (s = swap_list; s; s = s->next) 1914e98e3e1Schristos { 1924e98e3e1Schristos if (s->start <= addr && addr < s->end) 1934e98e3e1Schristos return 1; 1944e98e3e1Schristos } 1954e98e3e1Schristos return 0; 1964e98e3e1Schristos } 1974e98e3e1Schristos 1984e98e3e1Schristos SIM_RC 199837edd6bSchristos sim_load (SIM_DESC sd, const char *prog, struct bfd *abfd, int from_tty) 2004e98e3e1Schristos { 2014e98e3e1Schristos check_desc (sd); 2024e98e3e1Schristos 2034e98e3e1Schristos if (!abfd) 2044e98e3e1Schristos abfd = open_objfile (prog); 2054e98e3e1Schristos if (!abfd) 2064e98e3e1Schristos return SIM_RC_FAIL; 2074e98e3e1Schristos 208a2e2270fSchristos rx_load (abfd, get_callbacks ()); 2094e98e3e1Schristos build_swap_list (abfd); 2104e98e3e1Schristos 2114e98e3e1Schristos return SIM_RC_OK; 2124e98e3e1Schristos } 2134e98e3e1Schristos 2144e98e3e1Schristos SIM_RC 215ba340e45Schristos sim_create_inferior (SIM_DESC sd, struct bfd *abfd, 216ba340e45Schristos char * const *argv, char * const *env) 2174e98e3e1Schristos { 2184e98e3e1Schristos check_desc (sd); 2194e98e3e1Schristos 2204e98e3e1Schristos if (abfd) 2214e98e3e1Schristos { 222a2e2270fSchristos rx_load (abfd, NULL); 2234e98e3e1Schristos build_swap_list (abfd); 2244e98e3e1Schristos } 2254e98e3e1Schristos 2264e98e3e1Schristos return SIM_RC_OK; 2274e98e3e1Schristos } 2284e98e3e1Schristos 229*1f4e7eb9Schristos uint64_t 230*1f4e7eb9Schristos sim_read (SIM_DESC sd, uint64_t addr, void *buffer, uint64_t length) 2314e98e3e1Schristos { 2324e98e3e1Schristos int i; 2334b169a6bSchristos unsigned char *data = buffer; 2344e98e3e1Schristos 2354e98e3e1Schristos check_desc (sd); 2364e98e3e1Schristos 237*1f4e7eb9Schristos if (addr == 0) 2384e98e3e1Schristos return 0; 2394e98e3e1Schristos 2404e98e3e1Schristos execution_error_clear_last_error (); 2414e98e3e1Schristos 2424e98e3e1Schristos for (i = 0; i < length; i++) 2434e98e3e1Schristos { 244*1f4e7eb9Schristos bfd_vma vma = addr + i; 245*1f4e7eb9Schristos int do_swap = addr_in_swap_list (vma); 246*1f4e7eb9Schristos data[i] = mem_get_qi (vma ^ (do_swap ? 3 : 0)); 2474e98e3e1Schristos 2484e98e3e1Schristos if (execution_error_get_last_error () != SIM_ERR_NONE) 2494e98e3e1Schristos return i; 2504e98e3e1Schristos } 2514e98e3e1Schristos 2524e98e3e1Schristos return length; 2534e98e3e1Schristos } 2544e98e3e1Schristos 255*1f4e7eb9Schristos uint64_t 256*1f4e7eb9Schristos sim_write (SIM_DESC sd, uint64_t addr, const void *buffer, uint64_t length) 2574e98e3e1Schristos { 2584e98e3e1Schristos int i; 2594b169a6bSchristos const unsigned char *data = buffer; 2604e98e3e1Schristos 2614e98e3e1Schristos check_desc (sd); 2624e98e3e1Schristos 2634e98e3e1Schristos execution_error_clear_last_error (); 2644e98e3e1Schristos 2654e98e3e1Schristos for (i = 0; i < length; i++) 2664e98e3e1Schristos { 267*1f4e7eb9Schristos bfd_vma vma = addr + i; 268*1f4e7eb9Schristos int do_swap = addr_in_swap_list (vma); 269*1f4e7eb9Schristos mem_put_qi (vma ^ (do_swap ? 3 : 0), data[i]); 2704e98e3e1Schristos 2714e98e3e1Schristos if (execution_error_get_last_error () != SIM_ERR_NONE) 2724e98e3e1Schristos return i; 2734e98e3e1Schristos } 2744e98e3e1Schristos 2754e98e3e1Schristos return length; 2764e98e3e1Schristos } 2774e98e3e1Schristos 2784e98e3e1Schristos /* Read the LENGTH bytes at BUF as an little-endian value. */ 2794e98e3e1Schristos static DI 2804b169a6bSchristos get_le (const unsigned char *buf, int length) 2814e98e3e1Schristos { 2824e98e3e1Schristos DI acc = 0; 2834e98e3e1Schristos while (--length >= 0) 2844e98e3e1Schristos acc = (acc << 8) + buf[length]; 2854e98e3e1Schristos 2864e98e3e1Schristos return acc; 2874e98e3e1Schristos } 2884e98e3e1Schristos 2894e98e3e1Schristos /* Read the LENGTH bytes at BUF as a big-endian value. */ 2904e98e3e1Schristos static DI 2914b169a6bSchristos get_be (const unsigned char *buf, int length) 2924e98e3e1Schristos { 2934e98e3e1Schristos DI acc = 0; 2944e98e3e1Schristos while (length-- > 0) 2954e98e3e1Schristos acc = (acc << 8) + *buf++; 2964e98e3e1Schristos 2974e98e3e1Schristos return acc; 2984e98e3e1Schristos } 2994e98e3e1Schristos 3004e98e3e1Schristos /* Store VAL as a little-endian value in the LENGTH bytes at BUF. */ 3014e98e3e1Schristos static void 3024e98e3e1Schristos put_le (unsigned char *buf, int length, DI val) 3034e98e3e1Schristos { 3044e98e3e1Schristos int i; 3054e98e3e1Schristos 3064e98e3e1Schristos for (i = 0; i < length; i++) 3074e98e3e1Schristos { 3084e98e3e1Schristos buf[i] = val & 0xff; 3094e98e3e1Schristos val >>= 8; 3104e98e3e1Schristos } 3114e98e3e1Schristos } 3124e98e3e1Schristos 3134e98e3e1Schristos /* Store VAL as a big-endian value in the LENGTH bytes at BUF. */ 3144e98e3e1Schristos static void 3154e98e3e1Schristos put_be (unsigned char *buf, int length, DI val) 3164e98e3e1Schristos { 3174e98e3e1Schristos int i; 3184e98e3e1Schristos 3194e98e3e1Schristos for (i = length-1; i >= 0; i--) 3204e98e3e1Schristos { 3214e98e3e1Schristos buf[i] = val & 0xff; 3224e98e3e1Schristos val >>= 8; 3234e98e3e1Schristos } 3244e98e3e1Schristos } 3254e98e3e1Schristos 3264e98e3e1Schristos 3274e98e3e1Schristos static int 3284e98e3e1Schristos check_regno (enum sim_rx_regnum regno) 3294e98e3e1Schristos { 3304e98e3e1Schristos return 0 <= regno && regno < sim_rx_num_regs; 3314e98e3e1Schristos } 3324e98e3e1Schristos 3334e98e3e1Schristos static size_t 3344e98e3e1Schristos reg_size (enum sim_rx_regnum regno) 3354e98e3e1Schristos { 3364e98e3e1Schristos size_t size; 3374e98e3e1Schristos 3384e98e3e1Schristos switch (regno) 3394e98e3e1Schristos { 3404e98e3e1Schristos case sim_rx_r0_regnum: 3414e98e3e1Schristos size = sizeof (regs.r[0]); 3424e98e3e1Schristos break; 3434e98e3e1Schristos case sim_rx_r1_regnum: 3444e98e3e1Schristos size = sizeof (regs.r[1]); 3454e98e3e1Schristos break; 3464e98e3e1Schristos case sim_rx_r2_regnum: 3474e98e3e1Schristos size = sizeof (regs.r[2]); 3484e98e3e1Schristos break; 3494e98e3e1Schristos case sim_rx_r3_regnum: 3504e98e3e1Schristos size = sizeof (regs.r[3]); 3514e98e3e1Schristos break; 3524e98e3e1Schristos case sim_rx_r4_regnum: 3534e98e3e1Schristos size = sizeof (regs.r[4]); 3544e98e3e1Schristos break; 3554e98e3e1Schristos case sim_rx_r5_regnum: 3564e98e3e1Schristos size = sizeof (regs.r[5]); 3574e98e3e1Schristos break; 3584e98e3e1Schristos case sim_rx_r6_regnum: 3594e98e3e1Schristos size = sizeof (regs.r[6]); 3604e98e3e1Schristos break; 3614e98e3e1Schristos case sim_rx_r7_regnum: 3624e98e3e1Schristos size = sizeof (regs.r[7]); 3634e98e3e1Schristos break; 3644e98e3e1Schristos case sim_rx_r8_regnum: 3654e98e3e1Schristos size = sizeof (regs.r[8]); 3664e98e3e1Schristos break; 3674e98e3e1Schristos case sim_rx_r9_regnum: 3684e98e3e1Schristos size = sizeof (regs.r[9]); 3694e98e3e1Schristos break; 3704e98e3e1Schristos case sim_rx_r10_regnum: 3714e98e3e1Schristos size = sizeof (regs.r[10]); 3724e98e3e1Schristos break; 3734e98e3e1Schristos case sim_rx_r11_regnum: 3744e98e3e1Schristos size = sizeof (regs.r[11]); 3754e98e3e1Schristos break; 3764e98e3e1Schristos case sim_rx_r12_regnum: 3774e98e3e1Schristos size = sizeof (regs.r[12]); 3784e98e3e1Schristos break; 3794e98e3e1Schristos case sim_rx_r13_regnum: 3804e98e3e1Schristos size = sizeof (regs.r[13]); 3814e98e3e1Schristos break; 3824e98e3e1Schristos case sim_rx_r14_regnum: 3834e98e3e1Schristos size = sizeof (regs.r[14]); 3844e98e3e1Schristos break; 3854e98e3e1Schristos case sim_rx_r15_regnum: 3864e98e3e1Schristos size = sizeof (regs.r[15]); 3874e98e3e1Schristos break; 3884e98e3e1Schristos case sim_rx_isp_regnum: 3894e98e3e1Schristos size = sizeof (regs.r_isp); 3904e98e3e1Schristos break; 3914e98e3e1Schristos case sim_rx_usp_regnum: 3924e98e3e1Schristos size = sizeof (regs.r_usp); 3934e98e3e1Schristos break; 3944e98e3e1Schristos case sim_rx_intb_regnum: 3954e98e3e1Schristos size = sizeof (regs.r_intb); 3964e98e3e1Schristos break; 3974e98e3e1Schristos case sim_rx_pc_regnum: 3984e98e3e1Schristos size = sizeof (regs.r_pc); 3994e98e3e1Schristos break; 4004e98e3e1Schristos case sim_rx_ps_regnum: 4014e98e3e1Schristos size = sizeof (regs.r_psw); 4024e98e3e1Schristos break; 4034e98e3e1Schristos case sim_rx_bpc_regnum: 4044e98e3e1Schristos size = sizeof (regs.r_bpc); 4054e98e3e1Schristos break; 4064e98e3e1Schristos case sim_rx_bpsw_regnum: 4074e98e3e1Schristos size = sizeof (regs.r_bpsw); 4084e98e3e1Schristos break; 4094e98e3e1Schristos case sim_rx_fintv_regnum: 4104e98e3e1Schristos size = sizeof (regs.r_fintv); 4114e98e3e1Schristos break; 4124e98e3e1Schristos case sim_rx_fpsw_regnum: 4134e98e3e1Schristos size = sizeof (regs.r_fpsw); 4144e98e3e1Schristos break; 4154e98e3e1Schristos case sim_rx_acc_regnum: 4164e98e3e1Schristos size = sizeof (regs.r_acc); 4174e98e3e1Schristos break; 4184e98e3e1Schristos default: 4194e98e3e1Schristos size = 0; 4204e98e3e1Schristos break; 4214e98e3e1Schristos } 4224e98e3e1Schristos return size; 4234e98e3e1Schristos } 4244e98e3e1Schristos 4254e98e3e1Schristos int 4264b169a6bSchristos sim_fetch_register (SIM_DESC sd, int regno, void *buf, int length) 4274e98e3e1Schristos { 4284e98e3e1Schristos size_t size; 4294e98e3e1Schristos DI val; 4304e98e3e1Schristos 4314e98e3e1Schristos check_desc (sd); 4324e98e3e1Schristos 4334e98e3e1Schristos if (!check_regno (regno)) 4344e98e3e1Schristos return 0; 4354e98e3e1Schristos 4364e98e3e1Schristos size = reg_size (regno); 4374e98e3e1Schristos 4384e98e3e1Schristos if (length != size) 4394e98e3e1Schristos return 0; 4404e98e3e1Schristos 4414e98e3e1Schristos switch (regno) 4424e98e3e1Schristos { 4434e98e3e1Schristos case sim_rx_r0_regnum: 4444e98e3e1Schristos val = get_reg (0); 4454e98e3e1Schristos break; 4464e98e3e1Schristos case sim_rx_r1_regnum: 4474e98e3e1Schristos val = get_reg (1); 4484e98e3e1Schristos break; 4494e98e3e1Schristos case sim_rx_r2_regnum: 4504e98e3e1Schristos val = get_reg (2); 4514e98e3e1Schristos break; 4524e98e3e1Schristos case sim_rx_r3_regnum: 4534e98e3e1Schristos val = get_reg (3); 4544e98e3e1Schristos break; 4554e98e3e1Schristos case sim_rx_r4_regnum: 4564e98e3e1Schristos val = get_reg (4); 4574e98e3e1Schristos break; 4584e98e3e1Schristos case sim_rx_r5_regnum: 4594e98e3e1Schristos val = get_reg (5); 4604e98e3e1Schristos break; 4614e98e3e1Schristos case sim_rx_r6_regnum: 4624e98e3e1Schristos val = get_reg (6); 4634e98e3e1Schristos break; 4644e98e3e1Schristos case sim_rx_r7_regnum: 4654e98e3e1Schristos val = get_reg (7); 4664e98e3e1Schristos break; 4674e98e3e1Schristos case sim_rx_r8_regnum: 4684e98e3e1Schristos val = get_reg (8); 4694e98e3e1Schristos break; 4704e98e3e1Schristos case sim_rx_r9_regnum: 4714e98e3e1Schristos val = get_reg (9); 4724e98e3e1Schristos break; 4734e98e3e1Schristos case sim_rx_r10_regnum: 4744e98e3e1Schristos val = get_reg (10); 4754e98e3e1Schristos break; 4764e98e3e1Schristos case sim_rx_r11_regnum: 4774e98e3e1Schristos val = get_reg (11); 4784e98e3e1Schristos break; 4794e98e3e1Schristos case sim_rx_r12_regnum: 4804e98e3e1Schristos val = get_reg (12); 4814e98e3e1Schristos break; 4824e98e3e1Schristos case sim_rx_r13_regnum: 4834e98e3e1Schristos val = get_reg (13); 4844e98e3e1Schristos break; 4854e98e3e1Schristos case sim_rx_r14_regnum: 4864e98e3e1Schristos val = get_reg (14); 4874e98e3e1Schristos break; 4884e98e3e1Schristos case sim_rx_r15_regnum: 4894e98e3e1Schristos val = get_reg (15); 4904e98e3e1Schristos break; 4914e98e3e1Schristos case sim_rx_isp_regnum: 4924e98e3e1Schristos val = get_reg (isp); 4934e98e3e1Schristos break; 4944e98e3e1Schristos case sim_rx_usp_regnum: 4954e98e3e1Schristos val = get_reg (usp); 4964e98e3e1Schristos break; 4974e98e3e1Schristos case sim_rx_intb_regnum: 4984e98e3e1Schristos val = get_reg (intb); 4994e98e3e1Schristos break; 5004e98e3e1Schristos case sim_rx_pc_regnum: 5014e98e3e1Schristos val = get_reg (pc); 5024e98e3e1Schristos break; 5034e98e3e1Schristos case sim_rx_ps_regnum: 5044e98e3e1Schristos val = get_reg (psw); 5054e98e3e1Schristos break; 5064e98e3e1Schristos case sim_rx_bpc_regnum: 5074e98e3e1Schristos val = get_reg (bpc); 5084e98e3e1Schristos break; 5094e98e3e1Schristos case sim_rx_bpsw_regnum: 5104e98e3e1Schristos val = get_reg (bpsw); 5114e98e3e1Schristos break; 5124e98e3e1Schristos case sim_rx_fintv_regnum: 5134e98e3e1Schristos val = get_reg (fintv); 5144e98e3e1Schristos break; 5154e98e3e1Schristos case sim_rx_fpsw_regnum: 5164e98e3e1Schristos val = get_reg (fpsw); 5174e98e3e1Schristos break; 5184e98e3e1Schristos case sim_rx_acc_regnum: 5194e98e3e1Schristos val = ((DI) get_reg (acchi) << 32) | get_reg (acclo); 5204e98e3e1Schristos break; 5214e98e3e1Schristos default: 5224e98e3e1Schristos fprintf (stderr, "rx minisim: unrecognized register number: %d\n", 5234e98e3e1Schristos regno); 5244e98e3e1Schristos return -1; 5254e98e3e1Schristos } 5264e98e3e1Schristos 5274e98e3e1Schristos if (rx_big_endian) 5284e98e3e1Schristos put_be (buf, length, val); 5294e98e3e1Schristos else 5304e98e3e1Schristos put_le (buf, length, val); 5314e98e3e1Schristos 5324e98e3e1Schristos return size; 5334e98e3e1Schristos } 5344e98e3e1Schristos 5354e98e3e1Schristos int 5364b169a6bSchristos sim_store_register (SIM_DESC sd, int regno, const void *buf, int length) 5374e98e3e1Schristos { 5384e98e3e1Schristos size_t size; 5394e98e3e1Schristos DI val; 5404e98e3e1Schristos 5414e98e3e1Schristos check_desc (sd); 5424e98e3e1Schristos 5434e98e3e1Schristos if (!check_regno (regno)) 5444e98e3e1Schristos return -1; 5454e98e3e1Schristos 5464e98e3e1Schristos size = reg_size (regno); 5474e98e3e1Schristos 5484e98e3e1Schristos if (length != size) 5494e98e3e1Schristos return -1; 5504e98e3e1Schristos 5514e98e3e1Schristos if (rx_big_endian) 5524e98e3e1Schristos val = get_be (buf, length); 5534e98e3e1Schristos else 5544e98e3e1Schristos val = get_le (buf, length); 5554e98e3e1Schristos 5564e98e3e1Schristos switch (regno) 5574e98e3e1Schristos { 5584e98e3e1Schristos case sim_rx_r0_regnum: 5594e98e3e1Schristos put_reg (0, val); 5604e98e3e1Schristos break; 5614e98e3e1Schristos case sim_rx_r1_regnum: 5624e98e3e1Schristos put_reg (1, val); 5634e98e3e1Schristos break; 5644e98e3e1Schristos case sim_rx_r2_regnum: 5654e98e3e1Schristos put_reg (2, val); 5664e98e3e1Schristos break; 5674e98e3e1Schristos case sim_rx_r3_regnum: 5684e98e3e1Schristos put_reg (3, val); 5694e98e3e1Schristos break; 5704e98e3e1Schristos case sim_rx_r4_regnum: 5714e98e3e1Schristos put_reg (4, val); 5724e98e3e1Schristos break; 5734e98e3e1Schristos case sim_rx_r5_regnum: 5744e98e3e1Schristos put_reg (5, val); 5754e98e3e1Schristos break; 5764e98e3e1Schristos case sim_rx_r6_regnum: 5774e98e3e1Schristos put_reg (6, val); 5784e98e3e1Schristos break; 5794e98e3e1Schristos case sim_rx_r7_regnum: 5804e98e3e1Schristos put_reg (7, val); 5814e98e3e1Schristos break; 5824e98e3e1Schristos case sim_rx_r8_regnum: 5834e98e3e1Schristos put_reg (8, val); 5844e98e3e1Schristos break; 5854e98e3e1Schristos case sim_rx_r9_regnum: 5864e98e3e1Schristos put_reg (9, val); 5874e98e3e1Schristos break; 5884e98e3e1Schristos case sim_rx_r10_regnum: 5894e98e3e1Schristos put_reg (10, val); 5904e98e3e1Schristos break; 5914e98e3e1Schristos case sim_rx_r11_regnum: 5924e98e3e1Schristos put_reg (11, val); 5934e98e3e1Schristos break; 5944e98e3e1Schristos case sim_rx_r12_regnum: 5954e98e3e1Schristos put_reg (12, val); 5964e98e3e1Schristos break; 5974e98e3e1Schristos case sim_rx_r13_regnum: 5984e98e3e1Schristos put_reg (13, val); 5994e98e3e1Schristos break; 6004e98e3e1Schristos case sim_rx_r14_regnum: 6014e98e3e1Schristos put_reg (14, val); 6024e98e3e1Schristos break; 6034e98e3e1Schristos case sim_rx_r15_regnum: 6044e98e3e1Schristos put_reg (15, val); 6054e98e3e1Schristos break; 6064e98e3e1Schristos case sim_rx_isp_regnum: 6074e98e3e1Schristos put_reg (isp, val); 6084e98e3e1Schristos break; 6094e98e3e1Schristos case sim_rx_usp_regnum: 6104e98e3e1Schristos put_reg (usp, val); 6114e98e3e1Schristos break; 6124e98e3e1Schristos case sim_rx_intb_regnum: 6134e98e3e1Schristos put_reg (intb, val); 6144e98e3e1Schristos break; 6154e98e3e1Schristos case sim_rx_pc_regnum: 6164e98e3e1Schristos put_reg (pc, val); 6174e98e3e1Schristos break; 6184e98e3e1Schristos case sim_rx_ps_regnum: 6194e98e3e1Schristos put_reg (psw, val); 6204e98e3e1Schristos break; 6214e98e3e1Schristos case sim_rx_bpc_regnum: 6224e98e3e1Schristos put_reg (bpc, val); 6234e98e3e1Schristos break; 6244e98e3e1Schristos case sim_rx_bpsw_regnum: 6254e98e3e1Schristos put_reg (bpsw, val); 6264e98e3e1Schristos break; 6274e98e3e1Schristos case sim_rx_fintv_regnum: 6284e98e3e1Schristos put_reg (fintv, val); 6294e98e3e1Schristos break; 6304e98e3e1Schristos case sim_rx_fpsw_regnum: 6314e98e3e1Schristos put_reg (fpsw, val); 6324e98e3e1Schristos break; 6334e98e3e1Schristos case sim_rx_acc_regnum: 6344e98e3e1Schristos put_reg (acclo, val & 0xffffffff); 6354e98e3e1Schristos put_reg (acchi, (val >> 32) & 0xffffffff); 6364e98e3e1Schristos break; 6374e98e3e1Schristos default: 6384e98e3e1Schristos fprintf (stderr, "rx minisim: unrecognized register number: %d\n", 6394e98e3e1Schristos regno); 6404e98e3e1Schristos return 0; 6414e98e3e1Schristos } 6424e98e3e1Schristos 6434e98e3e1Schristos return size; 6444e98e3e1Schristos } 6454e98e3e1Schristos 6464e98e3e1Schristos void 647*1f4e7eb9Schristos sim_info (SIM_DESC sd, bool verbose) 6484e98e3e1Schristos { 6494e98e3e1Schristos check_desc (sd); 6504e98e3e1Schristos 6514e98e3e1Schristos printf ("The rx minisim doesn't collect any statistics.\n"); 6524e98e3e1Schristos } 6534e98e3e1Schristos 6544e98e3e1Schristos static volatile int stop; 6554e98e3e1Schristos static enum sim_stop reason; 6564e98e3e1Schristos int siggnal; 6574e98e3e1Schristos 6584e98e3e1Schristos 6594e98e3e1Schristos /* Given a signal number used by the RX bsp (that is, newlib), 660837edd6bSchristos return a target signal number used by GDB. */ 661837edd6bSchristos static int 662837edd6bSchristos rx_signal_to_gdb_signal (int rx) 6634e98e3e1Schristos { 6644e98e3e1Schristos switch (rx) 6654e98e3e1Schristos { 6664e98e3e1Schristos case 4: 667837edd6bSchristos return GDB_SIGNAL_ILL; 6684e98e3e1Schristos 6694e98e3e1Schristos case 5: 670837edd6bSchristos return GDB_SIGNAL_TRAP; 6714e98e3e1Schristos 6724e98e3e1Schristos case 10: 673837edd6bSchristos return GDB_SIGNAL_BUS; 6744e98e3e1Schristos 6754e98e3e1Schristos case 11: 676837edd6bSchristos return GDB_SIGNAL_SEGV; 6774e98e3e1Schristos 6784e98e3e1Schristos case 24: 679837edd6bSchristos return GDB_SIGNAL_XCPU; 6804e98e3e1Schristos 6814e98e3e1Schristos case 2: 682837edd6bSchristos return GDB_SIGNAL_INT; 6834e98e3e1Schristos 6844e98e3e1Schristos case 8: 685837edd6bSchristos return GDB_SIGNAL_FPE; 6864e98e3e1Schristos 6874e98e3e1Schristos case 6: 688837edd6bSchristos return GDB_SIGNAL_ABRT; 6894e98e3e1Schristos } 6904e98e3e1Schristos 6914e98e3e1Schristos return 0; 6924e98e3e1Schristos } 6934e98e3e1Schristos 6944e98e3e1Schristos 6954e98e3e1Schristos /* Take a step return code RC and set up the variables consulted by 6964e98e3e1Schristos sim_stop_reason appropriately. */ 6974b169a6bSchristos static void 6984e98e3e1Schristos handle_step (int rc) 6994e98e3e1Schristos { 7004e98e3e1Schristos if (execution_error_get_last_error () != SIM_ERR_NONE) 7014e98e3e1Schristos { 7024e98e3e1Schristos reason = sim_stopped; 703a2e2270fSchristos siggnal = GDB_SIGNAL_SEGV; 7044e98e3e1Schristos } 7054e98e3e1Schristos if (RX_STEPPED (rc) || RX_HIT_BREAK (rc)) 7064e98e3e1Schristos { 7074e98e3e1Schristos reason = sim_stopped; 708a2e2270fSchristos siggnal = GDB_SIGNAL_TRAP; 7094e98e3e1Schristos } 7104e98e3e1Schristos else if (RX_STOPPED (rc)) 7114e98e3e1Schristos { 7124e98e3e1Schristos reason = sim_stopped; 713837edd6bSchristos siggnal = rx_signal_to_gdb_signal (RX_STOP_SIG (rc)); 7144e98e3e1Schristos } 7154e98e3e1Schristos else 7164e98e3e1Schristos { 7174e98e3e1Schristos assert (RX_EXITED (rc)); 7184e98e3e1Schristos reason = sim_exited; 7194e98e3e1Schristos siggnal = RX_EXIT_STATUS (rc); 7204e98e3e1Schristos } 7214e98e3e1Schristos } 7224e98e3e1Schristos 7234e98e3e1Schristos 7244e98e3e1Schristos void 7254e98e3e1Schristos sim_resume (SIM_DESC sd, int step, int sig_to_deliver) 7264e98e3e1Schristos { 7274e98e3e1Schristos int rc; 7284e98e3e1Schristos 7294e98e3e1Schristos check_desc (sd); 7304e98e3e1Schristos 7314e98e3e1Schristos if (sig_to_deliver != 0) 7324e98e3e1Schristos { 7334e98e3e1Schristos fprintf (stderr, 7344e98e3e1Schristos "Warning: the rx minisim does not implement " 7354e98e3e1Schristos "signal delivery yet.\n" "Resuming with no signal.\n"); 7364e98e3e1Schristos } 7374e98e3e1Schristos 7384e98e3e1Schristos execution_error_clear_last_error (); 7394e98e3e1Schristos 7404e98e3e1Schristos if (step) 7414e98e3e1Schristos { 7424e98e3e1Schristos rc = setjmp (decode_jmp_buf); 7434e98e3e1Schristos if (rc == 0) 7444e98e3e1Schristos rc = decode_opcode (); 7454e98e3e1Schristos handle_step (rc); 7464e98e3e1Schristos } 7474e98e3e1Schristos else 7484e98e3e1Schristos { 7494e98e3e1Schristos /* We don't clear 'stop' here, because then we would miss 7504e98e3e1Schristos interrupts that arrived on the way here. Instead, we clear 7514e98e3e1Schristos the flag in sim_stop_reason, after GDB has disabled the 7524e98e3e1Schristos interrupt signal handler. */ 7534e98e3e1Schristos for (;;) 7544e98e3e1Schristos { 7554e98e3e1Schristos if (stop) 7564e98e3e1Schristos { 7574e98e3e1Schristos stop = 0; 7584e98e3e1Schristos reason = sim_stopped; 759a2e2270fSchristos siggnal = GDB_SIGNAL_INT; 7604e98e3e1Schristos break; 7614e98e3e1Schristos } 7624e98e3e1Schristos 7634e98e3e1Schristos rc = setjmp (decode_jmp_buf); 7644e98e3e1Schristos if (rc == 0) 7654e98e3e1Schristos rc = decode_opcode (); 7664e98e3e1Schristos 7674e98e3e1Schristos if (execution_error_get_last_error () != SIM_ERR_NONE) 7684e98e3e1Schristos { 7694e98e3e1Schristos reason = sim_stopped; 770a2e2270fSchristos siggnal = GDB_SIGNAL_SEGV; 7714e98e3e1Schristos break; 7724e98e3e1Schristos } 7734e98e3e1Schristos 7744e98e3e1Schristos if (!RX_STEPPED (rc)) 7754e98e3e1Schristos { 7764e98e3e1Schristos handle_step (rc); 7774e98e3e1Schristos break; 7784e98e3e1Schristos } 7794e98e3e1Schristos } 7804e98e3e1Schristos } 7814e98e3e1Schristos } 7824e98e3e1Schristos 7834e98e3e1Schristos int 7844e98e3e1Schristos sim_stop (SIM_DESC sd) 7854e98e3e1Schristos { 7864e98e3e1Schristos stop = 1; 7874e98e3e1Schristos 7884e98e3e1Schristos return 1; 7894e98e3e1Schristos } 7904e98e3e1Schristos 7914e98e3e1Schristos void 7924e98e3e1Schristos sim_stop_reason (SIM_DESC sd, enum sim_stop *reason_p, int *sigrc_p) 7934e98e3e1Schristos { 7944e98e3e1Schristos check_desc (sd); 7954e98e3e1Schristos 7964e98e3e1Schristos *reason_p = reason; 7974e98e3e1Schristos *sigrc_p = siggnal; 7984e98e3e1Schristos } 7994e98e3e1Schristos 8004e98e3e1Schristos void 801837edd6bSchristos sim_do_command (SIM_DESC sd, const char *cmd) 8024e98e3e1Schristos { 8034b169a6bSchristos const char *arg; 8044b169a6bSchristos char **argv = buildargv (cmd); 8054e98e3e1Schristos 806837edd6bSchristos check_desc (sd); 8074e98e3e1Schristos 8084b169a6bSchristos cmd = arg = ""; 8094b169a6bSchristos if (argv != NULL) 8104e98e3e1Schristos { 8114b169a6bSchristos if (argv[0] != NULL) 8124b169a6bSchristos cmd = argv[0]; 8134b169a6bSchristos if (argv[1] != NULL) 8144b169a6bSchristos arg = argv[1]; 8154e98e3e1Schristos } 8164e98e3e1Schristos 8174e98e3e1Schristos if (strcmp (cmd, "trace") == 0) 8184e98e3e1Schristos { 8194b169a6bSchristos if (strcmp (arg, "on") == 0) 8204e98e3e1Schristos trace = 1; 8214b169a6bSchristos else if (strcmp (arg, "off") == 0) 8224e98e3e1Schristos trace = 0; 8234e98e3e1Schristos else 8244e98e3e1Schristos printf ("The 'sim trace' command expects 'on' or 'off' " 8254e98e3e1Schristos "as an argument.\n"); 8264e98e3e1Schristos } 8274e98e3e1Schristos else if (strcmp (cmd, "verbose") == 0) 8284e98e3e1Schristos { 8294b169a6bSchristos if (strcmp (arg, "on") == 0) 8304e98e3e1Schristos verbose = 1; 8314b169a6bSchristos else if (strcmp (arg, "noisy") == 0) 8324e98e3e1Schristos verbose = 2; 8334b169a6bSchristos else if (strcmp (arg, "off") == 0) 8344e98e3e1Schristos verbose = 0; 8354e98e3e1Schristos else 8364e98e3e1Schristos printf ("The 'sim verbose' command expects 'on', 'noisy', or 'off'" 8374e98e3e1Schristos " as an argument.\n"); 8384e98e3e1Schristos } 8394e98e3e1Schristos else 8404e98e3e1Schristos printf ("The 'sim' command expects either 'trace' or 'verbose'" 8414e98e3e1Schristos " as a subcommand.\n"); 842837edd6bSchristos 8434b169a6bSchristos freeargv (argv); 8444e98e3e1Schristos } 845a2e2270fSchristos 846a2e2270fSchristos char ** 84703467a24Schristos sim_complete_command (SIM_DESC sd, const char *text, const char *word) 848a2e2270fSchristos { 849a2e2270fSchristos return NULL; 850a2e2270fSchristos } 8514b169a6bSchristos 8524b169a6bSchristos /* Stub this out for now. */ 8534b169a6bSchristos 8544b169a6bSchristos char * 8554b169a6bSchristos sim_memory_map (SIM_DESC sd) 8564b169a6bSchristos { 8574b169a6bSchristos return NULL; 8584b169a6bSchristos } 859