Home | History | Annotate | Line # | Download | only in pru
      1      1.1  christos /* Simulator for the Texas Instruments PRU processor
      2  1.1.1.3  christos    Copyright 2009-2024 Free Software Foundation, Inc.
      3      1.1  christos    Inspired by the Microblaze simulator
      4      1.1  christos    Contributed by Dimitar Dimitrov <dimitar (at) dinux.eu>
      5      1.1  christos 
      6      1.1  christos    This file is part of the simulators.
      7      1.1  christos 
      8      1.1  christos    This program is free software; you can redistribute it and/or modify
      9      1.1  christos    it under the terms of the GNU General Public License as published by
     10      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     11      1.1  christos    (at your option) any later version.
     12      1.1  christos 
     13      1.1  christos    This program is distributed in the hope that it will be useful,
     14      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16      1.1  christos    GNU General Public License for more details.
     17      1.1  christos 
     18      1.1  christos    You should have received a copy of the GNU General Public License
     19      1.1  christos    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
     20      1.1  christos 
     21  1.1.1.2  christos /* This must come before any other includes.  */
     22  1.1.1.2  christos #include "defs.h"
     23  1.1.1.2  christos 
     24      1.1  christos #include <stdbool.h>
     25      1.1  christos #include <stdint.h>
     26      1.1  christos #include <stddef.h>
     27      1.1  christos #include "bfd.h"
     28  1.1.1.2  christos #include "sim/callback.h"
     29      1.1  christos #include "libiberty.h"
     30  1.1.1.2  christos #include "sim/sim.h"
     31      1.1  christos #include "sim-main.h"
     32      1.1  christos #include "sim-assert.h"
     33      1.1  christos #include "sim-options.h"
     34  1.1.1.2  christos #include "sim-signal.h"
     35      1.1  christos #include "sim-syscall.h"
     36      1.1  christos #include "pru.h"
     37      1.1  christos 
     38      1.1  christos /* DMEM zero address is perfectly valid.  But if CRT leaves the first word
     39      1.1  christos    alone, we can use it as a trap to catch NULL pointer access.  */
     40      1.1  christos static bfd_boolean abort_on_dmem_zero_access;
     41      1.1  christos 
     42      1.1  christos enum {
     43      1.1  christos   OPTION_ERROR_NULL_DEREF = OPTION_START,
     44      1.1  christos };
     45      1.1  christos 
     46      1.1  christos /* Extract (from PRU endianess) and return an integer in HOST's endianness.  */
     47      1.1  christos static uint32_t
     48  1.1.1.2  christos pru_extract_unsigned_integer (const uint8_t *addr, size_t len)
     49      1.1  christos {
     50      1.1  christos   uint32_t retval;
     51  1.1.1.2  christos   const uint8_t *p;
     52  1.1.1.2  christos   const uint8_t *startaddr = addr;
     53  1.1.1.2  christos   const uint8_t *endaddr = startaddr + len;
     54      1.1  christos 
     55      1.1  christos   /* Start at the most significant end of the integer, and work towards
     56      1.1  christos      the least significant.  */
     57      1.1  christos   retval = 0;
     58      1.1  christos 
     59      1.1  christos   for (p = endaddr; p > startaddr;)
     60      1.1  christos     retval = (retval << 8) | * -- p;
     61      1.1  christos   return retval;
     62      1.1  christos }
     63      1.1  christos 
     64      1.1  christos /* Store "val" (which is in HOST's endianess) into "addr"
     65      1.1  christos    (using PRU's endianness).  */
     66      1.1  christos static void
     67      1.1  christos pru_store_unsigned_integer (uint8_t *addr, size_t len, uint32_t val)
     68      1.1  christos {
     69      1.1  christos   uint8_t *p;
     70      1.1  christos   uint8_t *startaddr = (uint8_t *)addr;
     71      1.1  christos   uint8_t *endaddr = startaddr + len;
     72      1.1  christos 
     73      1.1  christos   for (p = startaddr; p < endaddr;)
     74      1.1  christos     {
     75      1.1  christos       *p++ = val & 0xff;
     76      1.1  christos       val >>= 8;
     77      1.1  christos     }
     78      1.1  christos }
     79      1.1  christos 
     80      1.1  christos /* Extract a field value from CPU register using the given REGSEL selector.
     81      1.1  christos 
     82      1.1  christos    Byte number maps directly to first values of RSEL, so we can
     83      1.1  christos    safely use "regsel" as a register byte number (0..3).  */
     84      1.1  christos static inline uint32_t
     85      1.1  christos extract_regval (uint32_t val, uint32_t regsel)
     86      1.1  christos {
     87      1.1  christos   ASSERT (RSEL_7_0 == 0);
     88      1.1  christos   ASSERT (RSEL_15_8 == 1);
     89      1.1  christos   ASSERT (RSEL_23_16 == 2);
     90      1.1  christos   ASSERT (RSEL_31_24 == 3);
     91      1.1  christos 
     92      1.1  christos   switch (regsel)
     93      1.1  christos     {
     94      1.1  christos     case RSEL_7_0:    return (val >> 0) & 0xff;
     95      1.1  christos     case RSEL_15_8:   return (val >> 8) & 0xff;
     96      1.1  christos     case RSEL_23_16:  return (val >> 16) & 0xff;
     97      1.1  christos     case RSEL_31_24:  return (val >> 24) & 0xff;
     98      1.1  christos     case RSEL_15_0:   return (val >> 0) & 0xffff;
     99      1.1  christos     case RSEL_23_8:   return (val >> 8) & 0xffff;
    100      1.1  christos     case RSEL_31_16:  return (val >> 16) & 0xffff;
    101      1.1  christos     case RSEL_31_0:   return val;
    102      1.1  christos     default:	      sim_io_error (NULL, "invalid regsel");
    103      1.1  christos     }
    104      1.1  christos }
    105      1.1  christos 
    106      1.1  christos /* Write a value into CPU subregister pointed by reg and regsel.  */
    107      1.1  christos static inline void
    108      1.1  christos write_regval (uint32_t val, uint32_t *reg, uint32_t regsel)
    109      1.1  christos {
    110      1.1  christos   uint32_t mask, sh;
    111      1.1  christos 
    112      1.1  christos   switch (regsel)
    113      1.1  christos     {
    114      1.1  christos     case RSEL_7_0:    mask = (0xffu << 0); sh = 0; break;
    115      1.1  christos     case RSEL_15_8:   mask = (0xffu << 8); sh = 8; break;
    116      1.1  christos     case RSEL_23_16:  mask = (0xffu << 16); sh = 16; break;
    117      1.1  christos     case RSEL_31_24:  mask = (0xffu << 24); sh = 24; break;
    118      1.1  christos     case RSEL_15_0:   mask = (0xffffu << 0); sh = 0; break;
    119      1.1  christos     case RSEL_23_8:   mask = (0xffffu << 8); sh = 8; break;
    120      1.1  christos     case RSEL_31_16:  mask = (0xffffu << 16); sh = 16; break;
    121      1.1  christos     case RSEL_31_0:   mask = 0xffffffffu; sh = 0; break;
    122      1.1  christos     default:	      sim_io_error (NULL, "invalid regsel");
    123      1.1  christos     }
    124      1.1  christos 
    125      1.1  christos   *reg = (*reg & ~mask) | ((val << sh) & mask);
    126      1.1  christos }
    127      1.1  christos 
    128      1.1  christos /* Convert the given IMEM word address to a regular byte address used by the
    129      1.1  christos    GNU ELF container.  */
    130      1.1  christos static uint32_t
    131      1.1  christos imem_wordaddr_to_byteaddr (SIM_CPU *cpu, uint16_t wa)
    132      1.1  christos {
    133  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    134  1.1.1.3  christos 
    135      1.1  christos   return (((uint32_t) wa << 2) & IMEM_ADDR_MASK) | PC_ADDR_SPACE_MARKER;
    136      1.1  christos }
    137      1.1  christos 
    138      1.1  christos /* Convert the given ELF text byte address to IMEM word address.  */
    139      1.1  christos static uint16_t
    140      1.1  christos imem_byteaddr_to_wordaddr (SIM_CPU *cpu, uint32_t ba)
    141      1.1  christos {
    142      1.1  christos   return (ba >> 2) & 0xffff;
    143      1.1  christos }
    144      1.1  christos 
    145      1.1  christos 
    146      1.1  christos /* Store "nbytes" into DMEM "addr" from CPU register file, starting with
    147      1.1  christos    register "regn", and byte "regb" within it.  */
    148      1.1  christos static inline void
    149      1.1  christos pru_reg2dmem (SIM_CPU *cpu, uint32_t addr, unsigned int nbytes,
    150      1.1  christos 	      int regn, int regb)
    151      1.1  christos {
    152  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    153      1.1  christos   /* GDB assumes unconditional access to all memories, so enable additional
    154      1.1  christos      checks only in standalone mode.  */
    155      1.1  christos   bool standalone = (STATE_OPEN_KIND (CPU_STATE (cpu)) == SIM_OPEN_STANDALONE);
    156      1.1  christos 
    157      1.1  christos   if (abort_on_dmem_zero_access && addr < 4)
    158      1.1  christos     {
    159      1.1  christos       sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, write_map,
    160      1.1  christos 		       nbytes, addr, write_transfer,
    161      1.1  christos 		       sim_core_unmapped_signal);
    162      1.1  christos     }
    163      1.1  christos   else if (standalone && ((addr >= PC_ADDR_SPACE_MARKER)
    164      1.1  christos 			  || (addr + nbytes > PC_ADDR_SPACE_MARKER)))
    165      1.1  christos     {
    166      1.1  christos       sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, write_map,
    167      1.1  christos 		       nbytes, addr, write_transfer,
    168      1.1  christos 		       sim_core_unmapped_signal);
    169      1.1  christos     }
    170      1.1  christos   else if ((regn * 4 + regb + nbytes) > (32 * 4))
    171      1.1  christos     {
    172      1.1  christos       sim_io_eprintf (CPU_STATE (cpu),
    173      1.1  christos 		      "SBBO/SBCO with invalid store data length\n");
    174      1.1  christos       RAISE_SIGILL (CPU_STATE (cpu));
    175      1.1  christos     }
    176      1.1  christos   else
    177      1.1  christos     {
    178      1.1  christos       TRACE_MEMORY (cpu, "write of %d bytes to %08x", nbytes, addr);
    179      1.1  christos       while (nbytes--)
    180      1.1  christos 	{
    181      1.1  christos 	  sim_core_write_1 (cpu,
    182      1.1  christos 			    PC_byteaddr,
    183      1.1  christos 			    write_map,
    184      1.1  christos 			    addr++,
    185      1.1  christos 			    extract_regval (CPU.regs[regn], regb));
    186      1.1  christos 
    187      1.1  christos 	  if (++regb >= 4)
    188      1.1  christos 	    {
    189      1.1  christos 	      regb = 0;
    190      1.1  christos 	      regn++;
    191      1.1  christos 	    }
    192      1.1  christos 	}
    193      1.1  christos     }
    194      1.1  christos }
    195      1.1  christos 
    196      1.1  christos /* Load "nbytes" from DMEM "addr" into CPU register file, starting with
    197      1.1  christos    register "regn", and byte "regb" within it.  */
    198      1.1  christos static inline void
    199      1.1  christos pru_dmem2reg (SIM_CPU *cpu, uint32_t addr, unsigned int nbytes,
    200      1.1  christos 	      int regn, int regb)
    201      1.1  christos {
    202  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    203      1.1  christos   /* GDB assumes unconditional access to all memories, so enable additional
    204      1.1  christos      checks only in standalone mode.  */
    205      1.1  christos   bool standalone = (STATE_OPEN_KIND (CPU_STATE (cpu)) == SIM_OPEN_STANDALONE);
    206      1.1  christos 
    207      1.1  christos   if (abort_on_dmem_zero_access && addr < 4)
    208      1.1  christos     {
    209      1.1  christos       sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, read_map,
    210      1.1  christos 		       nbytes, addr, read_transfer,
    211      1.1  christos 		       sim_core_unmapped_signal);
    212      1.1  christos     }
    213      1.1  christos   else if (standalone && ((addr >= PC_ADDR_SPACE_MARKER)
    214      1.1  christos 			  || (addr + nbytes > PC_ADDR_SPACE_MARKER)))
    215      1.1  christos     {
    216      1.1  christos       /* This check is necessary because our IMEM "address space"
    217      1.1  christos 	 is not really accessible, yet we have mapped it as a generic
    218      1.1  christos 	 memory space.  */
    219      1.1  christos       sim_core_signal (CPU_STATE (cpu), cpu, PC_byteaddr, read_map,
    220      1.1  christos 		       nbytes, addr, read_transfer,
    221      1.1  christos 		       sim_core_unmapped_signal);
    222      1.1  christos     }
    223      1.1  christos   else if ((regn * 4 + regb + nbytes) > (32 * 4))
    224      1.1  christos     {
    225      1.1  christos       sim_io_eprintf (CPU_STATE (cpu),
    226      1.1  christos 		      "LBBO/LBCO with invalid load data length\n");
    227      1.1  christos       RAISE_SIGILL (CPU_STATE (cpu));
    228      1.1  christos     }
    229      1.1  christos   else
    230      1.1  christos     {
    231      1.1  christos       unsigned int b;
    232      1.1  christos       TRACE_MEMORY (cpu, "read of %d bytes from %08x", nbytes, addr);
    233      1.1  christos       while (nbytes--)
    234      1.1  christos 	{
    235      1.1  christos 	  b = sim_core_read_1 (cpu, PC_byteaddr, read_map, addr++);
    236      1.1  christos 
    237      1.1  christos 	  /* Reuse the fact the Register Byte Number maps directly to RSEL.  */
    238      1.1  christos 	  ASSERT (RSEL_7_0 == 0);
    239      1.1  christos 	  write_regval (b, &CPU.regs[regn], regb);
    240      1.1  christos 
    241      1.1  christos 	  if (++regb >= 4)
    242      1.1  christos 	    {
    243      1.1  christos 	      regb = 0;
    244      1.1  christos 	      regn++;
    245      1.1  christos 	    }
    246      1.1  christos 	}
    247      1.1  christos     }
    248      1.1  christos }
    249      1.1  christos 
    250      1.1  christos /* Set reset values of general-purpose registers.  */
    251      1.1  christos static void
    252      1.1  christos set_initial_gprs (SIM_CPU *cpu)
    253      1.1  christos {
    254  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    255      1.1  christos   int i;
    256      1.1  christos 
    257      1.1  christos   /* Set up machine just out of reset.  */
    258      1.1  christos   CPU_PC_SET (cpu, 0);
    259      1.1  christos   PC_ADDR_SPACE_MARKER = IMEM_ADDR_DEFAULT; /* from default linker script? */
    260      1.1  christos 
    261      1.1  christos   /* Clean out the GPRs.  */
    262      1.1  christos   for (i = 0; i < ARRAY_SIZE (CPU.regs); i++)
    263      1.1  christos     CPU.regs[i] = 0;
    264      1.1  christos   for (i = 0; i < ARRAY_SIZE (CPU.macregs); i++)
    265      1.1  christos     CPU.macregs[i] = 0;
    266      1.1  christos 
    267      1.1  christos   CPU.loop.looptop = CPU.loop.loopend = 0;
    268      1.1  christos   CPU.loop.loop_in_progress = 0;
    269      1.1  christos   CPU.loop.loop_counter = 0;
    270      1.1  christos 
    271      1.1  christos   CPU.carry = 0;
    272      1.1  christos   CPU.insts = 0;
    273      1.1  christos   CPU.cycles = 0;
    274      1.1  christos 
    275      1.1  christos   /* AM335x should provide sane defaults.  */
    276      1.1  christos   CPU.ctable[0] = 0x00020000;
    277      1.1  christos   CPU.ctable[1] = 0x48040000;
    278      1.1  christos   CPU.ctable[2] = 0x4802a000;
    279      1.1  christos   CPU.ctable[3] = 0x00030000;
    280      1.1  christos   CPU.ctable[4] = 0x00026000;
    281      1.1  christos   CPU.ctable[5] = 0x48060000;
    282      1.1  christos   CPU.ctable[6] = 0x48030000;
    283      1.1  christos   CPU.ctable[7] = 0x00028000;
    284      1.1  christos   CPU.ctable[8] = 0x46000000;
    285      1.1  christos   CPU.ctable[9] = 0x4a100000;
    286      1.1  christos   CPU.ctable[10] = 0x48318000;
    287      1.1  christos   CPU.ctable[11] = 0x48022000;
    288      1.1  christos   CPU.ctable[12] = 0x48024000;
    289      1.1  christos   CPU.ctable[13] = 0x48310000;
    290      1.1  christos   CPU.ctable[14] = 0x481cc000;
    291      1.1  christos   CPU.ctable[15] = 0x481d0000;
    292      1.1  christos   CPU.ctable[16] = 0x481a0000;
    293      1.1  christos   CPU.ctable[17] = 0x4819c000;
    294      1.1  christos   CPU.ctable[18] = 0x48300000;
    295      1.1  christos   CPU.ctable[19] = 0x48302000;
    296      1.1  christos   CPU.ctable[20] = 0x48304000;
    297      1.1  christos   CPU.ctable[21] = 0x00032400;
    298      1.1  christos   CPU.ctable[22] = 0x480c8000;
    299      1.1  christos   CPU.ctable[23] = 0x480ca000;
    300      1.1  christos   CPU.ctable[24] = 0x00000000;
    301      1.1  christos   CPU.ctable[25] = 0x00002000;
    302      1.1  christos   CPU.ctable[26] = 0x0002e000;
    303      1.1  christos   CPU.ctable[27] = 0x00032000;
    304      1.1  christos   CPU.ctable[28] = 0x00000000;
    305      1.1  christos   CPU.ctable[29] = 0x49000000;
    306      1.1  christos   CPU.ctable[30] = 0x40000000;
    307      1.1  christos   CPU.ctable[31] = 0x80000000;
    308      1.1  christos }
    309      1.1  christos 
    310      1.1  christos /* Map regsel selector to subregister field width.  */
    311      1.1  christos static inline unsigned int
    312      1.1  christos regsel_width (uint32_t regsel)
    313      1.1  christos {
    314      1.1  christos   switch (regsel)
    315      1.1  christos     {
    316      1.1  christos     case RSEL_7_0:    return 8;
    317      1.1  christos     case RSEL_15_8:   return 8;
    318      1.1  christos     case RSEL_23_16:  return 8;
    319      1.1  christos     case RSEL_31_24:  return 8;
    320      1.1  christos     case RSEL_15_0:   return 16;
    321      1.1  christos     case RSEL_23_8:   return 16;
    322      1.1  christos     case RSEL_31_16:  return 16;
    323      1.1  christos     case RSEL_31_0:   return 32;
    324      1.1  christos     default:	      sim_io_error (NULL, "invalid regsel");
    325      1.1  christos     }
    326      1.1  christos }
    327      1.1  christos 
    328      1.1  christos /* Handle XIN instruction addressing the MAC peripheral.  */
    329      1.1  christos static void
    330      1.1  christos pru_sim_xin_mac (SIM_DESC sd, SIM_CPU *cpu, unsigned int rd_regn,
    331      1.1  christos 		 unsigned int rdb, unsigned int length)
    332      1.1  christos {
    333  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    334  1.1.1.3  christos 
    335      1.1  christos   if (rd_regn < 25 || (rd_regn * 4 + rdb + length) > (27 + 1) * 4)
    336      1.1  christos     sim_io_error (sd, "XIN MAC: invalid transfer regn=%u.%u, length=%u\n",
    337      1.1  christos 		  rd_regn, rdb, length);
    338      1.1  christos 
    339      1.1  christos   /* Copy from MAC to PRU regs.  Ranges have been validated above.  */
    340      1.1  christos   while (length--)
    341      1.1  christos     {
    342      1.1  christos       write_regval (CPU.macregs[rd_regn - 25] >> (rdb * 8),
    343      1.1  christos 		    &CPU.regs[rd_regn],
    344      1.1  christos 		    rdb);
    345      1.1  christos       if (++rdb == 4)
    346      1.1  christos 	{
    347      1.1  christos 	  rdb = 0;
    348      1.1  christos 	  rd_regn++;
    349      1.1  christos 	}
    350      1.1  christos     }
    351      1.1  christos }
    352      1.1  christos 
    353      1.1  christos /* Handle XIN instruction.  */
    354      1.1  christos static void
    355      1.1  christos pru_sim_xin (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
    356      1.1  christos 	     unsigned int rd_regn, unsigned int rdb, unsigned int length)
    357      1.1  christos {
    358  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    359  1.1.1.3  christos 
    360      1.1  christos   if (wba == 0)
    361      1.1  christos     {
    362      1.1  christos       pru_sim_xin_mac (sd, cpu, rd_regn, rdb, length);
    363      1.1  christos     }
    364      1.1  christos   else if (wba == XFRID_SCRATCH_BANK_0 || wba == XFRID_SCRATCH_BANK_1
    365      1.1  christos 	   || wba == XFRID_SCRATCH_BANK_2 || wba == XFRID_SCRATCH_BANK_PEER)
    366      1.1  christos     {
    367      1.1  christos       while (length--)
    368      1.1  christos 	{
    369      1.1  christos 	  unsigned int val;
    370      1.1  christos 
    371      1.1  christos 	  val = extract_regval (CPU.scratchpads[wba][rd_regn], rdb);
    372      1.1  christos 	  write_regval (val, &CPU.regs[rd_regn], rdb);
    373      1.1  christos 	  if (++rdb == 4)
    374      1.1  christos 	    {
    375      1.1  christos 	      rdb = 0;
    376      1.1  christos 	      rd_regn++;
    377      1.1  christos 	    }
    378      1.1  christos 	}
    379      1.1  christos     }
    380      1.1  christos   else if (wba == 254 || wba == 255)
    381      1.1  christos     {
    382      1.1  christos       /* FILL/ZERO pseudos implemented via XIN.  */
    383      1.1  christos       unsigned int fillbyte = (wba == 254) ? 0xff : 0x00;
    384      1.1  christos       while (length--)
    385      1.1  christos 	{
    386      1.1  christos 	  write_regval (fillbyte, &CPU.regs[rd_regn], rdb);
    387      1.1  christos 	  if (++rdb == 4)
    388      1.1  christos 	    {
    389      1.1  christos 	      rdb = 0;
    390      1.1  christos 	      rd_regn++;
    391      1.1  christos 	    }
    392      1.1  christos 	}
    393      1.1  christos     }
    394      1.1  christos   else
    395      1.1  christos     {
    396      1.1  christos       sim_io_error (sd, "XIN: XFR device %d not supported.\n", wba);
    397      1.1  christos     }
    398      1.1  christos }
    399      1.1  christos 
    400      1.1  christos /* Handle XOUT instruction addressing the MAC peripheral.  */
    401      1.1  christos static void
    402      1.1  christos pru_sim_xout_mac (SIM_DESC sd, SIM_CPU *cpu, unsigned int rd_regn,
    403      1.1  christos 		  unsigned int rdb, unsigned int length)
    404      1.1  christos {
    405  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    406      1.1  christos   const int modereg_accessed = (rd_regn == 25);
    407      1.1  christos 
    408      1.1  christos   /* Multiple Accumulate.  */
    409      1.1  christos   if (rd_regn < 25 || (rd_regn * 4 + rdb + length) > (27 + 1) * 4)
    410      1.1  christos     sim_io_error (sd, "XOUT MAC: invalid transfer regn=%u.%u, length=%u\n",
    411      1.1  christos 		  rd_regn, rdb, length);
    412      1.1  christos 
    413      1.1  christos   /* Copy from PRU to MAC regs.  Ranges have been validated above.  */
    414      1.1  christos   while (length--)
    415      1.1  christos     {
    416      1.1  christos       write_regval (CPU.regs[rd_regn] >> (rdb * 8),
    417      1.1  christos 		    &CPU.macregs[rd_regn - 25],
    418      1.1  christos 		    rdb);
    419      1.1  christos       if (++rdb == 4)
    420      1.1  christos 	{
    421      1.1  christos 	  rdb = 0;
    422      1.1  christos 	  rd_regn++;
    423      1.1  christos 	}
    424      1.1  christos     }
    425      1.1  christos 
    426      1.1  christos   if (modereg_accessed
    427      1.1  christos       && (CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK))
    428      1.1  christos     {
    429      1.1  christos       /* MUL/MAC operands are sampled every XOUT in multiply and
    430      1.1  christos 	 accumulate mode.  */
    431      1.1  christos       uint64_t prod, oldsum, sum;
    432      1.1  christos       CPU.macregs[PRU_MACREG_OP_0] = CPU.regs[28];
    433      1.1  christos       CPU.macregs[PRU_MACREG_OP_1] = CPU.regs[29];
    434      1.1  christos 
    435      1.1  christos       prod = CPU.macregs[PRU_MACREG_OP_0];
    436      1.1  christos       prod *= (uint64_t)CPU.macregs[PRU_MACREG_OP_1];
    437      1.1  christos 
    438      1.1  christos       oldsum = CPU.macregs[PRU_MACREG_ACC_L];
    439      1.1  christos       oldsum += (uint64_t)CPU.macregs[PRU_MACREG_ACC_H] << 32;
    440      1.1  christos       sum = oldsum + prod;
    441      1.1  christos 
    442      1.1  christos       CPU.macregs[PRU_MACREG_PROD_L] = sum & 0xfffffffful;
    443      1.1  christos       CPU.macregs[PRU_MACREG_PROD_H] = sum >> 32;
    444      1.1  christos       CPU.macregs[PRU_MACREG_ACC_L] = CPU.macregs[PRU_MACREG_PROD_L];
    445      1.1  christos       CPU.macregs[PRU_MACREG_ACC_H] = CPU.macregs[PRU_MACREG_PROD_H];
    446      1.1  christos 
    447      1.1  christos       if (oldsum > sum)
    448      1.1  christos 	CPU.macregs[PRU_MACREG_MODE] |= MAC_R25_ACC_CARRY_MASK;
    449      1.1  christos     }
    450      1.1  christos   if (modereg_accessed
    451      1.1  christos       && (CPU.macregs[PRU_MACREG_MODE] & MAC_R25_ACC_CARRY_MASK))
    452      1.1  christos     {
    453      1.1  christos       /* store 1 to clear.  */
    454      1.1  christos       CPU.macregs[PRU_MACREG_MODE] &= ~MAC_R25_ACC_CARRY_MASK;
    455      1.1  christos       CPU.macregs[PRU_MACREG_ACC_L] = 0;
    456      1.1  christos       CPU.macregs[PRU_MACREG_ACC_H] = 0;
    457      1.1  christos     }
    458      1.1  christos 
    459      1.1  christos }
    460      1.1  christos 
    461      1.1  christos /* Handle XOUT instruction.  */
    462      1.1  christos static void
    463      1.1  christos pru_sim_xout (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
    464      1.1  christos 	      unsigned int rd_regn, unsigned int rdb, unsigned int length)
    465      1.1  christos {
    466  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    467  1.1.1.3  christos 
    468      1.1  christos   if (wba == 0)
    469      1.1  christos     {
    470      1.1  christos       pru_sim_xout_mac (sd, cpu, rd_regn, rdb, length);
    471      1.1  christos     }
    472      1.1  christos   else if (wba == XFRID_SCRATCH_BANK_0 || wba == XFRID_SCRATCH_BANK_1
    473      1.1  christos 	   || wba == XFRID_SCRATCH_BANK_2 || wba == XFRID_SCRATCH_BANK_PEER)
    474      1.1  christos     {
    475      1.1  christos       while (length--)
    476      1.1  christos 	{
    477      1.1  christos 	  unsigned int val;
    478      1.1  christos 
    479      1.1  christos 	  val = extract_regval (CPU.regs[rd_regn], rdb);
    480      1.1  christos 	  write_regval (val, &CPU.scratchpads[wba][rd_regn], rdb);
    481      1.1  christos 	  if (++rdb == 4)
    482      1.1  christos 	    {
    483      1.1  christos 	      rdb = 0;
    484      1.1  christos 	      rd_regn++;
    485      1.1  christos 	    }
    486      1.1  christos 	}
    487      1.1  christos     }
    488      1.1  christos   else
    489      1.1  christos     sim_io_error (sd, "XOUT: XFR device %d not supported.\n", wba);
    490      1.1  christos }
    491      1.1  christos 
    492      1.1  christos /* Handle XCHG instruction.  */
    493      1.1  christos static void
    494      1.1  christos pru_sim_xchg (SIM_DESC sd, SIM_CPU *cpu, unsigned int wba,
    495      1.1  christos 	      unsigned int rd_regn, unsigned int rdb, unsigned int length)
    496      1.1  christos {
    497  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    498  1.1.1.3  christos 
    499      1.1  christos   if (wba == XFRID_SCRATCH_BANK_0 || wba == XFRID_SCRATCH_BANK_1
    500      1.1  christos 	   || wba == XFRID_SCRATCH_BANK_2 || wba == XFRID_SCRATCH_BANK_PEER)
    501      1.1  christos     {
    502      1.1  christos       while (length--)
    503      1.1  christos 	{
    504      1.1  christos 	  unsigned int valr, vals;
    505      1.1  christos 
    506      1.1  christos 	  valr = extract_regval (CPU.regs[rd_regn], rdb);
    507      1.1  christos 	  vals = extract_regval (CPU.scratchpads[wba][rd_regn], rdb);
    508      1.1  christos 	  write_regval (valr, &CPU.scratchpads[wba][rd_regn], rdb);
    509      1.1  christos 	  write_regval (vals, &CPU.regs[rd_regn], rdb);
    510      1.1  christos 	  if (++rdb == 4)
    511      1.1  christos 	    {
    512      1.1  christos 	      rdb = 0;
    513      1.1  christos 	      rd_regn++;
    514      1.1  christos 	    }
    515      1.1  christos 	}
    516      1.1  christos     }
    517      1.1  christos   else
    518      1.1  christos     sim_io_error (sd, "XOUT: XFR device %d not supported.\n", wba);
    519      1.1  christos }
    520      1.1  christos 
    521      1.1  christos /* Handle syscall simulation.  Its ABI is specific to the GNU simulator.  */
    522      1.1  christos static void
    523      1.1  christos pru_sim_syscall (SIM_DESC sd, SIM_CPU *cpu)
    524      1.1  christos {
    525  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    526      1.1  christos   /* If someday TI confirms that the "reserved" HALT opcode fields
    527      1.1  christos      can be used for extra arguments, then maybe we can embed
    528      1.1  christos      the syscall number there.  Until then, let's use R1.  */
    529      1.1  christos   const uint32_t syscall_num = CPU.regs[1];
    530      1.1  christos   long ret;
    531      1.1  christos 
    532      1.1  christos   ret = sim_syscall (cpu, syscall_num,
    533      1.1  christos 		     CPU.regs[14], CPU.regs[15],
    534      1.1  christos 		     CPU.regs[16], CPU.regs[17]);
    535      1.1  christos   CPU.regs[14] = ret;
    536      1.1  christos }
    537      1.1  christos 
    538      1.1  christos /* Simulate one instruction.  */
    539      1.1  christos static void
    540      1.1  christos sim_step_once (SIM_DESC sd)
    541      1.1  christos {
    542      1.1  christos   SIM_CPU *cpu = STATE_CPU (sd, 0);
    543  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    544      1.1  christos   const struct pru_opcode *op;
    545      1.1  christos   uint32_t inst;
    546      1.1  christos   uint32_t _RDVAL, OP2;	/* intermediate values.  */
    547      1.1  christos   int rd_is_modified = 0;	/* RD modified and must be stored back.  */
    548      1.1  christos 
    549      1.1  christos   /* Fetch the initial instruction that we'll decode.  */
    550      1.1  christos   inst = sim_core_read_4 (cpu, PC_byteaddr, exec_map, PC_byteaddr);
    551      1.1  christos   TRACE_MEMORY (cpu, "read of insn 0x%08x from %08x", inst, PC_byteaddr);
    552      1.1  christos 
    553      1.1  christos   op = pru_find_opcode (inst);
    554      1.1  christos 
    555      1.1  christos   if (!op)
    556      1.1  christos     {
    557      1.1  christos       sim_io_eprintf (sd, "Unknown instruction 0x%04x\n", inst);
    558      1.1  christos       RAISE_SIGILL (sd);
    559      1.1  christos     }
    560      1.1  christos   else
    561      1.1  christos     {
    562      1.1  christos       TRACE_DISASM (cpu, PC_byteaddr);
    563      1.1  christos 
    564      1.1  christos       /* In multiply-only mode, R28/R29 operands are sampled on every clock
    565      1.1  christos 	 cycle.  */
    566      1.1  christos       if ((CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK) == 0)
    567      1.1  christos 	{
    568      1.1  christos 	  CPU.macregs[PRU_MACREG_OP_0] = CPU.regs[28];
    569      1.1  christos 	  CPU.macregs[PRU_MACREG_OP_1] = CPU.regs[29];
    570      1.1  christos 	}
    571      1.1  christos 
    572      1.1  christos       switch (op->type)
    573      1.1  christos 	{
    574      1.1  christos /* Helper macro to improve clarity of pru.isa.  The empty while is a
    575      1.1  christos    guard against using RD as a left-hand side value.  */
    576      1.1  christos #define RD  do { } while (0); rd_is_modified = 1; _RDVAL
    577      1.1  christos #define INSTRUCTION(NAME, ACTION)		\
    578      1.1  christos 	case prui_ ## NAME:			\
    579      1.1  christos 		ACTION;				\
    580      1.1  christos 	  break;
    581      1.1  christos #include "pru.isa"
    582      1.1  christos #undef INSTRUCTION
    583      1.1  christos #undef RD
    584      1.1  christos 
    585      1.1  christos 	default:
    586      1.1  christos 	  RAISE_SIGILL (sd);
    587      1.1  christos 	}
    588      1.1  christos 
    589      1.1  christos       if (rd_is_modified)
    590      1.1  christos 	write_regval (_RDVAL, &CPU.regs[RD_REGN], RDSEL);
    591      1.1  christos 
    592      1.1  christos       /* Don't treat r30 and r31 as regular registers, they are I/O!  */
    593      1.1  christos       CPU.regs[30] = 0;
    594      1.1  christos       CPU.regs[31] = 0;
    595      1.1  christos 
    596      1.1  christos       /* Handle PC match of loop end.  */
    597      1.1  christos       if (LOOP_IN_PROGRESS && (PC == LOOPEND))
    598      1.1  christos 	{
    599      1.1  christos 	  SIM_ASSERT (LOOPCNT > 0);
    600      1.1  christos 	  if (--LOOPCNT == 0)
    601      1.1  christos 	    LOOP_IN_PROGRESS = 0;
    602      1.1  christos 	  else
    603      1.1  christos 	    PC = LOOPTOP;
    604      1.1  christos 	}
    605      1.1  christos 
    606      1.1  christos       /* In multiply-only mode, MAC does multiplication every cycle.  */
    607      1.1  christos       if ((CPU.macregs[PRU_MACREG_MODE] & MAC_R25_MAC_MODE_MASK) == 0)
    608      1.1  christos 	{
    609      1.1  christos 	  uint64_t prod;
    610      1.1  christos 	  prod = CPU.macregs[PRU_MACREG_OP_0];
    611      1.1  christos 	  prod *= (uint64_t)CPU.macregs[PRU_MACREG_OP_1];
    612      1.1  christos 	  CPU.macregs[PRU_MACREG_PROD_L] = prod & 0xfffffffful;
    613      1.1  christos 	  CPU.macregs[PRU_MACREG_PROD_H] = prod >> 32;
    614      1.1  christos 
    615      1.1  christos 	  /* Clear the MAC accumulator when in normal mode.  */
    616      1.1  christos 	  CPU.macregs[PRU_MACREG_ACC_L] = 0;
    617      1.1  christos 	  CPU.macregs[PRU_MACREG_ACC_H] = 0;
    618      1.1  christos 	}
    619      1.1  christos 
    620      1.1  christos       /* Update cycle counts.  */
    621      1.1  christos       CPU.insts += 1;		  /* One instruction completed ...  */
    622      1.1  christos       CPU.cycles += 1;		  /* ... and it takes a single cycle.  */
    623      1.1  christos 
    624      1.1  christos       /* Account for memory access latency with a reasonable estimate.
    625      1.1  christos 	 No distinction is currently made between SRAM, DRAM and generic
    626      1.1  christos 	 L3 slaves.  */
    627      1.1  christos       if (op->type == prui_lbbo || op->type == prui_sbbo
    628      1.1  christos 	  || op->type == prui_lbco || op->type == prui_sbco)
    629      1.1  christos 	CPU.cycles += 2;
    630      1.1  christos 
    631      1.1  christos     }
    632      1.1  christos }
    633      1.1  christos 
    634      1.1  christos /* Implement standard sim_engine_run function.  */
    635      1.1  christos void
    636      1.1  christos sim_engine_run (SIM_DESC sd,
    637      1.1  christos 		int next_cpu_nr, /* ignore  */
    638      1.1  christos 		int nr_cpus, /* ignore  */
    639      1.1  christos 		int siggnal) /* ignore  */
    640      1.1  christos {
    641      1.1  christos   while (1)
    642      1.1  christos     {
    643      1.1  christos       sim_step_once (sd);
    644      1.1  christos       if (sim_events_tick (sd))
    645      1.1  christos 	sim_events_process (sd);
    646      1.1  christos     }
    647      1.1  christos }
    648      1.1  christos 
    649      1.1  christos 
    650      1.1  christos /* Implement callback for standard CPU_PC_FETCH routine.  */
    651      1.1  christos static sim_cia
    652      1.1  christos pru_pc_get (sim_cpu *cpu)
    653      1.1  christos {
    654  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    655  1.1.1.3  christos 
    656      1.1  christos   /* Present PC as byte address.  */
    657  1.1.1.3  christos   return imem_wordaddr_to_byteaddr (cpu, pru_cpu->pc);
    658      1.1  christos }
    659      1.1  christos 
    660      1.1  christos /* Implement callback for standard CPU_PC_STORE routine.  */
    661      1.1  christos static void
    662      1.1  christos pru_pc_set (sim_cpu *cpu, sim_cia pc)
    663      1.1  christos {
    664  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    665  1.1.1.3  christos 
    666      1.1  christos   /* PC given as byte address.  */
    667  1.1.1.3  christos   pru_cpu->pc = imem_byteaddr_to_wordaddr (cpu, pc);
    668      1.1  christos }
    669      1.1  christos 
    670      1.1  christos 
    671      1.1  christos /* Implement callback for standard CPU_REG_STORE routine.  */
    672      1.1  christos static int
    673  1.1.1.2  christos pru_store_register (SIM_CPU *cpu, int rn, const void *memory, int length)
    674      1.1  christos {
    675  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    676  1.1.1.3  christos 
    677      1.1  christos   if (rn < NUM_REGS && rn >= 0)
    678      1.1  christos     {
    679      1.1  christos       if (length == 4)
    680      1.1  christos 	{
    681      1.1  christos 	  /* Misalignment safe.  */
    682      1.1  christos 	  long ival = pru_extract_unsigned_integer (memory, 4);
    683      1.1  christos 	  if (rn < 32)
    684      1.1  christos 	    CPU.regs[rn] = ival;
    685      1.1  christos 	  else
    686      1.1  christos 	    pru_pc_set (cpu, ival);
    687      1.1  christos 	  return 4;
    688      1.1  christos 	}
    689      1.1  christos       else
    690      1.1  christos 	return 0;
    691      1.1  christos     }
    692      1.1  christos   else
    693      1.1  christos     return 0;
    694      1.1  christos }
    695      1.1  christos 
    696      1.1  christos /* Implement callback for standard CPU_REG_FETCH routine.  */
    697      1.1  christos static int
    698  1.1.1.2  christos pru_fetch_register (SIM_CPU *cpu, int rn, void *memory, int length)
    699      1.1  christos {
    700  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    701      1.1  christos   long ival;
    702      1.1  christos 
    703      1.1  christos   if (rn < NUM_REGS && rn >= 0)
    704      1.1  christos     {
    705      1.1  christos       if (length == 4)
    706      1.1  christos 	{
    707      1.1  christos 	  if (rn < 32)
    708      1.1  christos 	    ival = CPU.regs[rn];
    709      1.1  christos 	  else
    710      1.1  christos 	    ival = pru_pc_get (cpu);
    711      1.1  christos 
    712      1.1  christos 	  /* Misalignment-safe.  */
    713      1.1  christos 	  pru_store_unsigned_integer (memory, 4, ival);
    714      1.1  christos 	  return 4;
    715      1.1  christos 	}
    716      1.1  christos       else
    717      1.1  christos 	return 0;
    718      1.1  christos     }
    719      1.1  christos   else
    720      1.1  christos     return 0;
    721      1.1  christos }
    722      1.1  christos 
    723      1.1  christos static void
    724      1.1  christos free_state (SIM_DESC sd)
    725      1.1  christos {
    726      1.1  christos   if (STATE_MODULES (sd) != NULL)
    727      1.1  christos     sim_module_uninstall (sd);
    728      1.1  christos   sim_cpu_free_all (sd);
    729      1.1  christos   sim_state_free (sd);
    730      1.1  christos }
    731      1.1  christos 
    732      1.1  christos /* Declare the PRU option handler.  */
    733      1.1  christos static DECLARE_OPTION_HANDLER (pru_option_handler);
    734      1.1  christos 
    735      1.1  christos /* Implement the PRU option handler.  */
    736      1.1  christos static SIM_RC
    737      1.1  christos pru_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, char *arg,
    738      1.1  christos 		    int is_command)
    739      1.1  christos {
    740      1.1  christos   switch (opt)
    741      1.1  christos     {
    742      1.1  christos     case OPTION_ERROR_NULL_DEREF:
    743      1.1  christos       abort_on_dmem_zero_access = TRUE;
    744      1.1  christos       return SIM_RC_OK;
    745      1.1  christos 
    746      1.1  christos     default:
    747      1.1  christos       sim_io_eprintf (sd, "Unknown PRU option %d\n", opt);
    748      1.1  christos       return SIM_RC_FAIL;
    749      1.1  christos     }
    750      1.1  christos }
    751      1.1  christos 
    752      1.1  christos /* List of PRU-specific options.  */
    753      1.1  christos static const OPTION pru_options[] =
    754      1.1  christos {
    755      1.1  christos   { {"error-null-deref", no_argument, NULL, OPTION_ERROR_NULL_DEREF},
    756      1.1  christos       '\0', NULL, "Trap any access to DMEM address zero",
    757      1.1  christos       pru_option_handler, NULL },
    758      1.1  christos 
    759      1.1  christos   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
    760      1.1  christos };
    761      1.1  christos 
    762      1.1  christos /* Implement standard sim_open function.  */
    763      1.1  christos SIM_DESC
    764      1.1  christos sim_open (SIM_OPEN_KIND kind, host_callback *cb,
    765      1.1  christos 	  struct bfd *abfd, char * const *argv)
    766      1.1  christos {
    767      1.1  christos   int i;
    768      1.1  christos   char c;
    769      1.1  christos   SIM_DESC sd = sim_state_alloc (kind, cb);
    770      1.1  christos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
    771      1.1  christos 
    772  1.1.1.2  christos   /* Set default options before parsing user options.  */
    773  1.1.1.2  christos   current_alignment = STRICT_ALIGNMENT;
    774  1.1.1.2  christos   current_target_byte_order = BFD_ENDIAN_LITTLE;
    775  1.1.1.2  christos 
    776      1.1  christos   /* The cpu data is kept in a separately allocated chunk of memory.  */
    777  1.1.1.3  christos   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct pru_regset)) != SIM_RC_OK)
    778      1.1  christos     {
    779      1.1  christos       free_state (sd);
    780      1.1  christos       return 0;
    781      1.1  christos     }
    782      1.1  christos 
    783      1.1  christos   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
    784      1.1  christos     {
    785      1.1  christos       free_state (sd);
    786      1.1  christos       return 0;
    787      1.1  christos     }
    788      1.1  christos   sim_add_option_table (sd, NULL, pru_options);
    789      1.1  christos 
    790      1.1  christos   /* The parser will print an error message for us, so we silently return.  */
    791      1.1  christos   if (sim_parse_args (sd, argv) != SIM_RC_OK)
    792      1.1  christos     {
    793      1.1  christos       free_state (sd);
    794      1.1  christos       return 0;
    795      1.1  christos     }
    796      1.1  christos 
    797      1.1  christos   /* Check for/establish a reference program image.  */
    798  1.1.1.2  christos   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
    799      1.1  christos     {
    800      1.1  christos       free_state (sd);
    801      1.1  christos       return 0;
    802      1.1  christos     }
    803      1.1  christos 
    804      1.1  christos   /* Configure/verify the target byte order and other runtime
    805      1.1  christos      configuration options.  */
    806      1.1  christos   if (sim_config (sd) != SIM_RC_OK)
    807      1.1  christos     {
    808      1.1  christos       sim_module_uninstall (sd);
    809      1.1  christos       return 0;
    810      1.1  christos     }
    811      1.1  christos 
    812      1.1  christos   if (sim_post_argv_init (sd) != SIM_RC_OK)
    813      1.1  christos     {
    814      1.1  christos       /* Uninstall the modules to avoid memory leaks,
    815      1.1  christos 	 file descriptor leaks, etc.  */
    816      1.1  christos       sim_module_uninstall (sd);
    817      1.1  christos       return 0;
    818      1.1  christos     }
    819      1.1  christos 
    820      1.1  christos   /* CPU specific initialization.  */
    821      1.1  christos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    822      1.1  christos     {
    823      1.1  christos       SIM_CPU *cpu = STATE_CPU (sd, i);
    824      1.1  christos 
    825      1.1  christos       CPU_REG_STORE (cpu) = pru_store_register;
    826      1.1  christos       CPU_REG_FETCH (cpu) = pru_fetch_register;
    827      1.1  christos       CPU_PC_FETCH (cpu) = pru_pc_get;
    828      1.1  christos       CPU_PC_STORE (cpu) = pru_pc_set;
    829      1.1  christos 
    830      1.1  christos       set_initial_gprs (cpu);
    831      1.1  christos     }
    832      1.1  christos 
    833      1.1  christos   /* Allocate external memory if none specified by user.
    834      1.1  christos      Use address 4 here in case the user wanted address 0 unmapped.  */
    835      1.1  christos   if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
    836      1.1  christos     {
    837      1.1  christos       sim_do_commandf (sd, "memory-region 0x%x,0x%x",
    838      1.1  christos 		       0,
    839      1.1  christos 		       DMEM_DEFAULT_SIZE);
    840      1.1  christos     }
    841      1.1  christos   if (sim_core_read_buffer (sd, NULL, read_map, &c, IMEM_ADDR_DEFAULT, 1) == 0)
    842      1.1  christos     {
    843      1.1  christos       sim_do_commandf (sd, "memory-region 0x%x,0x%x",
    844      1.1  christos 		       IMEM_ADDR_DEFAULT,
    845      1.1  christos 		       IMEM_DEFAULT_SIZE);
    846      1.1  christos     }
    847      1.1  christos 
    848      1.1  christos   return sd;
    849      1.1  christos }
    850      1.1  christos 
    851      1.1  christos /* Implement standard sim_create_inferior function.  */
    852      1.1  christos SIM_RC
    853      1.1  christos sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
    854      1.1  christos 		     char * const *argv, char * const *env)
    855      1.1  christos {
    856      1.1  christos   SIM_CPU *cpu = STATE_CPU (sd, 0);
    857  1.1.1.3  christos   struct pru_regset *pru_cpu = PRU_SIM_CPU (cpu);
    858  1.1.1.2  christos   host_callback *cb = STATE_CALLBACK (sd);
    859  1.1.1.3  christos   bfd_vma addr;
    860      1.1  christos 
    861      1.1  christos   addr = bfd_get_start_address (prog_bfd);
    862      1.1  christos 
    863      1.1  christos   sim_pc_set (cpu, addr);
    864      1.1  christos   PC_ADDR_SPACE_MARKER = addr & ~IMEM_ADDR_MASK;
    865      1.1  christos 
    866      1.1  christos   /* Standalone mode (i.e. `run`) will take care of the argv for us in
    867      1.1  christos      sim_open () -> sim_parse_args ().  But in debug mode (i.e. 'target sim'
    868      1.1  christos      with `gdb`), we need to handle it because the user can change the
    869      1.1  christos      argv on the fly via gdb's 'run'.  */
    870      1.1  christos   if (STATE_PROG_ARGV (sd) != argv)
    871      1.1  christos     {
    872      1.1  christos       freeargv (STATE_PROG_ARGV (sd));
    873      1.1  christos       STATE_PROG_ARGV (sd) = dupargv (argv);
    874      1.1  christos     }
    875      1.1  christos 
    876  1.1.1.2  christos   if (STATE_PROG_ENVP (sd) != env)
    877  1.1.1.2  christos     {
    878  1.1.1.2  christos       freeargv (STATE_PROG_ENVP (sd));
    879  1.1.1.2  christos       STATE_PROG_ENVP (sd) = dupargv (env);
    880  1.1.1.2  christos     }
    881  1.1.1.2  christos 
    882  1.1.1.2  christos   cb->argv = STATE_PROG_ARGV (sd);
    883  1.1.1.2  christos   cb->envp = STATE_PROG_ENVP (sd);
    884  1.1.1.2  christos 
    885      1.1  christos   return SIM_RC_OK;
    886      1.1  christos }
    887