xref: /netbsd-src/external/gpl3/gdb/dist/sim/rx/mem.c (revision 1f4e7eb9e5e045e008f1894823a8e4e6c9f46890)
14e98e3e1Schristos /* mem.c --- memory for RX simulator.
24e98e3e1Schristos 
3*1f4e7eb9Schristos Copyright (C) 2005-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 /* This slows down the simulator and we get some false negatives from
254e98e3e1Schristos    gcc, like when it uses a long-sized hole to hold a byte-sized
264e98e3e1Schristos    variable, knowing that it doesn't care about the other bits.  But,
274e98e3e1Schristos    if you need to track down a read-from-unitialized bug, set this to
284e98e3e1Schristos    1.  */
294e98e3e1Schristos #define RDCHECK 0
304e98e3e1Schristos 
314e98e3e1Schristos #include <stdio.h>
324e98e3e1Schristos #include <stdlib.h>
334e98e3e1Schristos #include <string.h>
344e98e3e1Schristos 
354e98e3e1Schristos #include "opcode/rx.h"
364e98e3e1Schristos #include "mem.h"
374e98e3e1Schristos #include "cpu.h"
384e98e3e1Schristos #include "syscalls.h"
394e98e3e1Schristos #include "misc.h"
404e98e3e1Schristos #include "err.h"
414e98e3e1Schristos 
424e98e3e1Schristos #define L1_BITS  (10)
434e98e3e1Schristos #define L2_BITS  (10)
444e98e3e1Schristos #define OFF_BITS PAGE_BITS
454e98e3e1Schristos 
464e98e3e1Schristos #define L1_LEN  (1 << L1_BITS)
474e98e3e1Schristos #define L2_LEN  (1 << L2_BITS)
484e98e3e1Schristos #define OFF_LEN (1 << OFF_BITS)
494e98e3e1Schristos 
504e98e3e1Schristos static unsigned char **pt[L1_LEN];
514e98e3e1Schristos static unsigned char **ptr[L1_LEN];
524e98e3e1Schristos static RX_Opcode_Decoded ***ptdc[L1_LEN];
534e98e3e1Schristos 
544e98e3e1Schristos /* [ get=0/put=1 ][ byte size ] */
554e98e3e1Schristos static unsigned int mem_counters[2][5];
564e98e3e1Schristos 
574e98e3e1Schristos #define COUNT(isput,bytes)                                      \
584e98e3e1Schristos   if (verbose && enable_counting) mem_counters[isput][bytes]++
594e98e3e1Schristos 
604e98e3e1Schristos void
614e98e3e1Schristos init_mem (void)
624e98e3e1Schristos {
634e98e3e1Schristos   int i, j;
644e98e3e1Schristos 
654e98e3e1Schristos   for (i = 0; i < L1_LEN; i++)
664e98e3e1Schristos     if (pt[i])
674e98e3e1Schristos       {
684e98e3e1Schristos 	for (j = 0; j < L2_LEN; j++)
694e98e3e1Schristos 	  if (pt[i][j])
704e98e3e1Schristos 	    free (pt[i][j]);
714e98e3e1Schristos 	free (pt[i]);
724e98e3e1Schristos       }
734e98e3e1Schristos   memset (pt, 0, sizeof (pt));
744e98e3e1Schristos   memset (ptr, 0, sizeof (ptr));
754e98e3e1Schristos   memset (mem_counters, 0, sizeof (mem_counters));
764e98e3e1Schristos }
774e98e3e1Schristos 
784e98e3e1Schristos unsigned char *
794e98e3e1Schristos rx_mem_ptr (unsigned long address, enum mem_ptr_action action)
804e98e3e1Schristos {
814e98e3e1Schristos   int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
824e98e3e1Schristos   int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
834e98e3e1Schristos   int pto = address & ((1 << OFF_BITS) - 1);
844e98e3e1Schristos 
854e98e3e1Schristos   if (address == 0)
864e98e3e1Schristos     execution_error (SIM_ERR_NULL_POINTER_DEREFERENCE, 0);
874e98e3e1Schristos 
884e98e3e1Schristos   if (pt[pt1] == 0)
894e98e3e1Schristos     {
904e98e3e1Schristos       pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
914e98e3e1Schristos       ptr[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
924e98e3e1Schristos       ptdc[pt1] = (RX_Opcode_Decoded ***) calloc (L2_LEN, sizeof (RX_Opcode_Decoded ***));
934e98e3e1Schristos     }
944e98e3e1Schristos   if (pt[pt1][pt2] == 0)
954e98e3e1Schristos     {
964e98e3e1Schristos       if (action == MPA_READING)
974e98e3e1Schristos 	execution_error (SIM_ERR_READ_UNWRITTEN_PAGES, address);
984e98e3e1Schristos 
994e98e3e1Schristos       pt[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
1004e98e3e1Schristos       ptr[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
1014e98e3e1Schristos       ptdc[pt1][pt2] = (RX_Opcode_Decoded **) calloc (OFF_LEN, sizeof(RX_Opcode_Decoded *));
1024e98e3e1Schristos     }
1034e98e3e1Schristos   else if (action == MPA_READING
1044e98e3e1Schristos 	   && ptr[pt1][pt2][pto] == MC_UNINIT)
1054e98e3e1Schristos     execution_error (SIM_ERR_READ_UNWRITTEN_BYTES, address);
1064e98e3e1Schristos 
1074e98e3e1Schristos   if (action == MPA_WRITING)
1084e98e3e1Schristos     {
1094e98e3e1Schristos       int pto_dc;
1104e98e3e1Schristos       if (ptr[pt1][pt2][pto] == MC_PUSHED_PC)
1114e98e3e1Schristos 	execution_error (SIM_ERR_CORRUPT_STACK, address);
1124e98e3e1Schristos       ptr[pt1][pt2][pto] = MC_DATA;
1134e98e3e1Schristos 
1144e98e3e1Schristos       /* The instruction decoder doesn't store it's decoded instructions
1154e98e3e1Schristos          at word swapped addresses.  Therefore, when clearing the decode
1164e98e3e1Schristos 	 cache, we have to account for that here.  */
1174e98e3e1Schristos       pto_dc = pto ^ (rx_big_endian ? 3 : 0);
1184e98e3e1Schristos       if (ptdc[pt1][pt2][pto_dc])
1194e98e3e1Schristos 	{
1204e98e3e1Schristos 	  free (ptdc[pt1][pt2][pto_dc]);
1214e98e3e1Schristos 	  ptdc[pt1][pt2][pto_dc] = NULL;
1224e98e3e1Schristos 	}
1234e98e3e1Schristos     }
1244e98e3e1Schristos 
1254e98e3e1Schristos   if (action == MPA_CONTENT_TYPE)
1264e98e3e1Schristos     return (unsigned char *) (ptr[pt1][pt2] + pto);
1274e98e3e1Schristos 
1284e98e3e1Schristos   if (action == MPA_DECODE_CACHE)
1294e98e3e1Schristos     return (unsigned char *) (ptdc[pt1][pt2] + pto);
1304e98e3e1Schristos 
1314e98e3e1Schristos   return pt[pt1][pt2] + pto;
1324e98e3e1Schristos }
1334e98e3e1Schristos 
1344e98e3e1Schristos RX_Opcode_Decoded **
1354e98e3e1Schristos rx_mem_decode_cache (unsigned long address)
1364e98e3e1Schristos {
1374e98e3e1Schristos   return (RX_Opcode_Decoded **) rx_mem_ptr (address, MPA_DECODE_CACHE);
1384e98e3e1Schristos }
1394e98e3e1Schristos 
1404e98e3e1Schristos static inline int
1414e98e3e1Schristos is_reserved_address (unsigned int address)
1424e98e3e1Schristos {
1434e98e3e1Schristos   return (address >= 0x00020000 && address < 0x00080000)
1444e98e3e1Schristos     ||   (address >= 0x00100000 && address < 0x01000000)
1454e98e3e1Schristos     ||   (address >= 0x08000000 && address < 0xff000000);
1464e98e3e1Schristos }
1474e98e3e1Schristos 
1484e98e3e1Schristos static void
1494e98e3e1Schristos used (int rstart, int i, int j)
1504e98e3e1Schristos {
1514e98e3e1Schristos   int rend = i << (L2_BITS + OFF_BITS);
1524e98e3e1Schristos   rend += j << OFF_BITS;
1534e98e3e1Schristos   if (rstart == 0xe0000 && rend == 0xe1000)
1544e98e3e1Schristos     return;
1554e98e3e1Schristos   printf ("mem:   %08x - %08x (%dk bytes)\n", rstart, rend - 1,
1564e98e3e1Schristos 	  (rend - rstart) / 1024);
1574e98e3e1Schristos }
1584e98e3e1Schristos 
1594e98e3e1Schristos static char *
1604e98e3e1Schristos mcs (int isput, int bytes)
1614e98e3e1Schristos {
1624e98e3e1Schristos   return comma (mem_counters[isput][bytes]);
1634e98e3e1Schristos }
1644e98e3e1Schristos 
1654e98e3e1Schristos void
1664b169a6bSchristos mem_usage_stats (void)
1674e98e3e1Schristos {
1684e98e3e1Schristos   int i, j;
1694e98e3e1Schristos   int rstart = 0;
1704e98e3e1Schristos   int pending = 0;
1714e98e3e1Schristos 
1724e98e3e1Schristos   for (i = 0; i < L1_LEN; i++)
1734e98e3e1Schristos     if (pt[i])
1744e98e3e1Schristos       {
1754e98e3e1Schristos 	for (j = 0; j < L2_LEN; j++)
1764e98e3e1Schristos 	  if (pt[i][j])
1774e98e3e1Schristos 	    {
1784e98e3e1Schristos 	      if (!pending)
1794e98e3e1Schristos 		{
1804e98e3e1Schristos 		  pending = 1;
1814e98e3e1Schristos 		  rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
1824e98e3e1Schristos 		}
1834e98e3e1Schristos 	    }
1844e98e3e1Schristos 	  else if (pending)
1854e98e3e1Schristos 	    {
1864e98e3e1Schristos 	      pending = 0;
1874e98e3e1Schristos 	      used (rstart, i, j);
1884e98e3e1Schristos 	    }
1894e98e3e1Schristos       }
1904e98e3e1Schristos     else
1914e98e3e1Schristos       {
1924e98e3e1Schristos 	if (pending)
1934e98e3e1Schristos 	  {
1944e98e3e1Schristos 	    pending = 0;
1954e98e3e1Schristos 	    used (rstart, i, 0);
1964e98e3e1Schristos 	  }
1974e98e3e1Schristos       }
1984e98e3e1Schristos   /*       mem foo: 123456789012 123456789012 123456789012 123456789012
1994e98e3e1Schristos             123456789012 */
2004e98e3e1Schristos   printf ("                 byte        short        3byte         long"
2014e98e3e1Schristos           "       opcode\n");
2024e98e3e1Schristos   if (verbose > 1)
2034e98e3e1Schristos     {
2044e98e3e1Schristos       /* Only use comma separated numbers when being very verbose.
2054e98e3e1Schristos 	 Comma separated numbers are hard to parse in awk scripts.  */
2064e98e3e1Schristos       printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
2074e98e3e1Schristos 	      mcs (0, 3), mcs (0, 4), mcs (0, 0));
2084e98e3e1Schristos       printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
2094e98e3e1Schristos 	      mcs (1, 3), mcs (1, 4));
2104e98e3e1Schristos     }
2114e98e3e1Schristos   else
2124e98e3e1Schristos     {
2134e98e3e1Schristos       printf ("mem get: %12u %12u %12u %12u %12u\n",
2144e98e3e1Schristos 	      mem_counters[0][1], mem_counters[0][2],
2154e98e3e1Schristos 	      mem_counters[0][3], mem_counters[0][4],
2164e98e3e1Schristos 	      mem_counters[0][0]);
2174e98e3e1Schristos       printf ("mem put: %12u %12u %12u %12u\n",
2184e98e3e1Schristos 	      mem_counters [1][1], mem_counters [1][2],
2194e98e3e1Schristos 	      mem_counters [1][3], mem_counters [1][4]);
2204e98e3e1Schristos     }
2214e98e3e1Schristos }
2224e98e3e1Schristos 
2234e98e3e1Schristos unsigned long
2244e98e3e1Schristos mem_usage_cycles (void)
2254e98e3e1Schristos {
2264e98e3e1Schristos   unsigned long rv = mem_counters[0][0];
2274e98e3e1Schristos   rv += mem_counters[0][1] * 1;
2284e98e3e1Schristos   rv += mem_counters[0][2] * 2;
2294e98e3e1Schristos   rv += mem_counters[0][3] * 3;
2304e98e3e1Schristos   rv += mem_counters[0][4] * 4;
2314e98e3e1Schristos   rv += mem_counters[1][1] * 1;
2324e98e3e1Schristos   rv += mem_counters[1][2] * 2;
2334e98e3e1Schristos   rv += mem_counters[1][3] * 3;
2344e98e3e1Schristos   rv += mem_counters[1][4] * 4;
2354e98e3e1Schristos   return rv;
2364e98e3e1Schristos }
2374e98e3e1Schristos 
2384e98e3e1Schristos static int tpr = 0;
2394e98e3e1Schristos static void
2404e98e3e1Schristos s (int address, char *dir)
2414e98e3e1Schristos {
2424e98e3e1Schristos   if (tpr == 0)
2434e98e3e1Schristos     printf ("MEM[%08x] %s", address, dir);
2444e98e3e1Schristos   tpr++;
2454e98e3e1Schristos }
2464e98e3e1Schristos 
2474e98e3e1Schristos #define S(d) if (trace) s(address, d)
2484e98e3e1Schristos static void
2494b169a6bSchristos e (void)
2504e98e3e1Schristos {
2514e98e3e1Schristos   if (!trace)
2524e98e3e1Schristos     return;
2534e98e3e1Schristos   tpr--;
2544e98e3e1Schristos   if (tpr == 0)
2554e98e3e1Schristos     printf ("\n");
2564e98e3e1Schristos }
2574e98e3e1Schristos 
2584e98e3e1Schristos static char
2594e98e3e1Schristos mtypec (int address)
2604e98e3e1Schristos {
2614e98e3e1Schristos   unsigned char *cp = rx_mem_ptr (address, MPA_CONTENT_TYPE);
2624e98e3e1Schristos   return "udp"[*cp];
2634e98e3e1Schristos }
2644e98e3e1Schristos 
2654e98e3e1Schristos #define E() if (trace) e()
2664e98e3e1Schristos 
2674b169a6bSchristos static void
2684e98e3e1Schristos mem_put_byte (unsigned int address, unsigned char value)
2694e98e3e1Schristos {
2704e98e3e1Schristos   unsigned char *m;
2714e98e3e1Schristos   char tc = ' ';
2724e98e3e1Schristos 
2734e98e3e1Schristos   if (trace)
2744e98e3e1Schristos     tc = mtypec (address);
2754e98e3e1Schristos   m = rx_mem_ptr (address, MPA_WRITING);
2764e98e3e1Schristos   if (trace)
2774e98e3e1Schristos     printf (" %02x%c", value, tc);
2784e98e3e1Schristos   *m = value;
2794e98e3e1Schristos   switch (address)
2804e98e3e1Schristos     {
2814e98e3e1Schristos     case 0x0008c02a: /* PA.DR */
2824e98e3e1Schristos      {
2834e98e3e1Schristos 	static int old_led = -1;
2844e98e3e1Schristos 	int red_on = 0;
2854e98e3e1Schristos 	int i;
2864e98e3e1Schristos 
2874e98e3e1Schristos 	if (old_led != value)
2884e98e3e1Schristos 	  {
2894e98e3e1Schristos 	    fputs (" ", stdout);
2904e98e3e1Schristos 	    for (i = 0; i < 8; i++)
2914e98e3e1Schristos 	      if (value & (1 << i))
2924e98e3e1Schristos 		{
2934e98e3e1Schristos 		  if (! red_on)
2944e98e3e1Schristos 		    {
2954e98e3e1Schristos 		      fputs ("\033[31m", stdout);
2964e98e3e1Schristos 		      red_on = 1;
2974e98e3e1Schristos 		    }
2984e98e3e1Schristos 		  fputs (" @", stdout);
2994e98e3e1Schristos 		}
3004e98e3e1Schristos 	      else
3014e98e3e1Schristos 		{
3024e98e3e1Schristos 		  if (red_on)
3034e98e3e1Schristos 		    {
3044e98e3e1Schristos 		      fputs ("\033[0m", stdout);
3054e98e3e1Schristos 		      red_on = 0;
3064e98e3e1Schristos 		    }
3074e98e3e1Schristos 		  fputs (" *", stdout);
3084e98e3e1Schristos 		}
3094e98e3e1Schristos 
3104e98e3e1Schristos 	    if (red_on)
3114e98e3e1Schristos 	      fputs ("\033[0m", stdout);
3124e98e3e1Schristos 
3134e98e3e1Schristos 	    fputs ("\r", stdout);
3144e98e3e1Schristos 	    fflush (stdout);
3154e98e3e1Schristos 	    old_led = value;
3164e98e3e1Schristos 	  }
3174e98e3e1Schristos       }
3184e98e3e1Schristos       break;
3194e98e3e1Schristos 
3204b169a6bSchristos #ifdef WITH_PROFILE
3214e98e3e1Schristos     case 0x0008c02b: /* PB.DR */
3224e98e3e1Schristos       {
3234e98e3e1Schristos 	if (value == 0)
3244e98e3e1Schristos 	  halt_pipeline_stats ();
3254e98e3e1Schristos 	else
3264e98e3e1Schristos 	  reset_pipeline_stats ();
327*1f4e7eb9Schristos 	break;
3284e98e3e1Schristos       }
3294e98e3e1Schristos #endif
3304e98e3e1Schristos 
3314e98e3e1Schristos     case 0x00088263: /* SCI4.TDR */
3324e98e3e1Schristos       {
3334e98e3e1Schristos 	static int pending_exit = 0;
3344e98e3e1Schristos 	if (pending_exit == 2)
3354e98e3e1Schristos 	  {
3364e98e3e1Schristos 	    step_result = RX_MAKE_EXITED(value);
3374e98e3e1Schristos 	    longjmp (decode_jmp_buf, 1);
3384e98e3e1Schristos 	  }
3394e98e3e1Schristos 	else if (value == 3)
3404e98e3e1Schristos 	  pending_exit ++;
3414e98e3e1Schristos 	else
3424e98e3e1Schristos 	  pending_exit = 0;
3434e98e3e1Schristos 
3444e98e3e1Schristos 	putchar(value);
3454e98e3e1Schristos       }
3464e98e3e1Schristos       break;
3474e98e3e1Schristos 
3484e98e3e1Schristos     default:
3494e98e3e1Schristos       if (is_reserved_address (address))
3504e98e3e1Schristos 	generate_access_exception ();
3514e98e3e1Schristos     }
3524e98e3e1Schristos }
3534e98e3e1Schristos 
3544e98e3e1Schristos void
3554e98e3e1Schristos mem_put_qi (int address, unsigned char value)
3564e98e3e1Schristos {
3574e98e3e1Schristos   S ("<=");
3584e98e3e1Schristos   mem_put_byte (address, value & 0xff);
3594e98e3e1Schristos   E ();
3604e98e3e1Schristos   COUNT (1, 1);
3614e98e3e1Schristos }
3624e98e3e1Schristos 
3634e98e3e1Schristos #ifdef CYCLE_ACCURATE
3644e98e3e1Schristos static int tpu_base;
3654e98e3e1Schristos #endif
3664e98e3e1Schristos 
3674e98e3e1Schristos void
3684e98e3e1Schristos mem_put_hi (int address, unsigned short value)
3694e98e3e1Schristos {
3704e98e3e1Schristos   S ("<=");
3714e98e3e1Schristos   switch (address)
3724e98e3e1Schristos     {
3734e98e3e1Schristos #ifdef CYCLE_ACCURATE
3744e98e3e1Schristos     case 0x00088126: /* TPU1.TCNT */
3754e98e3e1Schristos       tpu_base = regs.cycle_count;
3764e98e3e1Schristos       break;
3774e98e3e1Schristos     case 0x00088136: /* TPU2.TCNT */
3784e98e3e1Schristos       tpu_base = regs.cycle_count;
3794e98e3e1Schristos       break;
3804e98e3e1Schristos #endif
3814e98e3e1Schristos     default:
3824e98e3e1Schristos       if (rx_big_endian)
3834e98e3e1Schristos 	{
3844e98e3e1Schristos 	  mem_put_byte (address, value >> 8);
3854e98e3e1Schristos 	  mem_put_byte (address + 1, value & 0xff);
3864e98e3e1Schristos 	}
3874e98e3e1Schristos       else
3884e98e3e1Schristos 	{
3894e98e3e1Schristos 	  mem_put_byte (address, value & 0xff);
3904e98e3e1Schristos 	  mem_put_byte (address + 1, value >> 8);
3914e98e3e1Schristos 	}
3924e98e3e1Schristos     }
3934e98e3e1Schristos   E ();
3944e98e3e1Schristos   COUNT (1, 2);
3954e98e3e1Schristos }
3964e98e3e1Schristos 
3974e98e3e1Schristos void
3984e98e3e1Schristos mem_put_psi (int address, unsigned long value)
3994e98e3e1Schristos {
4004e98e3e1Schristos   S ("<=");
4014e98e3e1Schristos   if (rx_big_endian)
4024e98e3e1Schristos     {
4034e98e3e1Schristos       mem_put_byte (address, value >> 16);
4044e98e3e1Schristos       mem_put_byte (address + 1, (value >> 8) & 0xff);
4054e98e3e1Schristos       mem_put_byte (address + 2, value & 0xff);
4064e98e3e1Schristos     }
4074e98e3e1Schristos   else
4084e98e3e1Schristos     {
4094e98e3e1Schristos       mem_put_byte (address, value & 0xff);
4104e98e3e1Schristos       mem_put_byte (address + 1, (value >> 8) & 0xff);
4114e98e3e1Schristos       mem_put_byte (address + 2, value >> 16);
4124e98e3e1Schristos     }
4134e98e3e1Schristos   E ();
4144e98e3e1Schristos   COUNT (1, 3);
4154e98e3e1Schristos }
4164e98e3e1Schristos 
4174e98e3e1Schristos void
4184e98e3e1Schristos mem_put_si (int address, unsigned long value)
4194e98e3e1Schristos {
4204e98e3e1Schristos   S ("<=");
4214e98e3e1Schristos   if (rx_big_endian)
4224e98e3e1Schristos     {
4234e98e3e1Schristos       mem_put_byte (address + 0, (value >> 24) & 0xff);
4244e98e3e1Schristos       mem_put_byte (address + 1, (value >> 16) & 0xff);
4254e98e3e1Schristos       mem_put_byte (address + 2, (value >> 8) & 0xff);
4264e98e3e1Schristos       mem_put_byte (address + 3, value & 0xff);
4274e98e3e1Schristos     }
4284e98e3e1Schristos   else
4294e98e3e1Schristos     {
4304e98e3e1Schristos       mem_put_byte (address + 0, value & 0xff);
4314e98e3e1Schristos       mem_put_byte (address + 1, (value >> 8) & 0xff);
4324e98e3e1Schristos       mem_put_byte (address + 2, (value >> 16) & 0xff);
4334e98e3e1Schristos       mem_put_byte (address + 3, (value >> 24) & 0xff);
4344e98e3e1Schristos     }
4354e98e3e1Schristos   E ();
4364e98e3e1Schristos   COUNT (1, 4);
4374e98e3e1Schristos }
4384e98e3e1Schristos 
4394e98e3e1Schristos void
4404b169a6bSchristos mem_put_blk (int address, void *bufptr_void, int nbytes)
4414e98e3e1Schristos {
4424b169a6bSchristos   unsigned char *bufptr = (unsigned char *) bufptr_void;
4434b169a6bSchristos 
4444e98e3e1Schristos   S ("<=");
4454e98e3e1Schristos   if (enable_counting)
4464e98e3e1Schristos     mem_counters[1][1] += nbytes;
4474e98e3e1Schristos   while (nbytes--)
4484b169a6bSchristos     mem_put_byte (address++, *bufptr++);
4494e98e3e1Schristos   E ();
4504e98e3e1Schristos }
4514e98e3e1Schristos 
4524e98e3e1Schristos unsigned char
4534e98e3e1Schristos mem_get_pc (int address)
4544e98e3e1Schristos {
4554e98e3e1Schristos   unsigned char *m = rx_mem_ptr (address, MPA_READING);
4564e98e3e1Schristos   COUNT (0, 0);
4574e98e3e1Schristos   return *m;
4584e98e3e1Schristos }
4594e98e3e1Schristos 
4604e98e3e1Schristos static unsigned char
4614e98e3e1Schristos mem_get_byte (unsigned int address)
4624e98e3e1Schristos {
4634e98e3e1Schristos   unsigned char *m;
4644e98e3e1Schristos 
4654e98e3e1Schristos   S ("=>");
4664e98e3e1Schristos   m = rx_mem_ptr (address, MPA_READING);
4674e98e3e1Schristos   switch (address)
4684e98e3e1Schristos     {
4694e98e3e1Schristos     case 0x00088264: /* SCI4.SSR */
4704e98e3e1Schristos       E();
4714e98e3e1Schristos       return 0x04; /* transmitter empty */
4724e98e3e1Schristos       break;
4734e98e3e1Schristos     default:
4744e98e3e1Schristos       if (trace)
4754e98e3e1Schristos 	printf (" %02x%c", *m, mtypec (address));
4764e98e3e1Schristos       if (is_reserved_address (address))
4774e98e3e1Schristos 	generate_access_exception ();
4784e98e3e1Schristos       break;
4794e98e3e1Schristos     }
4804e98e3e1Schristos   E ();
4814e98e3e1Schristos   return *m;
4824e98e3e1Schristos }
4834e98e3e1Schristos 
4844e98e3e1Schristos unsigned char
4854e98e3e1Schristos mem_get_qi (int address)
4864e98e3e1Schristos {
4874e98e3e1Schristos   unsigned char rv;
4884e98e3e1Schristos   S ("=>");
4894e98e3e1Schristos   rv = mem_get_byte (address);
4904e98e3e1Schristos   COUNT (0, 1);
4914e98e3e1Schristos   E ();
4924e98e3e1Schristos   return rv;
4934e98e3e1Schristos }
4944e98e3e1Schristos 
4954e98e3e1Schristos unsigned short
4964e98e3e1Schristos mem_get_hi (int address)
4974e98e3e1Schristos {
4984e98e3e1Schristos   unsigned short rv;
4994e98e3e1Schristos   S ("=>");
5004e98e3e1Schristos   switch (address)
5014e98e3e1Schristos     {
5024e98e3e1Schristos #ifdef CYCLE_ACCURATE
5034e98e3e1Schristos     case 0x00088126: /* TPU1.TCNT */
5044e98e3e1Schristos       rv = (regs.cycle_count - tpu_base) >> 16;
5054e98e3e1Schristos       break;
5064e98e3e1Schristos     case 0x00088136: /* TPU2.TCNT */
5074e98e3e1Schristos       rv = (regs.cycle_count - tpu_base) >> 0;
5084e98e3e1Schristos       break;
5094e98e3e1Schristos #endif
5104e98e3e1Schristos 
5114e98e3e1Schristos     default:
5124e98e3e1Schristos       if (rx_big_endian)
5134e98e3e1Schristos 	{
5144e98e3e1Schristos 	  rv = mem_get_byte (address) << 8;
5154e98e3e1Schristos 	  rv |= mem_get_byte (address + 1);
5164e98e3e1Schristos 	}
5174e98e3e1Schristos       else
5184e98e3e1Schristos 	{
5194e98e3e1Schristos 	  rv = mem_get_byte (address);
5204e98e3e1Schristos 	  rv |= mem_get_byte (address + 1) << 8;
5214e98e3e1Schristos 	}
5224e98e3e1Schristos     }
5234e98e3e1Schristos   COUNT (0, 2);
5244e98e3e1Schristos   E ();
5254e98e3e1Schristos   return rv;
5264e98e3e1Schristos }
5274e98e3e1Schristos 
5284e98e3e1Schristos unsigned long
5294e98e3e1Schristos mem_get_psi (int address)
5304e98e3e1Schristos {
5314e98e3e1Schristos   unsigned long rv;
5324e98e3e1Schristos   S ("=>");
5334e98e3e1Schristos   if (rx_big_endian)
5344e98e3e1Schristos     {
5354e98e3e1Schristos       rv = mem_get_byte (address + 2);
5364e98e3e1Schristos       rv |= mem_get_byte (address + 1) << 8;
5374e98e3e1Schristos       rv |= mem_get_byte (address) << 16;
5384e98e3e1Schristos     }
5394e98e3e1Schristos   else
5404e98e3e1Schristos     {
5414e98e3e1Schristos       rv = mem_get_byte (address);
5424e98e3e1Schristos       rv |= mem_get_byte (address + 1) << 8;
5434e98e3e1Schristos       rv |= mem_get_byte (address + 2) << 16;
5444e98e3e1Schristos     }
5454e98e3e1Schristos   COUNT (0, 3);
5464e98e3e1Schristos   E ();
5474e98e3e1Schristos   return rv;
5484e98e3e1Schristos }
5494e98e3e1Schristos 
5504e98e3e1Schristos unsigned long
5514e98e3e1Schristos mem_get_si (int address)
5524e98e3e1Schristos {
5534e98e3e1Schristos   unsigned long rv;
5544e98e3e1Schristos   S ("=>");
5554e98e3e1Schristos   if (rx_big_endian)
5564e98e3e1Schristos     {
5574e98e3e1Schristos       rv = mem_get_byte (address + 3);
5584e98e3e1Schristos       rv |= mem_get_byte (address + 2) << 8;
5594e98e3e1Schristos       rv |= mem_get_byte (address + 1) << 16;
5604e98e3e1Schristos       rv |= mem_get_byte (address) << 24;
5614e98e3e1Schristos     }
5624e98e3e1Schristos   else
5634e98e3e1Schristos     {
5644e98e3e1Schristos       rv = mem_get_byte (address);
5654e98e3e1Schristos       rv |= mem_get_byte (address + 1) << 8;
5664e98e3e1Schristos       rv |= mem_get_byte (address + 2) << 16;
5674e98e3e1Schristos       rv |= mem_get_byte (address + 3) << 24;
5684e98e3e1Schristos     }
5694e98e3e1Schristos   COUNT (0, 4);
5704e98e3e1Schristos   E ();
5714e98e3e1Schristos   return rv;
5724e98e3e1Schristos }
5734e98e3e1Schristos 
5744e98e3e1Schristos void
5754b169a6bSchristos mem_get_blk (int address, void *bufptr_void, int nbytes)
5764e98e3e1Schristos {
5774b169a6bSchristos   char *bufptr = (char *) bufptr_void;
5784b169a6bSchristos 
5794e98e3e1Schristos   S ("=>");
5804e98e3e1Schristos   if (enable_counting)
5814e98e3e1Schristos     mem_counters[0][1] += nbytes;
5824e98e3e1Schristos   while (nbytes--)
5834b169a6bSchristos     *bufptr++ = mem_get_byte (address++);
5844e98e3e1Schristos   E ();
5854e98e3e1Schristos }
5864e98e3e1Schristos 
5874e98e3e1Schristos int
5884e98e3e1Schristos sign_ext (int v, int bits)
5894e98e3e1Schristos {
5904e98e3e1Schristos   if (bits < 32)
5914e98e3e1Schristos     {
5924e98e3e1Schristos       v &= (1 << bits) - 1;
5934e98e3e1Schristos       if (v & (1 << (bits - 1)))
5944e98e3e1Schristos 	v -= (1 << bits);
5954e98e3e1Schristos     }
5964e98e3e1Schristos   return v;
5974e98e3e1Schristos }
5984e98e3e1Schristos 
5994e98e3e1Schristos void
6004e98e3e1Schristos mem_set_content_type (int address, enum mem_content_type type)
6014e98e3e1Schristos {
6024e98e3e1Schristos   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
6034e98e3e1Schristos   *mt = type;
6044e98e3e1Schristos }
6054e98e3e1Schristos 
6064e98e3e1Schristos void
6074e98e3e1Schristos mem_set_content_range (int start_address, int end_address, enum mem_content_type type)
6084e98e3e1Schristos {
6094e98e3e1Schristos   while (start_address < end_address)
6104e98e3e1Schristos     {
6114e98e3e1Schristos       int sz, ofs;
6124e98e3e1Schristos       unsigned char *mt;
6134e98e3e1Schristos 
6144e98e3e1Schristos       sz = end_address - start_address;
6154e98e3e1Schristos       ofs = start_address % L1_LEN;
6164e98e3e1Schristos       if (sz + ofs > L1_LEN)
6174e98e3e1Schristos 	sz = L1_LEN - ofs;
6184e98e3e1Schristos 
6194e98e3e1Schristos       mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE);
6204e98e3e1Schristos       memset (mt, type, sz);
6214e98e3e1Schristos 
6224e98e3e1Schristos       start_address += sz;
6234e98e3e1Schristos     }
6244e98e3e1Schristos }
6254e98e3e1Schristos 
6264e98e3e1Schristos enum mem_content_type
6274e98e3e1Schristos mem_get_content_type (int address)
6284e98e3e1Schristos {
6294e98e3e1Schristos   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
6304e98e3e1Schristos   return *mt;
6314e98e3e1Schristos }
632