ubsan: nds32: left shift cannot be represented in type 'int'
[deliverable/binutils-gdb.git] / sim / bfin / dv-bfin_uart.c
index be9038d39989ed57ef474ff9bd552d3207eb7944..d1bc263437ac1fbd0e7542a2834abd83fca53653 100644 (file)
@@ -1,7 +1,7 @@
 /* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
    For "old style" UARTs on BF53x/etc... parts.
 
-   Copyright (C) 2010-2011 Free Software Foundation, Inc.
+   Copyright (C) 2010-2019 Free Software Foundation, Inc.
    Contributed by Analog Devices, Inc.
 
    This file is part of simulators.
@@ -60,7 +60,8 @@ struct bfin_uart
 #define mmr_base()      offsetof(struct bfin_uart, dll)
 #define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base())
 
-static const char * const mmr_names[] = {
+static const char * const mmr_names[] =
+{
   "UART_RBR/UART_THR", "UART_IER", "UART_IIR", "UART_LCR", "UART_MCR",
   "UART_LSR", "UART_MSR", "UART_SCR", "<INV>", "UART_GCTL",
 };
@@ -73,12 +74,6 @@ static const char *mmr_name (struct bfin_uart *uart, bu32 idx)
 }
 #define mmr_name(off) mmr_name (uart, (off) / 4)
 
-#ifndef HAVE_DV_SOCKSER
-# define dv_sockser_status(sd) -1
-# define dv_sockser_write(sd, byte) do { ; } while (0)
-# define dv_sockser_read(sd) 0xff
-#endif
-
 static void
 bfin_uart_poll (struct hw *me, void *data)
 {
@@ -116,10 +111,21 @@ bfin_uart_reschedule (struct hw *me)
 }
 
 bu16
-bfin_uart_write_byte (struct hw *me, bu16 thr)
+bfin_uart_write_byte (struct hw *me, bu16 thr, bu16 mcr)
 {
+  struct bfin_uart *uart = hw_data (me);
   unsigned char ch = thr;
+
+  if (mcr & LOOP_ENA)
+    {
+      /* XXX: This probably doesn't work exactly right with
+              external FIFOs ...  */
+      uart->saved_byte = thr;
+      uart->saved_count = 1;
+    }
+
   bfin_uart_write_buffer (me, &ch, 1);
+
   return thr;
 }
 
@@ -132,14 +138,16 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
   bu32 value;
   bu16 *valuep;
 
+  /* Invalid access mode is higher priority than missing register.  */
+  if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
+    return 0;
+
   value = dv_load_2 (source);
   mmr_off = addr - uart->base;
   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
 
   HW_TRACE_WRITE ();
 
-  dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
-
   /* XXX: All MMRs are "8bit" ... what happens to high 8bits ?  */
   switch (mmr_off)
     {
@@ -148,7 +156,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
        uart->dll = value;
       else
        {
-         uart->thr = bfin_uart_write_byte (me, value);
+         uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
 
          if (uart->ier & ETBEI)
            hw_port_event (me, DV_PORT_TX, 1);
@@ -175,7 +183,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
       break;
     default:
       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
-      break;
+      return 0;
     }
 
   return nr_bytes;
@@ -183,7 +191,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
 
 /* Switch between socket and stdin on the fly.  */
 bu16
-bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh)
+bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bu16 mcr, bool *fresh)
 {
   SIM_DESC sd = hw_system (me);
   struct bfin_uart *uart = hw_data (me);
@@ -196,23 +204,26 @@ bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh)
     fresh = &_fresh;
 
   *fresh = false;
-  if (status & DV_SOCKSER_DISCONNECTED)
+
+  if (uart->saved_count > 0)
+    {
+      *fresh = true;
+      rbr = uart->saved_byte;
+      --uart->saved_count;
+    }
+  else if (mcr & LOOP_ENA)
+    {
+      /* RX is disconnected, so only return local data.  */
+    }
+  else if (status & DV_SOCKSER_DISCONNECTED)
     {
-      if (uart->saved_count > 0)
+      char byte;
+      int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
+
+      if (ret > 0)
        {
          *fresh = true;
-         rbr = uart->saved_byte;
-         --uart->saved_count;
-       }
-      else
-       {
-         char byte;
-         int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
-         if (ret > 0)
-           {
-             *fresh = true;
-             rbr = byte;
-           }
+         rbr = byte;
        }
     }
   else
@@ -238,7 +249,7 @@ bfin_uart_get_status (struct hw *me)
     }
   else
     lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) |
-                (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
+          (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
 
   return lsr;
 }
@@ -251,13 +262,15 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest,
   bu32 mmr_off;
   bu16 *valuep;
 
+  /* Invalid access mode is higher priority than missing register.  */
+  if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
+    return 0;
+
   mmr_off = addr - uart->base;
   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
 
   HW_TRACE_READ ();
 
-  dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
-
   switch (mmr_off)
     {
     case mmr_offset(dll):
@@ -265,7 +278,7 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest,
        dv_store_2 (dest, uart->dll);
       else
        {
-         uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL);
+         uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
          dv_store_2 (dest, uart->rbr);
        }
       break;
@@ -291,7 +304,7 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest,
       break;
     default:
       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
-      break;
+      return 0;
     }
 
   return nr_bytes;
@@ -374,7 +387,8 @@ bfin_uart_dma_write_buffer (struct hw *me, const void *source,
   return ret;
 }
 
-static const struct hw_port_descriptor bfin_uart_ports[] = {
+static const struct hw_port_descriptor bfin_uart_ports[] =
+{
   { "tx",   DV_PORT_TX,   0, output_port, },
   { "rx",   DV_PORT_RX,   0, output_port, },
   { "stat", DV_PORT_STAT, 0, output_port, },
@@ -431,7 +445,8 @@ bfin_uart_finish (struct hw *me)
   uart->lsr = 0x0060;
 }
 
-const struct hw_descriptor dv_bfin_uart_descriptor[] = {
+const struct hw_descriptor dv_bfin_uart_descriptor[] =
+{
   {"bfin_uart", bfin_uart_finish,},
   {NULL, NULL},
 };
This page took 0.025505 seconds and 4 git commands to generate.