* microblaze/interp.c: Add include microblaze-dis.h.
[deliverable/binutils-gdb.git] / sim / cris / traps.c
index 2eb0a1b4d24aec998cc16f96ce8abdc10d249e48..ecb43dab1109bd10ef3ea07f0bfb57974acab5b4 100644 (file)
@@ -1,28 +1,28 @@
 /* CRIS exception, interrupt, and trap (EIT) support
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Axis Communications.
 
 This file is part of the GNU simulators.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+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 "sim-main.h"
 #include "sim-options.h"
 #include "bfd.h"
 /* FIXME: get rid of targ-vals.h usage everywhere else.  */
 
+#include <stdarg.h>
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
@@ -38,6 +38,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
+/* For PATH_MAX, originally. */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+/* From ld/sysdep.h.  */
+#ifdef PATH_MAX
+# define SIM_PATHMAX PATH_MAX
+#else
+# ifdef MAXPATHLEN
+#  define SIM_PATHMAX MAXPATHLEN
+# else
+#  define SIM_PATHMAX 1024
+# endif
+#endif
 
 /* The verbatim values are from asm-cris/unistd.h.  */
 
@@ -50,6 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_time 13
 #define TARGET_SYS_lseek 19
 #define TARGET_SYS_getpid 20
+#define TARGET_SYS_access 33
 #define TARGET_SYS_kill 37
 #define TARGET_SYS_rename 38
 #define TARGET_SYS_pipe 42
@@ -72,6 +88,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_uname 122
 #define TARGET_SYS_mprotect 125
 #define TARGET_SYS_llseek 140
+#define TARGET_SYS_writev 146
 #define TARGET_SYS__sysctl 149
 #define TARGET_SYS_sched_setparam 154
 #define TARGET_SYS_sched_getparam 155
@@ -96,6 +113,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_getegid32 202
 #define TARGET_SYS_getgid32 200
 #define TARGET_SYS_fcntl64 221
+#define TARGET_SYS_set_thread_area 243
+#define TARGET_SYS_exit_group 252
 
 #define TARGET_PROT_READ       0x1
 #define TARGET_PROT_WRITE      0x2
@@ -107,6 +126,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_MAP_TYPE                0x0f
 #define TARGET_MAP_FIXED       0x10
 #define TARGET_MAP_ANONYMOUS   0x20
+#define TARGET_MAP_DENYWRITE   0x800
 
 #define TARGET_CTL_KERN                1
 #define TARGET_CTL_VM          2
@@ -126,10 +146,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define TARGET_TCGETS 0x5401
 
-#define TARGET_UTSNAME "#38 Sun Apr 1 00:00:00 MET 2001"
+#define TARGET_UTSNAME "#7 Thu Jan 1 00:00:00 MET 2009"
 
-/* Seconds since the above date + 10 minutes.  */
-#define TARGET_EPOCH 986080200
+/* Seconds since 1970-01-01 to the above date + 10 minutes;
+   'date -d "Thu Jan 1 00:00:10 MET 2009" +%s'.  */
+#define TARGET_EPOCH 1230764410
 
 /* Milliseconds since start of run.  We use the number of syscalls to
    avoid introducing noise in the execution time.  */
@@ -225,6 +246,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET___WALL 0x40000000
 #define TARGET___WCLONE 0x80000000
 
+/* From linux/limits.h. */
+#define TARGET_PIPE_BUF 4096
+
+/* From unistd.h.  */
+#define        TARGET_R_OK 4
+#define        TARGET_W_OK 2
+#define        TARGET_X_OK 1
+#define        TARGET_F_OK 0
+
 static const char stat_map[] =
 "st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
 ":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
@@ -725,6 +755,11 @@ static const CB_TARGET_DEFS_MAP open_map[] = {
   { -1, -1 }
 };
 
+/* Let's be less drastic and more traceable.  FIXME: mark as noreturn.  */
+#define abort()                                                        \
+  sim_io_error (sd, "simulator unhandled condition at %s:%d",  \
+               __FUNCTION__, __LINE__)
+
 /* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls.  */
 static SIM_CPU *current_cpu_for_cb_callback;
 
@@ -851,25 +886,25 @@ dump_statistics (SIM_CPU *current_cpu)
 
   /* For v32, unaligned_mem_dword_count should always be 0.  For
      v10, memsrc_stall_count should always be 0.  */
