sim: generate build dependencies on the fly
[platform/upstream/binutils.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 }