sim/ChangeLog:
[binutils-gdb.git] / sim / m32c / mem.c
1 /* mem.c --- memory for M32C simulator.
2
3 Copyright (C) 2005 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
7
8 The GNU simulators are free software; you can redistribute them and/or
9 modify them under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The GNU simulators are distributed in the hope that they will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with the GNU simulators; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA */
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "mem.h"
29 #include "cpu.h"
30 #include "syscalls.h"
31 #include "misc.h"
32
33 #define L1_BITS (10)
34 #define L2_BITS (10)
35 #define OFF_BITS (12)
36
37 #define L1_LEN (1 << L1_BITS)
38 #define L2_LEN (1 << L2_BITS)
39 #define OFF_LEN (1 << OFF_BITS)
40
41 static unsigned char **pt[L1_LEN];
42
43 /* [ get=0/put=1 ][ byte size ] */
44 static unsigned int mem_counters[2][4];
45
46 #define COUNT(isput,bytes) \
47 if (verbose && enable_counting) mem_counters[isput][bytes]++
48
49 void
50 init_mem (void)
51 {
52 int i, j;
53
54 for (i = 0; i < L1_LEN; i++)
55 if (pt[i])
56 {
57 for (j = 0; j < L2_LEN; j++)
58 if (pt[i][j])
59 free (pt[i][j]);
60 free (pt[i]);
61 }
62 memset (pt, 0, sizeof (pt));
63 memset (mem_counters, 0, sizeof (mem_counters));
64 }
65
66 static unsigned char *
67 mem_ptr (address)
68 {
69 int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
70 int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
71 int pto = address & ((1 << OFF_BITS) - 1);
72
73 if (address == 0)
74 {
75 printf ("NULL pointer dereference\n");
76 exit (1);
77 }
78
79 if (pt[pt1] == 0)
80 pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
81 if (pt[pt1][pt2] == 0)
82 {
83 pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
84 memset (pt[pt1][pt2], 0, OFF_LEN);
85 }
86
87 return pt[pt1][pt2] + pto;
88 }
89
90 static void
91 used (int rstart, int i, int j)
92 {
93 int rend = i << (L2_BITS + OFF_BITS);
94 rend += j << OFF_BITS;
95 if (rstart == 0xe0000 && rend == 0xe1000)
96 return;
97 printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1,
98 (rend - rstart) / 1024);
99 }
100
101 static char *
102 mcs (int isput, int bytes)
103 {
104 return comma (mem_counters[isput][bytes]);
105 }
106
107 void
108 mem_usage_stats ()
109 {
110 int i, j;
111 int rstart = 0;
112 int pending = 0;
113
114 for (i = 0; i < L1_LEN; i++)
115 if (pt[i])
116 {
117 for (j = 0; j < L2_LEN; j++)
118 if (pt[i][j])
119 {
120 if (!pending)
121 {
122 pending = 1;
123 rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
124 }
125 }
126 else if (pending)
127 {
128 pending = 0;
129 used (rstart, i, j);
130 }
131 }
132 else
133 {
134 if (pending)
135 {
136 pending = 0;
137 used (rstart, i, 0);
138 }
139 }
140 /* mem foo: 123456789012 123456789012 123456789012 123456789012
141 123456789012 */
142 printf (" byte short pointer long"
143 " fetch\n");
144 printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
145 mcs (0, 3), mcs (0, 4), mcs (0, 0));
146 printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
147 mcs (1, 3), mcs (1, 4));
148 }
149
150 static int tpr = 0;
151 static void
152 s (int address, char *dir)
153 {
154 if (tpr == 0)
155 printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir);
156 tpr++;
157 }
158
159 #define S(d) if (trace) s(address, d)
160 static void
161 e ()
162 {
163 if (!trace)
164 return;
165 tpr--;
166 if (tpr == 0)
167 printf ("\n");
168 }
169
170 #define E() if (trace) e()
171
172 void
173 mem_put_byte (int address, unsigned char value)
174 {
175 unsigned char *m;
176 address &= membus_mask;
177 m = mem_ptr (address);
178 if (trace)
179 printf (" %02x", value);
180 *m = value;
181 switch (address)
182 {
183 case 0x00e1:
184 {
185 static int old_led = -1;
186 static char *led_on[] =
187 { "\033[31m O ", "\033[32m O ", "\033[34m O " };
188 static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " };
189 int i;
190 if (old_led != value)
191 {
192 fputs (" ", stdout);
193 for (i = 0; i < 3; i++)
194 if (value & (1 << i))
195 fputs (led_off[i], stdout);
196 else
197 fputs (led_on[i], stdout);
198 fputs ("\033[0m\r", stdout);
199 fflush (stdout);
200 old_led = value;
201 }
202 }
203 break;
204
205 case 0x400:
206 m32c_syscall (value);
207 break;
208
209 case 0x401:
210 putchar (value);
211 break;
212
213 case 0x402:
214 printf ("SimTrace: %06lx %02x\n", regs.r_pc, value);
215 break;
216
217 case 0x403:
218 printf ("SimTrap: %06lx %02x\n", regs.r_pc, value);
219 abort ();
220 }
221 }
222
223 void
224 mem_put_qi (int address, unsigned char value)
225 {
226 S ("<=");
227 mem_put_byte (address, value & 0xff);
228 E ();
229 COUNT (1, 1);
230 }
231
232 void
233 mem_put_hi (int address, unsigned short value)
234 {
235 S ("<=");
236 mem_put_byte (address, value & 0xff);
237 mem_put_byte (address + 1, value >> 8);
238 E ();
239 COUNT (1, 2);
240 }
241
242 void
243 mem_put_psi (int address, unsigned long value)
244 {
245 S ("<=");
246 mem_put_byte (address, value & 0xff);
247 mem_put_byte (address + 1, (value >> 8) & 0xff);
248 mem_put_byte (address + 2, value >> 16);
249 E ();
250 COUNT (1, 3);
251 }
252
253 void
254 mem_put_si (int address, unsigned long value)
255 {
256 S ("<=");
257 mem_put_byte (address, value & 0xff);
258 mem_put_byte (address + 1, (value >> 8) & 0xff);
259 mem_put_byte (address + 2, (value >> 16) & 0xff);
260 mem_put_byte (address + 3, (value >> 24) & 0xff);
261 E ();
262 COUNT (1, 4);
263 }
264
265 void
266 mem_put_blk (int address, void *bufptr, int nbytes)
267 {
268 S ("<=");
269 if (enable_counting)
270 mem_counters[1][1] += nbytes;
271 while (nbytes--)
272 mem_put_byte (address++, *(unsigned char *) bufptr++);
273 E ();
274 }
275
276 unsigned char
277 mem_get_pc ()
278 {
279 unsigned char *m = mem_ptr (regs.r_pc & membus_mask);
280 COUNT (0, 0);
281 return *m;
282 }
283
284 static unsigned char
285 mem_get_byte (int address)
286 {
287 unsigned char *m;
288 address &= membus_mask;
289 S ("=>");
290 m = mem_ptr (address);
291 if (trace)
292 {
293 if (tpr)
294 printf (" %02x", *m);
295 else
296 {
297 S ("=>");
298 printf (" %02x", *m);
299 E ();
300 }
301 }
302 E ();
303 return *m;
304 }
305
306 unsigned char
307 mem_get_qi (int address)
308 {
309 unsigned char rv;
310 S ("=>");
311 rv = mem_get_byte (address);
312 COUNT (0, 1);
313 E ();
314 return rv;
315 }
316
317 unsigned short
318 mem_get_hi (int address)
319 {
320 unsigned short rv;
321 S ("=>");
322 rv = mem_get_byte (address);
323 rv |= mem_get_byte (address + 1) * 256;
324 COUNT (0, 2);
325 E ();
326 return rv;
327 }
328
329 unsigned long
330 mem_get_psi (int address)
331 {
332 unsigned long rv;
333 S ("=>");
334 rv = mem_get_byte (address);
335 rv |= mem_get_byte (address + 1) * 256;
336 rv |= mem_get_byte (address + 2) * 65536;
337 COUNT (0, 3);
338 E ();
339 return rv;
340 }
341
342 unsigned long
343 mem_get_si (int address)
344 {
345 unsigned long rv;
346 S ("=>");
347 rv = mem_get_byte (address);
348 rv |= mem_get_byte (address + 1) << 8;
349 rv |= mem_get_byte (address + 2) << 16;
350 rv |= mem_get_byte (address + 3) << 24;
351 COUNT (0, 4);
352 E ();
353 return rv;
354 }
355
356 void
357 mem_get_blk (int address, void *bufptr, int nbytes)
358 {
359 S ("=>");
360 if (enable_counting)
361 mem_counters[0][1] += nbytes;
362 while (nbytes--)
363 *(char *) bufptr++ = mem_get_byte (address++);
364 E ();
365 }
366
367 int
368 sign_ext (int v, int bits)
369 {
370 if (bits < 32)
371 {
372 v &= (1 << bits) - 1;
373 if (v & (1 << (bits - 1)))
374 v -= (1 << bits);
375 }
376 return v;
377 }