-  sim_io_eprintf (sd, "Memory source stall cycles: %lld\n",
-                 profp->memsrc_stall_count
-                 + profp->unaligned_mem_dword_count);
-  sim_io_eprintf (sd, "Memory read-after-write stall cycles: %lld\n",
-                 profp->memraw_stall_count);
-  sim_io_eprintf (sd, "Movem source stall cycles: %lld\n",
-                 profp->movemsrc_stall_count);
-  sim_io_eprintf (sd, "Movem destination stall cycles: %lld\n",
-                 profp->movemdst_stall_count);
-  sim_io_eprintf (sd, "Movem address stall cycles: %lld\n",
-                 profp->movemaddr_stall_count);
-  sim_io_eprintf (sd, "Multiplication source stall cycles: %lld\n",
-                 profp->mulsrc_stall_count);
-  sim_io_eprintf (sd, "Jump source stall cycles: %lld\n",
-                 profp->jumpsrc_stall_count);
-  sim_io_eprintf (sd, "Branch misprediction stall cycles: %lld\n",
-                 profp->branch_stall_count);
-  sim_io_eprintf (sd, "Jump target stall cycles: %lld\n",
-                 profp->jumptarget_stall_count);
+  sim_io_eprintf (sd, "Memory source stall cycles: %llu\n",
+                 (unsigned long long) (profp->memsrc_stall_count
+                                       + profp->unaligned_mem_dword_count));
+  sim_io_eprintf (sd, "Memory read-after-write stall cycles: %llu\n",
+                 (unsigned long long) profp->memraw_stall_count);
+  sim_io_eprintf (sd, "Movem source stall cycles: %llu\n",
+                 (unsigned long long) profp->movemsrc_stall_count);
+  sim_io_eprintf (sd, "Movem destination stall cycles: %llu\n",
+                 (unsigned long long) profp->movemdst_stall_count);
+  sim_io_eprintf (sd, "Movem address stall cycles: %llu\n",
+                 (unsigned long long) profp->movemaddr_stall_count);
+  sim_io_eprintf (sd, "Multiplication source stall cycles: %llu\n",
+                 (unsigned long long) profp->mulsrc_stall_count);
+  sim_io_eprintf (sd, "Jump source stall cycles: %llu\n",
+                 (unsigned long long) profp->jumpsrc_stall_count);
+  sim_io_eprintf (sd, "Branch misprediction stall cycles: %llu\n",
+                 (unsigned long long) profp->branch_stall_count);
+  sim_io_eprintf (sd, "Jump target stall cycles: %llu\n",
+                 (unsigned long long) profp->jumptarget_stall_count);
 }
 
 /* Check whether any part of [addr .. addr + len - 1] is already mapped.
@@ -894,7 +929,59 @@ is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
   return 0;
 }
 
-/* Create mmapped memory.  */
+/* Check whether any part of [addr .. addr + len - 1] is *un*mapped.
+   Return 1 if the whole area is mapped, 0 otherwise.  */
+
+static USI
+is_mapped_only (SIM_DESC sd ATTRIBUTE_UNUSED,
+               struct cris_sim_mmapped_page **rootp,
+               USI addr, USI len)
+{
+  struct cris_sim_mmapped_page *mapp;
+
+  if (len == 0 || (len & 8191))
+    abort ();
+
+  /* Iterate over the reverse-address sorted pages until we find a page
+     lower than the checked area.  */
+  for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
+    if (addr == mapp->addr && len == 8192)
+      return 1;
+    else if (addr + len > mapp->addr)
+      len -= 8192;
+
+  return 0;
+}
+
+/* Debug helper; to be run from gdb.  */
+
+void
+cris_dump_map (SIM_CPU *current_cpu)
+{
+  struct cris_sim_mmapped_page *mapp;
+  USI start, end;
+
+  for (mapp = current_cpu->highest_mmapped_page,
+        start = mapp == NULL ? 0 : mapp->addr + 8192,
+        end = mapp == NULL ? 0 : mapp->addr + 8191;
+       mapp != NULL;
+       mapp = mapp->prev)
+    {
+      if (mapp->addr != start - 8192)
+       {
+         sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
+         end = mapp->addr + 8191;
+       }
+
+      start = mapp->addr;
+    }
+
+  if (current_cpu->highest_mmapped_page != NULL)
+    sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
+}
+
+/* Create mmapped memory.  ADDR is -1 if any address will do.  Caller
+   must make sure that the address isn't already mapped.  */
 
 static USI
 create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
@@ -904,9 +991,9 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
   struct cris_sim_mmapped_page **higher_prevp = rootp;
   USI new_addr = 0x40000000;
 
-  if (addr != 0)
+  if (addr != (USI) -1)
     new_addr = addr;
-  else if (*rootp)
+  else if (*rootp && rootp[0]->addr >= new_addr)
     new_addr = rootp[0]->addr + 8192;
 
   if (len != 8192)
