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