run copyright.sh for 2011.
[deliverable/binutils-gdb.git] / sim / rx / mem.c
1 /* mem.c --- memory for RX simulator.
2
3 Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
5 Contributed by Red Hat, Inc.
6
7 This file is part of the GNU simulators.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 /* This slows down the simulator and we get some false negatives from
23 gcc, like when it uses a long-sized hole to hold a byte-sized
24 variable, knowing that it doesn't care about the other bits. But,
25 if you need to track down a read-from-unitialized bug, set this to
26 1. */
27 #define RDCHECK 0
28
29 #include "config.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "opcode/rx.h"
35 #include "mem.h"
36 #include "cpu.h"
37 #include "syscalls.h"
38 #include "misc.h"
39 #include "err.h"
40
41 #define L1_BITS (10)
42 #define L2_BITS (10)
43 #define OFF_BITS PAGE_BITS
44
45 #define L1_LEN (1 << L1_BITS)
46 #define L2_LEN (1 << L2_BITS)
47 #define OFF_LEN (1 << OFF_BITS)
48
49 static unsigned char **pt[L1_LEN];
50 static unsigned char **ptr[L1_LEN];
51 static RX_Opcode_Decoded ***ptdc[L1_LEN];
52
53 /* [ get=0/put=1 ][ byte size ] */
54 static unsigned int mem_counters[2][5];
55
56 #define COUNT(isput,bytes) \
57 if (verbose && enable_counting) mem_counters[isput][bytes]++
58
59 void
60 init_mem (void)
61 {
62 int i, j;
63
64 for (i = 0; i < L1_LEN; i++)
65 if (pt[i])
66 {
67 for (j = 0; j < L2_LEN; j++)
68 if (pt[i][j])
69 free (pt[i][j]);
70 free (pt[i]);
71 }
72 memset (pt, 0, sizeof (pt));
73 memset (ptr, 0, sizeof (ptr));
74 memset (mem_counters, 0, sizeof (mem_counters));
75 }
76
77 unsigned char *
78 rx_mem_ptr (unsigned long address, enum mem_ptr_action action)
79 {
80 int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
81 int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
82 int pto = address & ((1 << OFF_BITS) - 1);
83
84 if (address == 0)
85 execution_error (SIM_ERR_NULL_POINTER_DEREFERENCE, 0);
86
87 if (pt[pt1] == 0)
88 {
89 pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
90 ptr[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
91 ptdc[pt1] = (RX_Opcode_Decoded ***) calloc (L2_LEN, sizeof (RX_Opcode_Decoded ***));
92 }
93 if (pt[pt1][pt2] == 0)
94 {
95 if (action == MPA_READING)
96 execution_error (SIM_ERR_READ_UNWRITTEN_PAGES, address);
97
98 pt[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
99 ptr[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
100 ptdc[pt1][pt2] = (RX_Opcode_Decoded **) calloc (OFF_LEN, sizeof(RX_Opcode_Decoded *));
101 }
102 else if (action == MPA_READING
103 && ptr[pt1][pt2][pto] == MC_UNINIT)
104 execution_error (SIM_ERR_READ_UNWRITTEN_BYTES, address);
105
106 if (action == MPA_WRITING)
107 {
108 int pto_dc;
109 if (ptr[pt1][pt2][pto] == MC_PUSHED_PC)
110 execution_error (SIM_ERR_CORRUPT_STACK, address);
111 ptr[pt1][pt2][pto] = MC_DATA;
112
113 /* The instruction decoder doesn't store it's decoded instructions
114 at word swapped addresses. Therefore, when clearing the decode
115 cache, we have to account for that here. */
116 pto_dc = pto ^ (rx_big_endian ? 3 : 0);
117 if (ptdc[pt1][pt2][pto_dc])
118 {
119 free (ptdc[pt1][pt2][pto_dc]);
120 ptdc[pt1][pt2][pto_dc] = NULL;
121 }
122 }
123
124 if (action == MPA_CONTENT_TYPE)
125 return (unsigned char *) (ptr[pt1][pt2] + pto);
126
127 if (action == MPA_DECODE_CACHE)
128 return (unsigned char *) (ptdc[pt1][pt2] + pto);
129
130 return pt[pt1][pt2] + pto;
131 }
132
133 RX_Opcode_Decoded **
134 rx_mem_decode_cache (unsigned long address)
135 {
136 return (RX_Opcode_Decoded **) rx_mem_ptr (address, MPA_DECODE_CACHE);
137 }
138
139 static inline int
140 is_reserved_address (unsigned int address)
141 {
142 return (address >= 0x00020000 && address < 0x00080000)
143 || (address >= 0x00100000 && address < 0x01000000)
144 || (address >= 0x08000000 && address < 0xff000000);
145 }
146
147 static void
148 used (int rstart, int i, int j)
149 {
150 int rend = i << (L2_BITS + OFF_BITS);
151 rend += j << OFF_BITS;
152 if (rstart == 0xe0000 && rend == 0xe1000)
153 return;
154 printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1,
155 (rend - rstart) / 1024);
156 }
157
158 static char *
159 mcs (int isput, int bytes)
160 {
161 return comma (mem_counters[isput][bytes]);
162 }
163
164 void
165 mem_usage_stats ()
166 {
167 int i, j;
168 int rstart = 0;
169 int pending = 0;
170
171 for (i = 0; i < L1_LEN; i++)
172 if (pt[i])
173 {
174 for (j = 0; j < L2_LEN; j++)
175 if (pt[i][j])
176 {
177 if (!pending)
178 {
179 pending = 1;
180 rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
181 }
182 }
183 else if (pending)
184 {
185 pending = 0;
186 used (rstart, i, j);
187 }
188 }
189 else
190 {
191 if (pending)
192 {
193 pending = 0;
194 used (rstart, i, 0);
195 }
196 }
197 /* mem foo: 123456789012 123456789012 123456789012 123456789012
198 123456789012 */
199 printf (" byte short 3byte long"
200 " opcode\n");
201 if (verbose > 1)
202 {
203 /* Only use comma separated numbers when being very verbose.
204 Comma separated numbers are hard to parse in awk scripts. */
205 printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
206 mcs (0, 3), mcs (0, 4), mcs (0, 0));
207 printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
208 mcs (1, 3), mcs (1, 4));
209 }
210 else
211 {
212 printf ("mem get: %12u %12u %12u %12u %12u\n",
213 mem_counters[0][1], mem_counters[0][2],
214 mem_counters[0][3], mem_counters[0][4],
215 mem_counters[0][0]);
216 printf ("mem put: %12u %12u %12u %12u\n",
217 mem_counters [1][1], mem_counters [1][2],
218 mem_counters [1][3], mem_counters [1][4]);
219 }
220 }
221
222 unsigned long
223 mem_usage_cycles (void)
224 {
225 unsigned long rv = mem_counters[0][0];
226 rv += mem_counters[0][1] * 1;
227 rv += mem_counters[0][2] * 2;
228 rv += mem_counters[0][3] * 3;
229 rv += mem_counters[0][4] * 4;
230 rv += mem_counters[1][1] * 1;
231 rv += mem_counters[1][2] * 2;
232 rv += mem_counters[1][3] * 3;
233 rv += mem_counters[1][4] * 4;
234 return rv;
235 }
236
237 static int tpr = 0;
238 static void
239 s (int address, char *dir)
240 {
241 if (tpr == 0)
242 printf ("MEM[%08x] %s", address, dir);
243 tpr++;
244 }
245
246 #define S(d) if (trace) s(address, d)
247 static void
248 e ()
249 {
250 if (!trace)
251 return;
252 tpr--;
253 if (tpr == 0)
254 printf ("\n");
255 }
256
257 static char
258 mtypec (int address)
259 {
260 unsigned char *cp = rx_mem_ptr (address, MPA_CONTENT_TYPE);
261 return "udp"[*cp];
262 }
263
264 #define E() if (trace) e()
265
266 void
267 mem_put_byte (unsigned int address, unsigned char value)
268 {
269 unsigned char *m;
270 char tc = ' ';
271
272 if (trace)
273 tc = mtypec (address);
274 m = rx_mem_ptr (address, MPA_WRITING);
275 if (trace)
276 printf (" %02x%c", value, tc);
277 *m = value;
278 switch (address)
279 {
280 case 0x0008c02a: /* PA.DR */
281 {
282 static int old_led = -1;
283 int red_on = 0;
284 int i;
285
286 if (old_led != value)
287 {
288 fputs (" ", stdout);
289 for (i = 0; i < 8; i++)
290 if (value & (1 << i))
291 {
292 if (! red_on)
293 {
294 fputs ("\033[31m", stdout);
295 red_on = 1;
296 }
297 fputs (" @", stdout);
298 }
299 else
300 {
301 if (red_on)
302 {
303 fputs ("\033[0m", stdout);
304 red_on = 0;
305 }
306 fputs (" *", stdout);
307 }
308
309 if (red_on)
310 fputs ("\033[0m", stdout);
311
312 fputs ("\r", stdout);
313 fflush (stdout);
314 old_led = value;
315 }
316 }
317 break;
318
319 #ifdef CYCLE_STATS
320 case 0x0008c02b: /* PB.DR */
321 {
322 if (value == 0)
323 halt_pipeline_stats ();
324 else
325 reset_pipeline_stats ();
326 }
327 #endif
328
329 case 0x00088263: /* SCI4.TDR */
330 {
331 static int pending_exit = 0;
332 if (pending_exit == 2)
333 {
334 step_result = RX_MAKE_EXITED(value);
335 longjmp (decode_jmp_buf, 1);
336 }
337 else if (value == 3)
338 pending_exit ++;
339 else
340 pending_exit = 0;
341
342 putchar(value);
343 }
344 break;
345
346 default:
347 if (is_reserved_address (address))
348 generate_access_exception ();
349 }
350 }
351
352 void
353 mem_put_qi (int address, unsigned char value)
354 {
355 S ("<=");
356 mem_put_byte (address, value & 0xff);
357 E ();
358 COUNT (1, 1);
359 }
360
361 #ifdef CYCLE_ACCURATE
362 static int tpu_base;
363 #endif
364
365 void
366 mem_put_hi (int address, unsigned short value)
367 {
368 S ("<=");
369 switch (address)
370 {
371 #ifdef CYCLE_ACCURATE
372 case 0x00088126: /* TPU1.TCNT */
373 tpu_base = regs.cycle_count;
374 break;
375 case 0x00088136: /* TPU2.TCNT */
376 tpu_base = regs.cycle_count;
377 break;
378 #endif
379 default:
380 if (rx_big_endian)
381 {
382 mem_put_byte (address, value >> 8);
383 mem_put_byte (address + 1, value & 0xff);
384 }
385 else
386 {
387 mem_put_byte (address, value & 0xff);
388 mem_put_byte (address + 1, value >> 8);
389 }
390 }
391 E ();
392 COUNT (1, 2);
393 }
394
395 void
396 mem_put_psi (int address, unsigned long value)
397 {
398 S ("<=");
399 if (rx_big_endian)
400 {
401 mem_put_byte (address, value >> 16);
402 mem_put_byte (address + 1, (value >> 8) & 0xff);
403 mem_put_byte (address + 2, value & 0xff);
404 }
405 else
406 {
407 mem_put_byte (address, value & 0xff);
408 mem_put_byte (address + 1, (value >> 8) & 0xff);
409 mem_put_byte (address + 2, value >> 16);
410 }
411 E ();
412 COUNT (1, 3);
413 }
414
415 void
416 mem_put_si (int address, unsigned long value)
417 {
418 S ("<=");
419 if (rx_big_endian)
420 {
421 mem_put_byte (address + 0, (value >> 24) & 0xff);
422 mem_put_byte (address + 1, (value >> 16) & 0xff);
423 mem_put_byte (address + 2, (value >> 8) & 0xff);
424 mem_put_byte (address + 3, value & 0xff);
425 }
426 else
427 {
428 mem_put_byte (address + 0, value & 0xff);
429 mem_put_byte (address + 1, (value >> 8) & 0xff);
430 mem_put_byte (address + 2, (value >> 16) & 0xff);
431 mem_put_byte (address + 3, (value >> 24) & 0xff);
432 }
433 E ();
434 COUNT (1, 4);
435 }
436
437 void
438 mem_put_blk (int address, void *bufptr, int nbytes)
439 {
440 S ("<=");
441 if (enable_counting)
442 mem_counters[1][1] += nbytes;
443 while (nbytes--)
444 mem_put_byte (address++, *(unsigned char *) bufptr++);
445 E ();
446 }
447
448 unsigned char
449 mem_get_pc (int address)
450 {
451 unsigned char *m = rx_mem_ptr (address, MPA_READING);
452 COUNT (0, 0);
453 return *m;
454 }
455
456 static unsigned char
457 mem_get_byte (unsigned int address)
458 {
459 unsigned char *m;
460
461 S ("=>");
462 m = rx_mem_ptr (address, MPA_READING);
463 switch (address)
464 {
465 case 0x00088264: /* SCI4.SSR */
466 E();
467 return 0x04; /* transmitter empty */
468 break;
469 default:
470 if (trace)
471 printf (" %02x%c", *m, mtypec (address));
472 if (is_reserved_address (address))
473 generate_access_exception ();
474 break;
475 }
476 E ();
477 return *m;
478 }
479
480 unsigned char
481 mem_get_qi (int address)
482 {
483 unsigned char rv;
484 S ("=>");
485 rv = mem_get_byte (address);
486 COUNT (0, 1);
487 E ();
488 return rv;
489 }
490
491 unsigned short
492 mem_get_hi (int address)
493 {
494 unsigned short rv;
495 S ("=>");
496 switch (address)
497 {
498 #ifdef CYCLE_ACCURATE
499 case 0x00088126: /* TPU1.TCNT */
500 rv = (regs.cycle_count - tpu_base) >> 16;
501 break;
502 case 0x00088136: /* TPU2.TCNT */
503 rv = (regs.cycle_count - tpu_base) >> 0;
504 break;
505 #endif
506
507 default:
508 if (rx_big_endian)
509 {
510 rv = mem_get_byte (address) << 8;
511 rv |= mem_get_byte (address + 1);
512 }
513 else
514 {
515 rv = mem_get_byte (address);
516 rv |= mem_get_byte (address + 1) << 8;
517 }
518 }
519 COUNT (0, 2);
520 E ();
521 return rv;
522 }
523
524 unsigned long
525 mem_get_psi (int address)
526 {
527 unsigned long rv;
528 S ("=>");
529 if (rx_big_endian)
530 {
531 rv = mem_get_byte (address + 2);
532 rv |= mem_get_byte (address + 1) << 8;
533 rv |= mem_get_byte (address) << 16;
534 }
535 else
536 {
537 rv = mem_get_byte (address);
538 rv |= mem_get_byte (address + 1) << 8;
539 rv |= mem_get_byte (address + 2) << 16;
540 }
541 COUNT (0, 3);
542 E ();
543 return rv;
544 }
545
546 unsigned long
547 mem_get_si (int address)
548 {
549 unsigned long rv;
550 S ("=>");
551 if (rx_big_endian)
552 {
553 rv = mem_get_byte (address + 3);
554 rv |= mem_get_byte (address + 2) << 8;
555 rv |= mem_get_byte (address + 1) << 16;
556 rv |= mem_get_byte (address) << 24;
557 }
558 else
559 {
560 rv = mem_get_byte (address);
561 rv |= mem_get_byte (address + 1) << 8;
562 rv |= mem_get_byte (address + 2) << 16;
563 rv |= mem_get_byte (address + 3) << 24;
564 }
565 COUNT (0, 4);
566 E ();
567 return rv;
568 }
569
570 void
571 mem_get_blk (int address, void *bufptr, int nbytes)
572 {
573 S ("=>");
574 if (enable_counting)
575 mem_counters[0][1] += nbytes;
576 while (nbytes--)
577 *(char *) bufptr++ = mem_get_byte (address++);
578 E ();
579 }
580
581 int
582 sign_ext (int v, int bits)
583 {
584 if (bits < 32)
585 {
586 v &= (1 << bits) - 1;
587 if (v & (1 << (bits - 1)))
588 v -= (1 << bits);
589 }
590 return v;
591 }
592
593 void
594 mem_set_content_type (int address, enum mem_content_type type)
595 {
596 unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
597 *mt = type;
598 }
599
600 void
601 mem_set_content_range (int start_address, int end_address, enum mem_content_type type)
602 {
603 while (start_address < end_address)
604 {
605 int sz, ofs;
606 unsigned char *mt;
607
608 sz = end_address - start_address;
609 ofs = start_address % L1_LEN;
610 if (sz + ofs > L1_LEN)
611 sz = L1_LEN - ofs;
612
613 mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE);
614 memset (mt, type, sz);
615
616 start_address += sz;
617 }
618 }
619
620 enum mem_content_type
621 mem_get_content_type (int address)
622 {
623 unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
624 return *mt;
625 }
This page took 0.043611 seconds and 5 git commands to generate.