@@ -930,6 +1017,10 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
        mapp = mapp->prev)
     higher_prevp = &mapp->prev;
 
+  /* Assert for consistency that we don't create duplicate maps.  */
+  if (is_mapped (sd, rootp, new_addr, len))
+    abort ();
+
   /* Allocate the new page, on the next higher page from the last one
      allocated, and link in the new descriptor before previous ones.  */
   mapp = malloc (sizeof (*mapp));
@@ -960,6 +1051,7 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
   if (len != 8192)
     {
       USI page_addr;
+      int ret = 0;
 
       if (len & 8191)
        /* Which is better: return an error for this, or just round it up?  */
@@ -968,12 +1060,15 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
       /* Loop backwards to make each call is O(1) over the number of pages
         allocated, if we're unmapping from the high end of the pages.  */
       for (page_addr = addr + len - 8192;
-          page_addr >= addr;
+          page_addr > addr;
           page_addr -= 8192)
-       if (unmap_pages (sd, rootp, page_addr, 8192) != 0)
-         abort ();
+       if (unmap_pages (sd, rootp, page_addr, 8192))
+         ret = EINVAL;
+
+      if (unmap_pages (sd, rootp, addr, 8192))
+       ret = EINVAL;
 
-      return 0;
+      return ret;
     }
 
   for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
@@ -1006,6 +1101,7 @@ cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                   UINT srcreg ATTRIBUTE_UNUSED,
                   USI dstreg ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
@@ -1015,6 +1111,7 @@ h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED,
                    USI newval ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
@@ -1023,6 +1120,7 @@ h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                    UINT index ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
@@ -1179,6 +1277,7 @@ schedule (SIM_CPU *current_cpu, int next)
 static void
 reschedule (SIM_CPU *current_cpu)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   int i;
 
   /* Iterate over all thread slots, because after a few thread creations
@@ -1316,6 +1415,7 @@ deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
 static void
 make_first_thread (SIM_CPU *current_cpu)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   current_cpu->thread_data
     = xcalloc (1,
               SIM_TARGET_MAX_THREADS
@@ -1331,6 +1431,31 @@ make_first_thread (SIM_CPU *current_cpu)
     abort ();
 }
 
+/* Handle unknown system calls.  Returns (if it does) the syscall
+   return value.  */
+
+static USI
+cris_unknown_syscall (SIM_CPU *current_cpu, USI pc, char *s, ...)
+{
+  SIM_DESC sd = CPU_STATE (current_cpu);
+  host_callback *cb = STATE_CALLBACK (sd);
+
+  if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP
+      || cris_unknown_syscall_action == CRIS_USYSC_MSG_ENOSYS)
+    {
+      va_list ap;
+
+      va_start (ap, s);
+      sim_io_evprintf (sd, s, ap);
+      va_end (ap);
+
+      if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP)
+       sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+    }
+
+  return -cb_host_to_target_errno (cb, ENOSYS);
+}
+
 /* Main function: the handler of the "break 13" syscall insn.  */
 
 USI
@@ -1352,7 +1477,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
   s.arg2 = arg2;
   s.arg3 = arg3;
 
-  if (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0)
+  if (callnum == TARGET_SYS_exit_group
+      || (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0))
     {
       if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
          & FLAG_CRIS_MISC_PROFILE_ALL)
@@ -1449,16 +1575,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                }
              /* FALLTHROUGH */
            default:
-             /* Abort for all other cases.  */
-             sim_io_eprintf (sd, "Unimplemented %s syscall "
-                             "(fd: 0x%lx: cmd: 0x%lx arg: 0x%lx)\n",
-                             callnum == TARGET_SYS_fcntl
-                             ? "fcntl" : "fcntl64",
-                             (unsigned long) (USI) arg1,
-                             (unsigned long) (USI) arg2,
-                             (unsigned long) (USI) arg3);
-             sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                              SIM_SIGILL);
+             /* Nothing else is implemented.  */
+             retval
+               = cris_unknown_syscall (current_cpu, pc,
+                                       "Unimplemented %s syscall "
+                                       "(fd: 0x%lx: cmd: 0x%lx arg: "
+                                       "0x%lx)\n",
+                                       callnum == TARGET_SYS_fcntl
+                                       ? "fcntl" : "fcntl64",
+                                       (unsigned long) (USI) arg1,
+                                       (unsigned long) (USI) arg2,
+                                       (unsigned long) (USI) arg3);
              break;
            }
          break;
