1/* { dg-do compile { target cris-*-* } } */
2/* { dg-options "-O2" } */
3/* { dg-final { scan-assembler "\\\.ifnc \\\$r9-\\\$r10-\\\$r11-\\\$r12" } } */
4
5/* Sanity check for asm register operands in syscall failed for
6   cris-axis-linux-gnu due to regmove bug.
7   Hans-Peter Nilsson <hp@axis.com>.  */
8
9extern void lseek64 (int, long long, int);
10extern int *__errno_location (void);
11struct dirent64
12{
13  long long d_off;
14  unsigned short int d_reclen;
15  char d_name[256];
16};
17struct kernel_dirent64
18{
19  long long d_off;
20  unsigned short d_reclen;
21  char d_name[256];
22};
23
24static inline int __attribute__ ((__always_inline__))
25__syscall_getdents64 (int fd, unsigned char * dirp, unsigned count)
26{
27  register unsigned long __sys_res asm ("r10");
28  register unsigned long __r10 __asm__ ("r10") = (unsigned long) fd;
29  register unsigned long __r11 __asm__ ("r11") = (unsigned long) dirp;
30  register unsigned long __r12 __asm__ ("r12") = (unsigned long) count;
31  register unsigned long __callno asm ("r9") = (220);
32  asm volatile (".ifnc %1-%0-%3-%4,$r9-$r10-$r11-$r12\n\t"
33		".err\n\t"
34		".endif\n\t"
35		"break 13"
36		: "=r" (__sys_res)
37		: "r" (__callno), "0" (__r10), "r" (__r11), "r" (__r12)
38		: "memory");
39  if (__sys_res >= (unsigned long) -4096)
40    {
41      (*__errno_location ()) = - __sys_res;
42      __sys_res = -1;
43    }
44  return __sys_res;
45}
46
47int
48__getdents64 (int fd, char *buf, unsigned nbytes)
49{
50  struct dirent64 *dp;
51  long long last_offset = -1;
52  int retval;
53  struct kernel_dirent64 *skdp, *kdp;
54  dp = (struct dirent64 *) buf;
55  skdp = kdp = __builtin_alloca (nbytes);
56  retval = __syscall_getdents64(fd, (char *)kdp, nbytes);
57  if (retval == -1)
58    return -1;
59  while ((char *) kdp < (char *) skdp + retval)
60    {
61      if ((char *) dp > buf + nbytes)
62	{
63	  lseek64(fd, last_offset, 0);
64	  break;
65	}
66      last_offset = kdp->d_off;
67      __builtin_memcpy (dp->d_name, kdp->d_name, kdp->d_reclen - 10);
68      dp = (struct dirent64 *) ((char *) dp + sizeof (*dp));
69      kdp = (struct kernel_dirent64 *) (((char *) kdp) + kdp->d_reclen);
70    }
71
72  return (char *) dp - buf;
73}
74