[include/opcode]
[external/binutils.git] / sim / rx / mem.c
1 /* mem.c --- memory for RX simulator.
2
3 Copyright (C) 2005, 2007, 2008, 2009, 2010 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       if (ptr[pt1][pt2][pto] == MC_PUSHED_PC)
108         execution_error (SIM_ERR_CORRUPT_STACK, address);
109       ptr[pt1][pt2][pto] = MC_DATA;
110       if (ptdc[pt1][pt2][pto])
111         {
112           free (ptdc[pt1][pt2][pto]);
113           ptdc[pt1][pt2][pto] = NULL;
114         }
115     }
116
117   if (action == MPA_CONTENT_TYPE)
118     return (unsigned char *) (ptr[pt1][pt2] + pto);
119
120   if (action == MPA_DECODE_CACHE)
121     return (unsigned char *) (ptdc[pt1][pt2] + pto);
122
123   return pt[pt1][pt2] + pto;
124 }
125
126 RX_Opcode_Decoded **
127 rx_mem_decode_cache (unsigned long address)
128 {
129   return (RX_Opcode_Decoded **) rx_mem_ptr (address, MPA_DECODE_CACHE);
130 }
131
132 static inline int
133 is_reserved_address (unsigned int address)
134 {
135   return (address >= 0x00020000 && address < 0x00080000)
136     ||   (address >= 0x00100000 && address < 0x01000000)
137     ||   (address >= 0x08000000 && address < 0xff000000);
138 }
139
140 static void
141 used (int rstart, int i, int j)
142 {
143   int rend = i << (L2_BITS + OFF_BITS);
144   rend += j << OFF_BITS;
145   if (rstart == 0xe0000 && rend == 0xe1000)
146     return;
147   printf ("mem:   %08x - %08x (%dk bytes)\n", rstart, rend - 1,
148           (rend - rstart) / 1024);
149 }
150
151 static char *
152 mcs (int isput, int bytes)
153 {
154   return comma (mem_counters[isput][bytes]);
155 }
156
157 void
158 mem_usage_stats ()
159 {
160   int i, j;
161   int rstart = 0;
162   int pending = 0;
163
164   for (i = 0; i < L1_LEN; i++)
165     if (pt[i])
166       {
167         for (j = 0; j < L2_LEN; j++)
168           if (pt[i][j])
169             {
170               if (!pending)
171                 {
172                   pending = 1;
173                   rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
174                 }
175             }
176           else if (pending)
177             {
178               pending = 0;
179               used (rstart, i, j);
180             }
181       }
182     else
183       {
184         if (pending)
185           {
186             pending = 0;
187             used (rstart, i, 0);
188           }
189       }
190   /*       mem foo: 123456789012 123456789012 123456789012 123456789012
191             123456789012 */
192   printf ("                 byte        short        3byte         long"
193           "       opcode\n");
194   if (verbose > 1)
195     {
196       /* Only use comma separated numbers when being very verbose.
197          Comma separated numbers are hard to parse in awk scripts.  */
198       printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
199               mcs (0, 3), mcs (0, 4), mcs (0, 0));
200       printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
201               mcs (1, 3), mcs (1, 4));
202     }
203   else
204     {
205       printf ("mem get: %12u %12u %12u %12u %12u\n",
206               mem_counters[0][1], mem_counters[0][2],
207               mem_counters[0][3], mem_counters[0][4],
208               mem_counters[0][0]);
209       printf ("mem put: %12u %12u %12u %12u\n",
210               mem_counters [1][1], mem_counters [1][2],
211               mem_counters [1][3], mem_counters [1][4]);
212     }
213 }
214
215 unsigned long
216 mem_usage_cycles (void)
217 {
218   unsigned long rv = mem_counters[0][0];
219   rv += mem_counters[0][1] * 1;
220   rv += mem_counters[0][2] * 2;
221   rv += mem_counters[0][3] * 3;
222   rv += mem_counters[0][4] * 4;
223   rv += mem_counters[1][1] * 1;
224   rv += mem_counters[1][2] * 2;
225   rv += mem_counters[1][3] * 3;
226   rv += mem_counters[1][4] * 4;
227   return rv;
228 }
229
230 static int tpr = 0;
231 static void
232 s (int address, char *dir)
233 {
234   if (tpr == 0)
235     printf ("MEM[%08x] %s", address, dir);
236   tpr++;
237 }
238
239 #define S(d) if (trace) s(address, d)
240 static void
241 e ()
242 {
243   if (!trace)
244     return;
245   tpr--;
246   if (tpr == 0)
247     printf ("\n");
248 }
249
250 static char
251 mtypec (int address)
252 {
253   unsigned char *cp = rx_mem_ptr (address, MPA_CONTENT_TYPE);
254   return "udp"[*cp];
255 }
256
257 #define E() if (trace) e()
258
259 void
260 mem_put_byte (unsigned int address, unsigned char value)
261 {
262   unsigned char *m;
263   char tc = ' ';
264
265   if (trace)
266     tc = mtypec (address);
267   m = rx_mem_ptr (address, MPA_WRITING);
268   if (trace)
269     printf (" %02x%c", value, tc);
270   *m = value;
271   switch (address)
272     {
273     case 0x0008c02a: /* PA.DR */
274      {
275         static int old_led = -1;
276         int red_on = 0;
277         int i;
278
279         if (old_led != value)
280           {
281             fputs (" ", stdout);
282             for (i = 0; i < 8; i++)
283               if (value & (1 << i))
284                 {
285                   if (! red_on)
286                     {
287                       fputs ("\033[31m", stdout);
288                       red_on = 1;
289                     }
290                   fputs (" @", stdout);
291                 }
292               else
293                 {
294                   if (red_on)
295                     {
296                       fputs ("\033[0m", stdout);
297                       red_on = 0;
298                     }
299                   fputs (" *", stdout);
300                 }
301
302             if (red_on)
303               fputs ("\033[0m", stdout);
304
305             fputs ("\r", stdout);
306             fflush (stdout);
307             old_led = value;
308           }
309       }
310       break;
311
312 #ifdef CYCLE_STATS
313     case 0x0008c02b: /* PB.DR */
314       {
315         if (value == 0)
316           halt_pipeline_stats ();
317         else
318           reset_pipeline_stats ();
319       }
320 #endif
321
322     case 0x00088263: /* SCI4.TDR */
323       {
324         static int pending_exit = 0;
325         if (pending_exit == 2)
326           {
327             step_result = RX_MAKE_EXITED(value);
328             longjmp (decode_jmp_buf, 1);
329           }
330         else if (value == 3)
331           pending_exit ++;
332         else
333           pending_exit = 0;
334
335         putchar(value);
336       }
337       break;
338
339     default:
340       if (is_reserved_address (address))
341         generate_access_exception ();
342     }
343 }
344
345 void
346 mem_put_qi (int address, unsigned char value)
347 {
348   S ("<=");
349   mem_put_byte (address, value & 0xff);
350   E ();
351   COUNT (1, 1);
352 }
353
354 #ifdef CYCLE_ACCURATE
355 static int tpu_base;
356 #endif
357
358 void
359 mem_put_hi (int address, unsigned short value)
360 {
361   S ("<=");
362   switch (address)
363     {
364 #ifdef CYCLE_ACCURATE
365     case 0x00088126: /* TPU1.TCNT */
366       tpu_base = regs.cycle_count;
367       break;
368     case 0x00088136: /* TPU2.TCNT */
369       tpu_base = regs.cycle_count;
370       break;
371 #endif
372     default:
373       if (rx_big_endian)
374         {
375           mem_put_byte (address, value >> 8);
376           mem_put_byte (address + 1, value & 0xff);
377         }
378       else
379         {
380           mem_put_byte (address, value & 0xff);
381           mem_put_byte (address + 1, value >> 8);
382         }
383     }
384   E ();
385   COUNT (1, 2);
386 }
387
388 void
389 mem_put_psi (int address, unsigned long value)
390 {
391   S ("<=");
392   if (rx_big_endian)
393     {
394       mem_put_byte (address, value >> 16);
395       mem_put_byte (address + 1, (value >> 8) & 0xff);
396       mem_put_byte (address + 2, value & 0xff);
397     }
398   else
399     {
400       mem_put_byte (address, value & 0xff);
401       mem_put_byte (address + 1, (value >> 8) & 0xff);
402       mem_put_byte (address + 2, value >> 16);
403     }
404   E ();
405   COUNT (1, 3);
406 }
407
408 void
409 mem_put_si (int address, unsigned long value)
410 {
411   S ("<=");
412   if (rx_big_endian)
413     {
414       mem_put_byte (address + 0, (value >> 24) & 0xff);
415       mem_put_byte (address + 1, (value >> 16) & 0xff);
416       mem_put_byte (address + 2, (value >> 8) & 0xff);
417       mem_put_byte (address + 3, value & 0xff);
418     }
419   else
420     {
421       mem_put_byte (address + 0, value & 0xff);
422       mem_put_byte (address + 1, (value >> 8) & 0xff);
423       mem_put_byte (address + 2, (value >> 16) & 0xff);
424       mem_put_byte (address + 3, (value >> 24) & 0xff);
425     }
426   E ();
427   COUNT (1, 4);
428 }
429
430 void
431 mem_put_blk (int address, void *bufptr, int nbytes)
432 {
433   S ("<=");
434   if (enable_counting)
435     mem_counters[1][1] += nbytes;
436   while (nbytes--)
437     mem_put_byte (address++, *(unsigned char *) bufptr++);
438   E ();
439 }
440
441 unsigned char
442 mem_get_pc (int address)
443 {
444   unsigned char *m = rx_mem_ptr (address, MPA_READING);
445   COUNT (0, 0);
446   return *m;
447 }
448
449 static unsigned char
450 mem_get_byte (unsigned int address)
451 {
452   unsigned char *m;
453
454   S ("=>");
455   m = rx_mem_ptr (address, MPA_READING);
456   switch (address)
457     {
458     case 0x00088264: /* SCI4.SSR */
459       E();
460       return 0x04; /* transmitter empty */
461       break;
462     default: 
463       if (trace)
464         printf (" %02x%c", *m, mtypec (address));
465       if (is_reserved_address (address))
466         generate_access_exception ();
467       break;
468     }
469   E ();
470   return *m;
471 }
472
473 unsigned char
474 mem_get_qi (int address)
475 {
476   unsigned char rv;
477   S ("=>");
478   rv = mem_get_byte (address);
479   COUNT (0, 1);
480   E ();
481   return rv;
482 }
483
484 unsigned short
485 mem_get_hi (int address)
486 {
487   unsigned short rv;
488   S ("=>");
489   switch (address)
490     {
491 #ifdef CYCLE_ACCURATE
492     case 0x00088126: /* TPU1.TCNT */
493       rv = (regs.cycle_count - tpu_base) >> 16;
494       break;
495     case 0x00088136: /* TPU2.TCNT */
496       rv = (regs.cycle_count - tpu_base) >> 0;
497       break;
498 #endif
499
500     default:
501       if (rx_big_endian)
502         {
503           rv = mem_get_byte (address) << 8;
504           rv |= mem_get_byte (address + 1);
505         }
506       else
507         {
508           rv = mem_get_byte (address);
509           rv |= mem_get_byte (address + 1) << 8;
510         }
511     }
512   COUNT (0, 2);
513   E ();
514   return rv;
515 }
516
517 unsigned long
518 mem_get_psi (int address)
519 {
520   unsigned long rv;
521   S ("=>");
522   if (rx_big_endian)
523     {
524       rv = mem_get_byte (address + 2);
525       rv |= mem_get_byte (address + 1) << 8;
526       rv |= mem_get_byte (address) << 16;
527     }
528   else
529     {
530       rv = mem_get_byte (address);
531       rv |= mem_get_byte (address + 1) << 8;
532       rv |= mem_get_byte (address + 2) << 16;
533     }
534   COUNT (0, 3);
535   E ();
536   return rv;
537 }
538
539 unsigned long
540 mem_get_si (int address)
541 {
542   unsigned long rv;
543   S ("=>");
544   if (rx_big_endian)
545     {
546       rv = mem_get_byte (address + 3);
547       rv |= mem_get_byte (address + 2) << 8;
548       rv |= mem_get_byte (address + 1) << 16;
549       rv |= mem_get_byte (address) << 24;
550     }
551   else
552     {
553       rv = mem_get_byte (address);
554       rv |= mem_get_byte (address + 1) << 8;
555       rv |= mem_get_byte (address + 2) << 16;
556       rv |= mem_get_byte (address + 3) << 24;
557     }
558   COUNT (0, 4);
559   E ();
560   return rv;
561 }
562
563 void
564 mem_get_blk (int address, void *bufptr, int nbytes)
565 {
566   S ("=>");
567   if (enable_counting)
568     mem_counters[0][1] += nbytes;
569   while (nbytes--)
570     *(char *) bufptr++ = mem_get_byte (address++);
571   E ();
572 }
573
574 int
575 sign_ext (int v, int bits)
576 {
577   if (bits < 32)
578     {
579       v &= (1 << bits) - 1;
580       if (v & (1 << (bits - 1)))
581         v -= (1 << bits);
582     }
583   return v;
584 }
585
586 void
587 mem_set_content_type (int address, enum mem_content_type type)
588 {
589   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
590   *mt = type;
591 }
592
593 void
594 mem_set_content_range (int start_address, int end_address, enum mem_content_type type)
595 {
596   while (start_address < end_address)
597     {
598       int sz, ofs;
599       unsigned char *mt;
600
601       sz = end_address - start_address;
602       ofs = start_address % L1_LEN;
603       if (sz + ofs > L1_LEN)
604         sz = L1_LEN - ofs;
605
606       mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE);
607       memset (mt, type, sz);
608
609       start_address += sz;
610     }
611 }
612
613 enum mem_content_type
614 mem_get_content_type (int address)
615 {
616   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
617   return *mt;
618 }