@@ -1466,16 +1593,23 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
        case TARGET_SYS_uname:
          {
            /* Fill in a few constants to appease glibc.  */
-           static const char sim_utsname[6][65] =
+           static char sim_utsname[6][65] =
            {
              "Linux",
              "sim-target",
-             "2.4.5",
+             "2.6.27",
              TARGET_UTSNAME,
-             "cris",
+             "cris",           /* Overwritten below.  */
              "localdomain"
            };
 
+           /* Having the hardware type in Linux equal to the bfd
+              printable name is deliberate: if you make config.guess
+              work on your Linux-type system the usual way, it
+              probably will; either the bfd printable_name or the
+              ambiguous arch_name.  */
+           strcpy (sim_utsname[4], STATE_ARCHITECTURE (sd)->printable_name);
+
            if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
                               sizeof (sim_utsname))
                != sizeof (sim_utsname))
@@ -1559,6 +1693,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            USI fd = arg5;
            USI pgoff = arg6;
 
+           /* At 2.6.27, Linux (many (all?) ports, in the mmap2 syscalls)
+              still masked away this bit, so let's just ignore
+              it.  */
+           flags &= ~TARGET_MAP_DENYWRITE;
+
            /* If the simulator wants to mmap more than the very large
               limit, something is wrong.  FIXME: Return an error or
               abort?  Have command-line selectable?  */
@@ -1573,23 +1712,32 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                     != (TARGET_PROT_READ
                         | TARGET_PROT_WRITE
                         | TARGET_PROT_EXEC))
+                && (prot != (TARGET_PROT_READ | TARGET_PROT_EXEC))
                 && prot != TARGET_PROT_READ)
                || (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
                    && flags != TARGET_MAP_PRIVATE
+                   && flags != (TARGET_MAP_ANONYMOUS
+                                | TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
+                   && flags != (TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
                    && flags != TARGET_MAP_SHARED)
-               || (fd != (USI) -1 && prot != TARGET_PROT_READ)
-               || pgoff != 0)
+               || (fd != (USI) -1
+                   && prot != TARGET_PROT_READ
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
+               || (fd == (USI) -1 && pgoff != 0)
+               || (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS)))
              {
-               sim_io_eprintf (sd, "Unimplemented mmap2 call "
-                               "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3,
-                               (unsigned long) arg4,
-                               (unsigned long) arg5,
-                               (unsigned long) arg6);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                                "Unimplemented mmap2 call "
+                                                "(0x%lx, 0x%lx, 0x%lx, "
+                                                "0x%lx, 0x%lx, 0x%lx)\n",
+                                                (unsigned long) arg1,
+                                                (unsigned long) arg2,
+                                                (unsigned long) arg3,
+                                                (unsigned long) arg4,
+                                                (unsigned long) arg5,
+                                                (unsigned long) arg6);
                break;
              }
            else if (fd != (USI) -1)
@@ -1602,13 +1750,25 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                /* A non-aligned argument is allowed for files.  */
                USI newlen = (len + 8191) & ~8191;
 
-               /* We only support read, which we should already have
-                  checked.  Check again anyway.  */
-               if (prot != TARGET_PROT_READ)
+               /* We only support read, read|exec, and read|write,
+                  which we should already have checked.  Check again
+                  anyway.  */
+               if (prot != TARGET_PROT_READ
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
                  abort ();
 
+               if (flags & TARGET_MAP_FIXED)
+                 unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                              addr, newlen);
+               else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
+                                   addr, newlen))
+                 addr = 0;
+
                newaddr
-                 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
+                 = create_map (sd, &current_cpu->highest_mmapped_page,
+                               addr != 0 || (flags & TARGET_MAP_FIXED)
+                               ? addr : -1,
                                newlen);
 
                if (newaddr >= (USI) -8191)
@@ -1618,6 +1778,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                    break;
                  }
 
+               /* We were asked for MAP_FIXED, but couldn't.  */
+               if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
+                 {
+                   abort ();
+                   unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                                newaddr, newlen);
+                   retval = -cb_host_to_target_errno (cb, EINVAL);
+                   break;
+                 }
+
                /* Find the current position in the file.  */
                s.func = TARGET_SYS_lseek;
                s.arg1 = fd;
@@ -1627,6 +1797,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  abort ();
                pos = s.result;
 
+               if (s.result < 0)
+                 abort ();
+
+               /* Move to the correct offset in the file.  */
+               s.func = TARGET_SYS_lseek;
+               s.arg1 = fd;
+               s.arg2 = pgoff*8192;
+               s.arg3 = SEEK_SET;
+               if (cb_syscall (cb, &s) != CB_RC_OK)
+                 abort ();
+
                if (s.result < 0)
                  abort ();
 
@@ -1639,7 +1820,9 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                if (cb_syscall (cb, &s) != CB_RC_OK)
                  abort ();
 
