Remove ATTRIBUTE_UNUSED check from ARI
[deliverable/binutils-gdb.git] / sim / m32c / mem.c
index 432162916bb17d88ffa3ce3c7e03e5b089ca4333..e85c7edd3145e24400eb0dd2f7c9dd085890515a 100644 (file)
@@ -1,6 +1,6 @@
 /* mem.c --- memory for M32C simulator.
 
-Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+Copyright (C) 2005-2019 Free Software Foundation, Inc.
 Contributed by Red Hat, Inc.
 
 This file is part of the GNU simulators.
@@ -19,14 +19,29 @@ You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
+#include "config.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
 
 #include "mem.h"
 #include "cpu.h"
 #include "syscalls.h"
 #include "misc.h"
+#ifdef TIMER_A
+#include "int.h"
+#include "timer_a.h"
+#endif
 
 #define L1_BITS  (10)
 #define L2_BITS  (10)
@@ -38,8 +53,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 static unsigned char **pt[L1_LEN];
 
+#ifdef HAVE_TERMIOS_H
+int m32c_console_ifd = 0;
+#endif
+int m32c_console_ofd = 1;
+#ifdef HAVE_TERMIOS_H
+int m32c_use_raw_console = 0;
+#endif
+
+#ifdef TIMER_A
+Timer_A timer_a;
+#endif
+
 /* [ get=0/put=1 ][ byte size ] */
-static unsigned int mem_counters[2][4];
+static unsigned int mem_counters[2][5];
 
 #define COUNT(isput,bytes)                                      \
   if (verbose && enable_counting) mem_counters[isput][bytes]++
@@ -62,16 +89,25 @@ init_mem (void)
 }
 
 static unsigned char *
-mem_ptr (address)
+mem_ptr (int address)
 {
+  static int recursing = 0;
   int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
   int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
   int pto = address & ((1 << OFF_BITS) - 1);
 
-  if (address == 0)
+  if (address == 0 && !recursing)
     {
-      printf ("NULL pointer dereference\n");
+      recursing = 1;
+      put_reg (pc, m32c_opcode_pc);
+      printf ("NULL pointer dereference at pc=0x%x\n", get_reg (pc));
+      step_result = M32C_MAKE_HIT_BREAK ();
+#if 0
+      /* This code can be re-enabled to help diagnose NULL pointer
+         bugs that aren't debuggable in GDB.  */
+      m32c_dump_all_registers ();
       exit (1);
+#endif
     }
 
   if (pt[pt1] == 0)
@@ -103,7 +139,7 @@ mcs (int isput, int bytes)
 }
 
 void
-mem_usage_stats ()
+mem_usage_stats (void)
 {
   int i, j;
   int rstart = 0;
@@ -138,7 +174,7 @@ mem_usage_stats ()
   /*       mem foo: 123456789012 123456789012 123456789012 123456789012
             123456789012 */
   printf ("                 byte        short      pointer         long"
-          "        fetch\n");
+         "        fetch\n");
   printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
          mcs (0, 3), mcs (0, 4), mcs (0, 0));
   printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
@@ -156,7 +192,7 @@ s (int address, char *dir)
 
 #define S(d) if (trace) s(address, d)
 static void
-e ()
+e (void)
 {
   if (!trace)
     return;
@@ -167,7 +203,9 @@ e ()
 
 #define E() if (trace) e()
 
-void
+extern int m32c_disassemble;
+
+static void
 mem_put_byte (int address, unsigned char value)
 {
   unsigned char *m;
@@ -199,21 +237,65 @@ mem_put_byte (int address, unsigned char value)
          }
       }
       break;
+#ifdef TIMER_A
+      /* M32C Timer A */
+    case 0x346:                /* TA0low */
+      timer_a.count = (timer_a.count & 0xff00) | value;
+      timer_a.reload = timer_a.count;
+      break;
+    case 0x347:                /* TA0high */
+      timer_a.count = (timer_a.count & 0x00ff) | (value << 8);
+      timer_a.reload = timer_a.count;
+      break;
+    case 0x340:                /* TABSR */
+      timer_a.bsr = value;
+      break;
+    case 0x356:                /* TA0MR */
+      timer_a.mode = value;
+      break;
+    case 0x35f:                /* TCSPR */
+      timer_a.tcspr = value;
+      break;
+    case 0x006c:               /* TA0IC */
+      timer_a.ic = value;
+      break;
+
+      /* R8C Timer RA */
+    case 0x100:                /* TRACR */
+      timer_a.bsr = value;
+      break;
+    case 0x102:                /* TRAMR */
+      timer_a.mode = value;
+      break;
+    case 0x104:                /* TRA */
+      timer_a.count = value;
+      timer_a.reload = value;
+      break;
+    case 0x103:                /* TRAPRE */
+      timer_a.tcspr = value;
+      break;
+    case 0x0056:               /* TA0IC */
+      timer_a.ic = value;
+      break;
+#endif
 
-    case 0x3aa: /* uart1tx */
+    case 0x2ea:                /* m32c uart1tx */
+    case 0x3aa:                /* m16c uart1tx */
       {
        static int pending_exit = 0;
        if (value == 0)
          {
            if (pending_exit)
              {
-               step_result = M32C_MAKE_EXITED(value);
+               step_result = M32C_MAKE_EXITED (value);
                return;
              }
            pending_exit = 1;
          }
        else
-         putchar(value);
+         {
+           write (m32c_console_ofd, &value, 1);
+         }
       }
       break;
 
