PR sim/12737
[deliverable/binutils-gdb.git] / sim / m32c / mem.c
CommitLineData
d45a4bef
JB
1/* mem.c --- memory for M32C simulator.
2
7b6bb8da
JB
3Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
4Free Software Foundation, Inc.
d45a4bef
JB
5Contributed by Red Hat, Inc.
6
7This file is part of the GNU simulators.
8
4744ac1b
JB
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 3 of the License, or
12(at your option) any later version.
d45a4bef 13
4744ac1b
JB
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
d45a4bef
JB
18
19You should have received a copy of the GNU General Public License
4744ac1b 20along with this program. If not, see <http://www.gnu.org/licenses/>. */
d45a4bef
JB
21
22
340cf1cf 23#include "config.h"
d45a4bef
JB
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
3877a145
DD
27#include <ctype.h>
28#include <sys/time.h>
29#include <sys/types.h>
30#include <unistd.h>
340cf1cf 31#ifdef HAVE_SYS_SELECT_H
3877a145 32#include <sys/select.h>
340cf1cf
DD
33#endif
34#ifdef HAVE_TERMIOS_H
3877a145 35#include <termios.h>
340cf1cf 36#endif
d45a4bef
JB
37
38#include "mem.h"
39#include "cpu.h"
40#include "syscalls.h"
41#include "misc.h"
3877a145
DD
42#ifdef TIMER_A
43#include "int.h"
44#include "timer_a.h"
45#endif
d45a4bef
JB
46
47#define L1_BITS (10)
48#define L2_BITS (10)
49#define OFF_BITS (12)
50
51#define L1_LEN (1 << L1_BITS)
52#define L2_LEN (1 << L2_BITS)
53#define OFF_LEN (1 << OFF_BITS)
54
55static unsigned char **pt[L1_LEN];
56
340cf1cf 57#ifdef HAVE_TERMIOS_H
3877a145 58int m32c_console_ifd = 0;
340cf1cf 59#endif
3877a145 60int m32c_console_ofd = 1;
340cf1cf 61#ifdef HAVE_TERMIOS_H
e7ddc197 62int m32c_use_raw_console = 0;
340cf1cf 63#endif
3877a145
DD
64
65#ifdef TIMER_A
66Timer_A timer_a;
67#endif
68
d45a4bef 69/* [ get=0/put=1 ][ byte size ] */
3877a145 70static unsigned int mem_counters[2][5];
d45a4bef
JB
71
72#define COUNT(isput,bytes) \
73 if (verbose && enable_counting) mem_counters[isput][bytes]++
74
75void
76init_mem (void)
77{
78 int i, j;
79
80 for (i = 0; i < L1_LEN; i++)
81 if (pt[i])
82 {
83 for (j = 0; j < L2_LEN; j++)
84 if (pt[i][j])
85 free (pt[i][j]);
86 free (pt[i]);
87 }
88 memset (pt, 0, sizeof (pt));
89 memset (mem_counters, 0, sizeof (mem_counters));
90}
91
92static unsigned char *
93mem_ptr (address)
94{
3877a145 95 static int recursing = 0;
d45a4bef
JB
96 int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
97 int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
98 int pto = address & ((1 << OFF_BITS) - 1);
99
3877a145 100 if (address == 0 && !recursing)
d45a4bef 101 {
3877a145
DD
102 recursing = 1;
103 put_reg (pc, m32c_opcode_pc);
104 printf ("NULL pointer dereference at pc=0x%x\n", get_reg (pc));
105 step_result = M32C_MAKE_HIT_BREAK ();
106#if 0
107 /* This code can be re-enabled to help diagnose NULL pointer
108 bugs that aren't debuggable in GDB. */
109 m32c_dump_all_registers ();
d45a4bef 110 exit (1);
3877a145 111#endif
d45a4bef
JB
112 }
113
114 if (pt[pt1] == 0)
115 pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
116 if (pt[pt1][pt2] == 0)
117 {
118 pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
119 memset (pt[pt1][pt2], 0, OFF_LEN);
120 }
121
122 return pt[pt1][pt2] + pto;
123}
124
125static void
126used (int rstart, int i, int j)
127{
128 int rend = i << (L2_BITS + OFF_BITS);
129 rend += j << OFF_BITS;
130 if (rstart == 0xe0000 && rend == 0xe1000)
131 return;
132 printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1,
133 (rend - rstart) / 1024);
134}
135
136static char *
137mcs (int isput, int bytes)
138{
139 return comma (mem_counters[isput][bytes]);
140}
141
142void
143mem_usage_stats ()
144{
145 int i, j;
146 int rstart = 0;
147 int pending = 0;
148
149 for (i = 0; i < L1_LEN; i++)
150 if (pt[i])
151 {
152 for (j = 0; j < L2_LEN; j++)
153 if (pt[i][j])
154 {
155 if (!pending)
156 {
157 pending = 1;
158 rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
159 }
160 }
161 else if (pending)
162 {
163 pending = 0;
164 used (rstart, i, j);
165 }
166 }
167 else
168 {
169 if (pending)
170 {
171 pending = 0;
172 used (rstart, i, 0);
173 }
174 }
175 /* mem foo: 123456789012 123456789012 123456789012 123456789012
176 123456789012 */
177 printf (" byte short pointer long"
3877a145 178 " fetch\n");
d45a4bef
JB
179 printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
180 mcs (0, 3), mcs (0, 4), mcs (0, 0));
181 printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
182 mcs (1, 3), mcs (1, 4));
183}
184
185static int tpr = 0;
186static void
187s (int address, char *dir)
188{
189 if (tpr == 0)
190 printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir);
191 tpr++;
192}
193
194#define S(d) if (trace) s(address, d)
195static void
196e ()
197{
198 if (!trace)
199 return;
200 tpr--;
201 if (tpr == 0)
202 printf ("\n");
203}
204
205#define E() if (trace) e()
206
3877a145
DD
207extern int m32c_disassemble;
208
d45a4bef
JB
209void
210mem_put_byte (int address, unsigned char value)
211{
212 unsigned char *m;
213 address &= membus_mask;
214 m = mem_ptr (address);
215 if (trace)
216 printf (" %02x", value);
217 *m = value;
218 switch (address)
219 {
220 case 0x00e1:
221 {
222 static int old_led = -1;
223 static char *led_on[] =
224 { "\033[31m O ", "\033[32m O ", "\033[34m O " };