-               if ((USI) s.result != len)
+               /* If the result is a page or more lesser than what
+                  was requested, something went wrong.  */
+               if (len >= 8192 && (USI) s.result <= len - 8192)
                  abort ();
 
                /* After reading, we need to go back to the previous
@@ -1657,46 +1840,66 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
              }
            else
              {
-               USI newaddr
-                 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
-                               (len + 8191) & ~8191);
+               USI newlen = (len + 8191) & ~8191;
+               USI newaddr;
+
+               if (flags & TARGET_MAP_FIXED)
+                 unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                              addr, newlen);
+               else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
+                                   addr, newlen))
+                 addr = 0;
+
+               newaddr = create_map (sd, &current_cpu->highest_mmapped_page,
+                                     addr != 0 || (flags & TARGET_MAP_FIXED)
+                                     ? addr : -1,
+                                     newlen);
 
                if (newaddr >= (USI) -8191)
                  retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
                else
                  retval = newaddr;
+
+               if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
+                 {
+                   abort ();
+                   unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                                newaddr, newlen);
+                   retval = -cb_host_to_target_errno (cb, EINVAL);
+                   break;
+                 }
              }
            break;
          }
 
        case TARGET_SYS_mprotect:
          {
-           /* We only cover the case of linuxthreads mprotecting out its
-              stack guard page.  */
+           /* We only cover the case of linuxthreads mprotecting out
+              its stack guard page and of dynamic loading mprotecting
+              away the data (for some reason the whole library, then
+              mprotects away the data part and mmap-FIX:es it again.  */
            USI addr = arg1;
            USI len = arg2;
            USI prot = arg3;
 
-           if ((addr & 8191) != 0
-               || len != 8192
-               || prot != TARGET_PROT_NONE
-               || !is_mapped (sd, &current_cpu->highest_mmapped_page, addr,
-                              len))
+           if (prot != TARGET_PROT_NONE
+               || !is_mapped_only (sd, &current_cpu->highest_mmapped_page,
+                                   addr, (len + 8191) & ~8191))
              {
-               sim_io_eprintf (sd, "Unimplemented mprotect call "
-                               "(0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented mprotect call "
+                                         "(0x%lx, 0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3);
                break;
              }
 
-           /* FIXME: We should account for pages like this that are
-              "mprotected out".  For now, we just tell the simulator
-              core to remove that page from its map.  */
-           sim_core_detach (sd, NULL, 0, 0, addr);
+           /* Just ignore this.  We could make this equal to munmap,
+              but then we'd have to make sure no anon mmaps gets this
+              address before a subsequent MAP_FIXED mmap intended to
+              override it.  */
            retval = 0;
            break;
          }
@@ -1748,14 +1951,14 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || rusagep != 0
                || current_cpu->thread_data == NULL)
              {
-               sim_io_eprintf (sd, "Unimplemented wait4 call "
-                               "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3,
-                               (unsigned long) arg4);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented wait4 call "
+                                         "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3,
+                                         (unsigned long) arg4);
                break;
              }
 
@@ -1861,19 +2064,22 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                     && target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
                    || target_sa_handler == 0)
                  {
-                   sim_io_eprintf (sd, "Unimplemented rt_sigaction "
-                                   "syscall (0x%lx, "
-                                   "0x%lx: [0x%x, 0x%x, 0x%x, "
-                                   "{0x%x, 0x%x}], "
-                                   "0x%lx)\n",
-                                   (unsigned long) arg1,
-                                   (unsigned long) arg2,
-                                   target_sa_handler, target_sa_flags,
-                                   target_sa_restorer,
-                                   target_sa_mask_low, target_sa_mask_high,
-                                   (unsigned long) arg3);
-                   sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                    SIM_SIGILL);
+                   retval
+                     = cris_unknown_syscall (current_cpu, pc,
+                                             "Unimplemented rt_sigaction "
+                                             "syscall "
+                                             "(0x%lx, 0x%lx: "
+                                             "[0x%x, 0x%x, 0x%x, "
+                                             "{0x%x, 0x%x}], 0x%lx)\n",
+                                             (unsigned long) arg1,
+                                             (unsigned long) arg2,
+                                             target_sa_handler,
+                                             target_sa_flags,
+                                             target_sa_restorer,
+                                             target_sa_mask_low,
+                                             target_sa_mask_high,
+                                             (unsigned long) arg3);
+                   break;
                  }
 
                current_cpu->sighandler[signum] = target_sa_handler;
