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