@@ -283,42 +365,119 @@ mem_put_si (int address, unsigned long value)
 }
 
 void
-mem_put_blk (int address, void *bufptr, int nbytes)
+mem_put_blk (int address, const void *bufptr, int nbytes)
 {
   S ("<=");
   if (enable_counting)
     mem_counters[1][1] += nbytes;
   while (nbytes--)
-    mem_put_byte (address++, *(unsigned char *) bufptr++);
+    mem_put_byte (address++, *(const unsigned char *) bufptr++);
   E ();
 }
 
 unsigned char
-mem_get_pc ()
+mem_get_pc (void)
 {
   unsigned char *m = mem_ptr (regs.r_pc & membus_mask);
   COUNT (0, 0);
   return *m;
 }
 
+#ifdef HAVE_TERMIOS_H
+static int console_raw = 0;
+static struct termios oattr;
+
+static int
+stdin_ready (void)
+{
+  fd_set ifd;
+  int n;
+  struct timeval t;
+
+  t.tv_sec = 0;
+  t.tv_usec = 0;
+  FD_ZERO (&ifd);
+  FD_SET (m32c_console_ifd, &ifd);
+  n = select (1, &ifd, 0, 0, &t);
+  return n > 0;
+}
+
+void
+m32c_sim_restore_console (void)
+{
+  if (console_raw)
+    tcsetattr (m32c_console_ifd, TCSANOW, &oattr);
+  console_raw = 0;
+}
+#endif
+
 static unsigned char
 mem_get_byte (int address)
 {
   unsigned char *m;
   address &= membus_mask;
-  S ("=>");
   m = mem_ptr (address);
   switch (address)
     {
-    case 0x3ad: /* uart1c1 */
-      E();
-      return 2; /* transmitter empty */
-      break;
-    default: 
-      if (trace)
-       printf (" %02x", *m);
-      break;
+#ifdef HAVE_TERMIOS_H
+    case 0x2ed:                /* m32c uart1c1 */
+    case 0x3ad:                /* m16c uart1c1 */
+
+      if (!console_raw && m32c_use_raw_console)
+       {
+         struct termios attr;
+         tcgetattr (m32c_console_ifd, &attr);
+         tcgetattr (m32c_console_ifd, &oattr);
+         /* We want each key to be sent as the user presses them.  */
+         attr.c_lflag &= ~(ICANON | ECHO | ECHOE);
+         tcsetattr (m32c_console_ifd, TCSANOW, &attr);
+         console_raw = 1;
+         atexit (m32c_sim_restore_console);
+       }
+
+      if (stdin_ready ())
+       return 0x02;            /* tx empty and rx full */
+      else
+       return 0x0a;            /* transmitter empty */
+
+    case 0x2ee:                /* m32c uart1 rx */
+      {
+       char c;
+       read (m32c_console_ifd, &c, 1);
+       if (m32c_console_ifd == 0 && c == 3)    /* Ctrl-C */
+         {
+           printf ("Ctrl-C!\n");
+           exit (0);
+         }
+
+       if (m32c_console_ifd != 1)
+         {
+           if (isgraph (c))
+             printf ("\033[31m%c\033[0m", c);
+           else
+             printf ("\033[31m%02x\033[0m", c);
+         }
+       return c;
+      }
+#endif
+
+#ifdef TIMER_A
+    case 0x346:                /* TA0low */
+      return timer_a.count & 0xff;
+    case 0x347:                /* TA0high */
+      return (timer_a.count >> 8) & 0xff;
+    case 0x104:                /* TRA */
+      return timer_a.count;
+#endif
+
+    default:
+      /* In case both cases above are not included.  */
+      ;
     }
+
+  S ("=>");
+  if (trace)
+    printf (" %02x", *m);
   E ();
   return *m;
 }
@@ -395,3 +554,61 @@ sign_ext (int v, int bits)
     }
   return v;
 }
+
+#if TIMER_A
+void
+update_timer_a (void)
+{
+  if (timer_a.bsr & 1)
+    {
+      timer_a.prescale--;
+      if (timer_a.prescale < 0)
+       {
+         if (A24)
+           {
+             switch (timer_a.mode & 0xc0)
+               {
+               case 0x00:
+                 timer_a.prescale = 0;
+                 break;
+               case 0x40:
+                 timer_a.prescale = 8;
+                 break;
+               case 0x80:
+                 timer_a.prescale = timer_a.tcspr & 0x0f;
+                 break;
+               case 0xc0:
+                 timer_a.prescale = 32;
+                 break;
+               }
+           }
+         else
+           {
+             timer_a.prescale = timer_a.tcspr;
+           }
+         timer_a.count--;
+         if (timer_a.count < 0)
+           {
+             timer_a.count = timer_a.reload;
+             if (timer_a.ic & 7)
+               {
+                 if (A24)
+                   mem_put_qi (0x6c, timer_a.ic | 0x08);
+                 else
+                   mem_put_qi (0x56, timer_a.ic | 0x08);
+               }
+           }
+       }
+    }
+
+  if (regs.r_flags & FLAGBIT_I /* interrupts enabled */
+      && timer_a.ic & 0x08     /* timer A interrupt triggered */
+      && (timer_a.ic & 0x07) > ((regs.r_flags >> 12) & 0x07))
+    {
+      if (A24)
+       trigger_peripheral_interrupt (12, 0x06c);
+      else
+       trigger_peripheral_interrupt (22, 0x056);
+    }
+}
+#endif
This page took 0.037987 seconds and 4 git commands to generate.