@@ -1934,7 +2140,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
                mapped_addr
                  = create_map (sd, &current_cpu->highest_mmapped_page,
-                               0, new_len);
+                               -1, new_len);
 
                if (mapped_addr > (USI) -8192)
                  {
@@ -1994,11 +2200,14 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                    || (buf.st_mode & S_IFIFO) == 0)
                || current_cpu->thread_data == NULL)
              {
-               sim_io_eprintf (sd, "Unimplemented poll syscall "
-                               "(0x%lx: [0x%x, 0x%x, x], 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1, fd, events,
-                               (unsigned long) arg2, (unsigned long) arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented poll syscall "
+                                         "(0x%lx: [0x%x, 0x%x, x], "
+                                         "0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1, fd, events,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3);
                break;
              }
 
@@ -2090,12 +2299,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            if (!((offs_hi == 0 && offs_lo >= 0)
                  || (offs_hi == -1 &&  offs_lo < 0)))
              {
-               sim_io_eprintf (sd,
-                               "Unimplemented llseek offset,"
-                               " fd %d: 0x%x:0x%x\n",
-                               fd, (unsigned) arg2, (unsigned) arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented llseek offset,"
+                                         " fd %d: 0x%x:0x%x\n",
+                                         fd, (unsigned) arg2,
+                                         (unsigned) arg3);
+               break;
              }
 
            s.func = TARGET_SYS_lseek;
@@ -2119,6 +2329,55 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
+         /* ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
+             where:
+            struct iovec {
+              void  *iov_base;    Starting address
+               size_t iov_len;     Number of bytes to transfer
+            }; */
+       case TARGET_SYS_writev:
+         {
+           SI fd = arg1;
+           SI iov = arg2;
+           SI iovcnt = arg3;
+           SI retcnt = 0;
+           int i;
+
+           /* We'll ignore strict error-handling and just do multiple write calls.  */
+           for (i = 0; i < iovcnt; i++)
+             {
+               int sysret;
+               USI iov_base
+                 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
+                                              iov + 8*i);
+               USI iov_len
+                 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
+                                              iov + 8*i + 4);
+               
+               s.func = TARGET_SYS_write;
+               s.arg1 = fd;
+               s.arg2 = iov_base;
+               s.arg3 = iov_len;
+
+               if (cb_syscall (cb, &s) != CB_RC_OK)
+                 abort ();
+               sysret = s.result == -1 ? -s.errcode : s.result;
+
+               if (sysret != iov_len)
+                 {
+                   if (i != 0)
+                     abort ();
+                   retcnt = sysret;
+                   break;
+                 }
+
+               retcnt += iov_len;
+             }
+
+           retval = retcnt;
+         }
+         break;
+
        /* This one does have a generic callback function, but at the time
           of this writing, cb_syscall does not have code for it, and we
           need target-specific code for the threads implementation
@@ -2173,11 +2432,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                && how != TARGET_SIG_SETMASK
                && how != TARGET_SIG_UNBLOCK)
              {
-               sim_io_eprintf (sd, "Unimplemented rt_sigprocmask syscall "
-                              "(0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
-               retval = 0;
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented rt_sigprocmask "
+                                         "syscall (0x%x, 0x%x, 0x%x)\n",
+                                         arg1, arg2, arg3);
                break;
              }
 
@@ -2248,17 +2507,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || (current_cpu->thread_data[threadno].cpu_context_atsignal
                    == NULL))
              {
-               sim_io_eprintf (sd, "Invalid sigreturn syscall: no signal"
-                               " handler active "
-                               "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3,
-                               (unsigned long) arg4,
-                               (unsigned long) arg5,
-                               (unsigned long) arg6);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Invalid sigreturn syscall: "
+                                         "no signal handler active "
+                                         "(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+                                         "0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3,
+                                         (unsigned long) arg4,
+                                         (unsigned long) arg5,
+                                         (unsigned long) arg6);
+               break;
              }
 
            was_sigsuspended
@@ -2324,11 +2585,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
            if (setsize != 8)
              {
-               sim_io_eprintf (sd, "Unimplemented rt_sigsuspend syscall"
-                              " arguments (0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1, (unsigned long) arg2);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented rt_sigsuspend syscall"
+                                         " arguments (0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2);
+               break;
              }
 
            /* Don't change the signal mask if we're already in
@@ -2413,8 +2676,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            USI buf = arg1;
            USI size = arg2;
 
-           char *cwd = xmalloc (MAXPATHLEN);
-           if (cwd != getcwd (cwd, MAXPATHLEN))
+           char *cwd = xmalloc (SIM_PATHMAX);
+           if (cwd != getcwd (cwd, SIM_PATHMAX))
              abort ();
 
            /* FIXME: When and if we support chdir, we need something
@@ -2435,13 +2698,63 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
+       case TARGET_SYS_access:
+         {
+           SI path = arg1;
+           SI mode = arg2;
+           char *pbuf = xmalloc (SIM_PATHMAX);
+           int i;
+           int o = 0;
+           int hmode = 0;
+
+           if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
+             {
+               strcpy (pbuf, simulator_sysroot);
+               o += strlen (simulator_sysroot);
+             }
+
+           for (i = 0; i + o < SIM_PATHMAX; i++)
+             {
+               pbuf[i + o]
+                 = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
+               if (pbuf[i + o] == 0)
+                 break;
+             }
+
+           if (i + o == SIM_PATHMAX)
+             {
+               retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
+               break;
+             }
+
+           /* Assert that we don't get calls for files for which we
+              don't have support.  */
+           if (strncmp (pbuf + strlen (simulator_sysroot),
+                        "/proc/", 6) == 0)
+             abort ();
+#define X_AFLAG(x) if (mode & TARGET_ ## x) hmode |= x
+           X_AFLAG (R_OK);
+           X_AFLAG (W_OK);
+           X_AFLAG (X_OK);
+           X_AFLAG (F_OK);
+#undef X_AFLAG
+
+           if (access (pbuf, hmode) != 0)
+             retval = -cb_host_to_target_errno (cb, errno);
+           else
+             retval = 0;
+
+           free (pbuf);
+           break;
+         }
+
        case TARGET_SYS_readlink:
          {
            SI path = arg1;
            SI buf = arg2;
            SI bufsiz = arg3;
-           char *pbuf = xmalloc (MAXPATHLEN);
-           char *lbuf = xmalloc (MAXPATHLEN);
+           char *pbuf = xmalloc (SIM_PATHMAX);
+           char *lbuf = xmalloc (SIM_PATHMAX);
            char *lbuf_alloc = lbuf;
            int nchars = -1;
            int i;
@@ -2453,7 +2766,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                o += strlen (simulator_sysroot);
              }
 
