Imported Upstream version 7.9
[platform/upstream/gdb.git] / sim / m32c / mem.c
1 /* mem.c --- memory for M32C simulator.
2
3 Copyright (C) 2005-2015 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
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #ifdef HAVE_SYS_SELECT_H
31 #include <sys/select.h>
32 #endif
33 #ifdef HAVE_TERMIOS_H
34 #include <termios.h>
35 #endif
36
37 #include "mem.h"
38 #include "cpu.h"
39 #include "syscalls.h"
40 #include "misc.h"
41 #ifdef TIMER_A
42 #include "int.h"
43 #include "timer_a.h"
44 #endif
45
46 #define L1_BITS  (10)
47 #define L2_BITS  (10)
48 #define OFF_BITS (12)
49
50 #define L1_LEN  (1 << L1_BITS)
51 #define L2_LEN  (1 << L2_BITS)
52 #define OFF_LEN (1 << OFF_BITS)
53
54 static unsigned char **pt[L1_LEN];
55
56 #ifdef HAVE_TERMIOS_H
57 int m32c_console_ifd = 0;
58 #endif
59 int m32c_console_ofd = 1;
60 #ifdef HAVE_TERMIOS_H
61 int m32c_use_raw_console = 0;
62 #endif
63
64 #ifdef TIMER_A
65 Timer_A timer_a;
66 #endif
67
68 /* [ get=0/put=1 ][ byte size ] */
69 static unsigned int mem_counters[2][5];
70
71 #define COUNT(isput,bytes)                                      \
72   if (verbose && enable_counting) mem_counters[isput][bytes]++
73
74 void
75 init_mem (void)
76 {
77   int i, j;
78
79   for (i = 0; i < L1_LEN; i++)
80     if (pt[i])
81       {
82         for (j = 0; j < L2_LEN; j++)
83           if (pt[i][j])
84             free (pt[i][j]);
85         free (pt[i]);
86       }
87   memset (pt, 0, sizeof (pt));
88   memset (mem_counters, 0, sizeof (mem_counters));
89 }
90
91 static unsigned char *
92 mem_ptr (address)
93 {
94   static int recursing = 0;
95   int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
96   int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
97   int pto = address & ((1 << OFF_BITS) - 1);
98
99   if (address == 0 && !recursing)
100     {
101       recursing = 1;
102       put_reg (pc, m32c_opcode_pc);
103       printf ("NULL pointer dereference at pc=0x%x\n", get_reg (pc));
104       step_result = M32C_MAKE_HIT_BREAK ();
105 #if 0
106       /* This code can be re-enabled to help diagnose NULL pointer
107          bugs that aren't debuggable in GDB.  */
108       m32c_dump_all_registers ();
109       exit (1);
110 #endif
111     }
112
113   if (pt[pt1] == 0)
114     pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
115   if (pt[pt1][pt2] == 0)
116     {
117       pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
118       memset (pt[pt1][pt2], 0, OFF_LEN);
119     }
120
121   return pt[pt1][pt2] + pto;
122 }
123
124 static void
125 used (int rstart, int i, int j)
126 {
127   int rend = i << (L2_BITS + OFF_BITS);
128   rend += j << OFF_BITS;
129   if (rstart == 0xe0000 && rend == 0xe1000)
130     return;
131   printf ("mem:   %08x - %08x (%dk bytes)\n", rstart, rend - 1,
132           (rend - rstart) / 1024);
133 }
134
135 static char *
136 mcs (int isput, int bytes)
137 {
138   return comma (mem_counters[isput][bytes]);
139 }
140
141 void
142 mem_usage_stats ()
143 {
144   int i, j;
145   int rstart = 0;
146   int pending = 0;
147
148   for (i = 0; i < L1_LEN; i++)
149     if (pt[i])
150       {
151         for (j = 0; j < L2_LEN; j++)
152           if (pt[i][j])
153             {
154               if (!pending)
155                 {
156                   pending = 1;
157                   rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
158                 }
159             }
160           else if (pending)
161             {
162               pending = 0;
163               used (rstart, i, j);
164             }
165       }
166     else
167       {
168         if (pending)
169           {
170             pending = 0;
171             used (rstart, i, 0);
172           }
173       }
174   /*       mem foo: 123456789012 123456789012 123456789012 123456789012
175             123456789012 */
176   printf ("                 byte        short      pointer         long"
177           "        fetch\n");
178   printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
179           mcs (0, 3), mcs (0, 4), mcs (0, 0));
180   printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
181           mcs (1, 3), mcs (1, 4));
182 }
183
184 static int tpr = 0;
185 static void
186 s (int address, char *dir)
187 {
188   if (tpr == 0)
189     printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir);
190   tpr++;
191 }
192
193 #define S(d) if (trace) s(address, d)
194 static void
195 e ()
196 {
197   if (!trace)
198     return;
199   tpr--;
200   if (tpr == 0)
201     printf ("\n");
202 }
203
204 #define E() if (trace) e()
205
206 extern int m32c_disassemble;
207
208 void
209 mem_put_byte (int address, unsigned char value)
210 {
211   unsigned char *m;
212   address &= membus_mask;
213   m = mem_ptr (address);
214   if (trace)
215     printf (" %02x", value);
216   *m = value;
217   switch (address)
218     {
219     case 0x00e1:
220       {
221         static int old_led = -1;
222         static char *led_on[] =
223           { "\033[31m O ", "\033[32m O ", "\033[34m O " };
224         static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " };
225         int i;
226         if (old_led != value)
227           {
228             fputs ("  ", stdout);
229             for (i = 0; i < 3; i++)
230               if (value & (1 << i))
231                 fputs (led_off[i], stdout);
232               else
233                 fputs (led_on[i], stdout);
234             fputs ("\033[0m\r", stdout);
235             fflush (stdout);
236             old_led = value;
237           }
238       }
239       break;
240 #ifdef TIMER_A
241       /* M32C Timer A */
242     case 0x346:         /* TA0low */
243       timer_a.count = (timer_a.count & 0xff00) | value;
244       timer_a.reload = timer_a.count;
245       break;
246     case 0x347:         /* TA0high */
247       timer_a.count = (timer_a.count & 0x00ff) | (value << 8);
248       timer_a.reload = timer_a.count;
249       break;
250     case 0x340:         /* TABSR */
251       timer_a.bsr = value;
252       break;
253     case 0x356:         /* TA0MR */
254       timer_a.mode = value;
255       break;
256     case 0x35f:         /* TCSPR */
257       timer_a.tcspr = value;
258       break;
259     case 0x006c:                /* TA0IC */
260       timer_a.ic = value;
261       break;
262
263       /* R8C Timer RA */
264     case 0x100:         /* TRACR */
265       timer_a.bsr = value;
266       break;
267     case 0x102:         /* TRAMR */
268       timer_a.mode = value;
269       break;
270     case 0x104:         /* TRA */
271       timer_a.count = value;
272       timer_a.reload = value;
273       break;
274     case 0x103:         /* TRAPRE */
275       timer_a.tcspr = value;
276       break;
277     case 0x0056:                /* TA0IC */
278       timer_a.ic = value;
279       break;
280 #endif
281
282     case 0x2ea:         /* m32c uart1tx */
283     case 0x3aa:         /* m16c uart1tx */
284       {
285         static int pending_exit = 0;
286         if (value == 0)
287           {
288             if (pending_exit)
289               {
290                 step_result = M32C_MAKE_EXITED (value);
291                 return;
292               }
293             pending_exit = 1;
294           }
295         else
296           {
297             write (m32c_console_ofd, &value, 1);
298           }
299       }
300       break;
301
302     case 0x400:
303       m32c_syscall (value);
304       break;
305
306     case 0x401:
307       putchar (value);
308       break;
309
310     case 0x402:
311       printf ("SimTrace: %06lx %02x\n", regs.r_pc, value);
312       break;
313
314     case 0x403:
315       printf ("SimTrap: %06lx %02x\n", regs.r_pc, value);
316       abort ();
317     }
318 }
319
320 void
321 mem_put_qi (int address, unsigned char value)
322 {
323   S ("<=");
324   mem_put_byte (address, value & 0xff);
325   E ();
326   COUNT (1, 1);
327 }
328
329 void
330 mem_put_hi (int address, unsigned short value)
331 {
332   if (address == 0x402)
333     {
334       printf ("SimTrace: %06lx %04x\n", regs.r_pc, value);
335       return;
336     }
337   S ("<=");
338   mem_put_byte (address, value & 0xff);
339   mem_put_byte (address + 1, value >> 8);
340   E ();
341   COUNT (1, 2);
342 }
343
344 void
345 mem_put_psi (int address, unsigned long value)
346 {
347   S ("<=");
348   mem_put_byte (address, value & 0xff);
349   mem_put_byte (address + 1, (value >> 8) & 0xff);
350   mem_put_byte (address + 2, value >> 16);
351   E ();
352   COUNT (1, 3);
353 }
354
355 void
356 mem_put_si (int address, unsigned long value)
357 {
358   S ("<=");
359   mem_put_byte (address, value & 0xff);
360   mem_put_byte (address + 1, (value >> 8) & 0xff);
361   mem_put_byte (address + 2, (value >> 16) & 0xff);
362   mem_put_byte (address + 3, (value >> 24) & 0xff);
363   E ();
364   COUNT (1, 4);
365 }
366
367 void
368 mem_put_blk (int address, const void *bufptr, int nbytes)
369 {
370   S ("<=");
371   if (enable_counting)
372     mem_counters[1][1] += nbytes;
373   while (nbytes--)
374     mem_put_byte (address++, *(const unsigned char *) bufptr++);
375   E ();
376 }
377
378 unsigned char
379 mem_get_pc ()
380 {
381   unsigned char *m = mem_ptr (regs.r_pc & membus_mask);
382   COUNT (0, 0);
383   return *m;
384 }
385
386 #ifdef HAVE_TERMIOS_H
387 static int console_raw = 0;
388 static struct termios oattr;
389
390 static int
391 stdin_ready ()
392 {
393   fd_set ifd;
394   int n;
395   struct timeval t;
396
397   t.tv_sec = 0;
398   t.tv_usec = 0;
399   FD_ZERO (&ifd);
400   FD_SET (m32c_console_ifd, &ifd);
401   n = select (1, &ifd, 0, 0, &t);
402   return n > 0;
403 }
404
405 void
406 m32c_sim_restore_console ()
407 {
408   if (console_raw)
409     tcsetattr (m32c_console_ifd, TCSANOW, &oattr);
410   console_raw = 0;
411 }
412 #endif
413
414 static unsigned char
415 mem_get_byte (int address)
416 {
417   unsigned char *m;
418   address &= membus_mask;
419   m = mem_ptr (address);
420   switch (address)
421     {
422 #ifdef HAVE_TERMIOS_H
423     case 0x2ed:         /* m32c uart1c1 */
424     case 0x3ad:         /* m16c uart1c1 */
425
426       if (!console_raw && m32c_use_raw_console)
427         {
428           struct termios attr;
429           tcgetattr (m32c_console_ifd, &attr);
430           tcgetattr (m32c_console_ifd, &oattr);
431           /* We want each key to be sent as the user presses them.  */
432           attr.c_lflag &= ~(ICANON | ECHO | ECHOE);
433           tcsetattr (m32c_console_ifd, TCSANOW, &attr);
434           console_raw = 1;
435           atexit (m32c_sim_restore_console);
436         }
437
438       if (stdin_ready ())
439         return 0x02;            /* tx empty and rx full */
440       else
441         return 0x0a;            /* transmitter empty */
442
443     case 0x2ee:         /* m32c uart1 rx */
444       {
445         char c;
446         read (m32c_console_ifd, &c, 1);
447         if (m32c_console_ifd == 0 && c == 3)    /* Ctrl-C */
448           {
449             printf ("Ctrl-C!\n");
450             exit (0);
451           }
452
453         if (m32c_console_ifd != 1)
454           {
455             if (isgraph (c))
456               printf ("\033[31m%c\033[0m", c);
457             else
458               printf ("\033[31m%02x\033[0m", c);
459           }
460         return c;
461       }
462 #endif
463
464 #ifdef TIMER_A
465     case 0x346:         /* TA0low */
466       return timer_a.count & 0xff;
467     case 0x347:         /* TA0high */
468       return (timer_a.count >> 8) & 0xff;
469     case 0x104:         /* TRA */
470       return timer_a.count;
471 #endif
472
473     default:
474       /* In case both cases above are not included.  */
475       ;
476     }
477
478   S ("=>");
479   if (trace)
480     printf (" %02x", *m);
481   E ();
482   return *m;
483 }
484
485 unsigned char
486 mem_get_qi (int address)
487 {
488   unsigned char rv;
489   S ("=>");
490   rv = mem_get_byte (address);
491   COUNT (0, 1);
492   E ();
493   return rv;
494 }
495
496 unsigned short
497 mem_get_hi (int address)
498 {
499   unsigned short rv;
500   S ("=>");
501   rv = mem_get_byte (address);
502   rv |= mem_get_byte (address + 1) * 256;
503   COUNT (0, 2);
504   E ();
505   return rv;
506 }
507
508 unsigned long
509 mem_get_psi (int address)
510 {
511   unsigned long rv;
512   S ("=>");
513   rv = mem_get_byte (address);
514   rv |= mem_get_byte (address + 1) * 256;
515   rv |= mem_get_byte (address + 2) * 65536;
516   COUNT (0, 3);
517   E ();
518   return rv;
519 }
520
521 unsigned long
522 mem_get_si (int address)
523 {
524   unsigned long rv;
525   S ("=>");
526   rv = mem_get_byte (address);
527   rv |= mem_get_byte (address + 1) << 8;
528   rv |= mem_get_byte (address + 2) << 16;
529   rv |= mem_get_byte (address + 3) << 24;
530   COUNT (0, 4);
531   E ();
532   return rv;
533 }
534
535 void
536 mem_get_blk (int address, void *bufptr, int nbytes)
537 {
538   S ("=>");
539   if (enable_counting)
540     mem_counters[0][1] += nbytes;
541   while (nbytes--)
542     *(char *) bufptr++ = mem_get_byte (address++);
543   E ();
544 }
545
546 int
547 sign_ext (int v, int bits)
548 {
549   if (bits < 32)
550     {
551       v &= (1 << bits) - 1;
552       if (v & (1 << (bits - 1)))
553         v -= (1 << bits);
554     }
555   return v;
556 }
557
558 #if TIMER_A
559 void
560 update_timer_a ()
561 {
562   if (timer_a.bsr & 1)
563     {
564       timer_a.prescale--;
565       if (timer_a.prescale < 0)
566         {
567           if (A24)
568             {
569               switch (timer_a.mode & 0xc0)
570                 {
571                 case 0x00:
572                   timer_a.prescale = 0;
573                   break;
574                 case 0x40:
575                   timer_a.prescale = 8;
576                   break;
577                 case 0x80:
578                   timer_a.prescale = timer_a.tcspr & 0x0f;
579                   break;
580                 case 0xc0:
581                   timer_a.prescale = 32;
582                   break;
583                 }
584             }
585           else
586             {
587               timer_a.prescale = timer_a.tcspr;
588             }
589           timer_a.count--;
590           if (timer_a.count < 0)
591             {
592               timer_a.count = timer_a.reload;
593               if (timer_a.ic & 7)
594                 {
595                   if (A24)
596                     mem_put_qi (0x6c, timer_a.ic | 0x08);
597                   else
598                     mem_put_qi (0x56, timer_a.ic | 0x08);
599                 }
600             }
601         }
602     }
603
604   if (regs.r_flags & FLAGBIT_I  /* interrupts enabled */
605       && timer_a.ic & 0x08      /* timer A interrupt triggered */
606       && (timer_a.ic & 0x07) > ((regs.r_flags >> 12) & 0x07))
607     {
608       if (A24)
609         trigger_peripheral_interrupt (12, 0x06c);
610       else
611         trigger_peripheral_interrupt (22, 0x056);
612     }
613 }
614 #endif