-           for (i = 0; i + o < MAXPATHLEN; i++)
+           for (i = 0; i + o < SIM_PATHMAX; i++)
              {
                pbuf[i + o]
                  = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
@@ -2461,7 +2774,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  break;
              }
 
-           if (i + o == MAXPATHLEN)
+           if (i + o == SIM_PATHMAX)
              {
                retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
                break;
@@ -2478,12 +2791,12 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
                if (argv0 == NULL || *argv0 == '.')
                  {
-                   sim_io_eprintf (sd, "Unimplemented readlink syscall "
-                                   "(0x%lx: [\"%s\"], 0x%lx)\n",
-                                   (unsigned long) arg1, pbuf,
-                                   (unsigned long) arg2);
-                   sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                    SIM_SIGILL);
+                   retval
+                     = cris_unknown_syscall (current_cpu, pc,
+                                             "Unimplemented readlink syscall "
+                                             "(0x%lx: [\"%s\"], 0x%lx)\n",
+                                             (unsigned long) arg1, pbuf,
+                                             (unsigned long) arg2);
                    break;
                  }
                else if (*argv0 == '/')
@@ -2497,8 +2810,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  }
                else
                  {
-                   if (getcwd (lbuf, MAXPATHLEN) != NULL
-                       && strlen (lbuf) + 2 + strlen (argv0) < MAXPATHLEN)
+                   if (getcwd (lbuf, SIM_PATHMAX) != NULL
+                       && strlen (lbuf) + 2 + strlen (argv0) < SIM_PATHMAX)
                      {
                        if (strncmp (simulator_sysroot, lbuf,
                                     strlen (simulator_sysroot)) == 0)
@@ -2513,7 +2826,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  }
              }
            else
-             nchars = readlink (pbuf, lbuf, MAXPATHLEN);
+             nchars = readlink (pbuf, lbuf, SIM_PATHMAX);
 
            /* We trust that the readlink result returns a *relative*
               link, or one already adjusted for the file-path-prefix.
@@ -2716,19 +3029,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                break;
              }
 
-           sim_io_eprintf (sd, "Unimplemented _sysctl syscall "
-                           "(0x%lx: [0x%lx, 0x%lx],"
-                           " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                           (unsigned long) name,
-                           (unsigned long) name0,
-                           (unsigned long) name1,
-                           (unsigned long) nlen,
-                           (unsigned long) oldval,
-                           (unsigned long) oldlenp,
-                           (unsigned long) newval,
-                           (unsigned long) newlen);
-           sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                            SIM_SIGILL);
+           retval
+             = cris_unknown_syscall (current_cpu, pc,
+                                     "Unimplemented _sysctl syscall "
+                                     "(0x%lx: [0x%lx, 0x%lx],"
+                                     " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                                     (unsigned long) name,
+                                     (unsigned long) name0,
+                                     (unsigned long) name1,
+                                     (unsigned long) nlen,
+                                     (unsigned long) oldval,
+                                     (unsigned long) oldlenp,
+                                     (unsigned long) newval,
+                                     (unsigned long) newlen);
            break;
          }
 
@@ -2801,11 +3114,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                 | TARGET_CLONE_SIGHAND)
                || newsp == 0)
              {
-               sim_io_eprintf (sd,
-                               "Unimplemented clone syscall (0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1, (unsigned long) arg2);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented clone syscall "
+                                         "(0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2);
+               break;
              }
 
            if (current_cpu->thread_data == NULL)
@@ -2866,13 +3181,25 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
          retval = -cb_host_to_target_errno (cb, ENOSYS);
          break;
 
+       case TARGET_SYS_set_thread_area:
+         /* Do the same error check as Linux.  */
+         if (arg1 & 255)
+           {
+             retval = -cb_host_to_target_errno (cb, EINVAL);
+             break;
+           }
+         (*current_cpu->set_target_thread_data) (current_cpu, arg1);
+         retval = 0;
+         break;
+
        unimplemented_syscall:
        default:
-         sim_io_eprintf (sd, "Unimplemented syscall: %d "
-                         "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", callnum,
-                         arg1, arg2, arg3, arg4, arg5, arg6);
-         sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                          SIM_SIGILL);
+         retval
+           = cris_unknown_syscall (current_cpu, pc,
+                                   "Unimplemented syscall: %d "
+                                   "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+                                   callnum, arg1, arg2, arg3, arg4, arg5,
+                                   arg6);
        }
     }
 
@@ -2882,6 +3209,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
       current_cpu->last_open_fd = retval;
       current_cpu->last_open_flags = arg2;
     }
+
   current_cpu->last_syscall = callnum;
 
   /* A system call is a rescheduling point.  For the time being, we don't
@@ -2956,13 +3284,15 @@ cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
 
 static void
 cris_pipe_empty (host_callback *cb,
-                int reader ATTRIBUTE_UNUSED,
+                int reader,
                 int writer)
 {
   int i;
   SIM_CPU *cpu = current_cpu_for_cb_callback;
+  SIM_DESC sd = CPU_STATE (current_cpu_for_cb_callback);
   bfd_byte r10_buf[4];
-  int remaining = cb->pipe_buffer[writer].size;
+  int remaining
+    = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size;
 
   /* We need to find the thread that waits for this pipe.  */
   for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
@@ -2970,6 +3300,7 @@ cris_pipe_empty (host_callback *cb,
        && cpu->thread_data[i].pipe_write_fd == writer)
       {
        int retval;
+
        /* Temporarily switch to this cpu context, so we can change the
           PC by ordinary calls.  */
 
@@ -2980,19 +3311,25 @@ cris_pipe_empty (host_callback *cb,
                cpu->thread_data[i].cpu_context,
                cpu->thread_cpu_data_size);
 
-       /* The return value is supposed to contain the number of written
-          bytes, which is the number of bytes requested and returned at
-          the write call.  We subtract the remaining bytes from that,
-          but making sure we still get a positive number.
-          The return value may also be a negative number; an error
-          value.  We cover this case by comparing against remaining,
-          which is always >= 0.  */
+       /* The return value is supposed to contain the number of
+          written bytes, which is the number of bytes requested and
+          returned at the write call.  You might think the right
+          thing is to adjust the return-value to be only the
+          *consumed* number of bytes, but it isn't.  We're only
+          called if the pipe buffer is fully consumed or it is being
+          closed, possibly with remaining bytes.  For the latter
+          case, the writer is still supposed to see success for
+          PIPE_BUF bytes (a constant which we happen to know and is
+          unlikely to change).  The return value may also be a
+          negative number; an error value.  This case is covered
+          because "remaining" is always >= 0.  */
        (*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
        retval = (int) bfd_getl_signed_32 (r10_buf);
-       if (retval >= remaining)
-         bfd_putl32 (retval - remaining, r10_buf);
-       (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
-
+       if (retval - remaining > TARGET_PIPE_BUF)
+         {
+           bfd_putl32 (retval - remaining, r10_buf);
+           (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
+         }
        sim_pc_set (cpu, sim_pc_get (cpu) + 2);
        memcpy (cpu->thread_data[i].cpu_context,
                &cpu->cpu_data_placeholder,
This page took 0.039316 seconds and 4 git commands to generate.