1  /* { dg-do run } */
       2  /* { dg-options "-std=c99" } */
       3  
       4  extern int printf (const char *, ...);
       5  extern void abort (void) __attribute__((noreturn));
       6  
       7  typedef unsigned long uint32;
       8  typedef unsigned long long uint64;
       9  
      10  extern uint32 __mspabi_divul (uint32, uint32);
      11  extern uint32 __mspabi_divlu (uint32, uint32);
      12  extern uint64 __mspabi_divull (uint64, uint64);
      13  extern uint64 __mspabi_divllu (uint64, uint64);
      14  
      15  uint32 func1 (uint32, uint32) __attribute__ ((noinline));
      16  uint32 func2 (uint32, uint32) __attribute__ ((noinline));
      17  uint32 func3 (uint32, uint32) __attribute__ ((noinline));
      18  uint64 func4 (uint64, uint64) __attribute__ ((noinline));
      19  uint64 func5 (uint64, uint64) __attribute__ ((noinline));
      20  uint64 func6 (uint64, uint64) __attribute__ ((noinline));
      21  
      22  
      23  #define DEBUG 0
      24  
      25  int
      26  main (void)
      27  {
      28    int fail = 0;
      29  
      30    if (func1 (7UL, 3UL) != 2UL)
      31      {
      32  #if DEBUG
      33        printf ("FAIL: func1: 7 / 3 returns %lu\n", func1 (7UL, 3UL));
      34  #endif
      35        ++ fail;
      36      }
      37  
      38    if (func2 (7UL, 3UL) != 2UL)
      39      {
      40  #if DEBUG
      41        printf ("FAIL: func2: 7 / 3 returns %lu\n", func2 (7UL, 3UL));
      42  #endif
      43        ++ fail;
      44      }
      45  
      46    if (func3 (7UL, 3UL) != 2UL)
      47      {
      48  #if DEBUG
      49        printf ("FAIL: func4: 7 / 3 returns %lu\n", func3 (7UL, 3UL));
      50  #endif
      51        ++ fail;
      52      }
      53  
      54    if (func4 (7ULL, 3ULL) != 2ULL)
      55      {
      56  #if DEBUG
      57        printf ("FAIL: func4: 7 / 3 returns %llu\n", func4 (7ULL, 3ULL));
      58  #endif
      59        ++ fail;
      60      }
      61  
      62    if (func5 (7ULL, 3ULL) != 2ULL)
      63      {
      64  #if DEBUG
      65        printf ("FAIL: func5: 7 / 3 returns %llu\n", func5 (7ULL, 3ULL));
      66  #endif
      67        ++ fail;
      68      }
      69  
      70    if (func6 (7ULL, 3ULL) != 2ULL)
      71      {
      72  #if DEBUG
      73        printf ("FAIL: func6: 7 / 3 returns %llu\n", func6 (7ULL, 3ULL));
      74  #endif
      75        ++ fail;
      76      }
      77  
      78    if (fail)
      79      abort ();
      80  
      81    return 0;
      82  }
      83  
      84  /* At high levels of optimization gcc will probably fold func1 and func4 into
      85     main, but this does not really matter.  Those two functions are just there
      86     for a sanity check at low levels of optimization.  */
      87  			      
      88  uint32 func1 (uint32 a, uint32 b) { return a / b; }
      89  uint32 func2 (uint32 a, uint32 b) { return __mspabi_divul (a, b); }
      90  uint32 func3 (uint32 a, uint32 b) { return __mspabi_divlu (a, b); }
      91  uint64 func4 (uint64 a, uint64 b) { return a / b; }
      92  uint64 func5 (uint64 a, uint64 b) { return __mspabi_divull (a, b); }
      93  
      94  uint64
      95  func6 (uint64 a, uint64 b)
      96  {
      97    uint64 ret;
      98  
      99    /* This test function is special.  The correctly spelt ABI function
     100       __mspabi_divull takes its first argument in registers R8::R11 and its
     101       second argument in registers R12::R15, but GCC knows that __mspabi_divllu
     102       is not the correct spelling and so it will use the normal function
     103       calling convention - first argument in R12::R15, second argument on the
     104       stack.
     105       
     106       The stub function for __mspabi_divllu in libgcc just does a BRAnch to
     107       the real __mspabi_divull function - it does *not* rearrange the arguments
     108       or pull anything off the stack.  This is correct, because in real code
     109       that calls __mspabi_divllu, compiled by *old* versions of gcc, the
     110       arguments will already be in the special ABI mandated locations.
     111  
     112       As a result, in order to test __mspabi_divllu here, we have to put the
     113       arguments into the correct registers ourselves and call __mspabi_divllu
     114       manually.  This does lead to some very inefficient code generation, but
     115       that is not our concern here.  */
     116  
     117  #ifdef __MSP430X_LARGE__
     118    __asm ("mov  %A1, r8\n\
     119          mov  %B1, r9\n\
     120          mov  %C1, r10\n\
     121          mov  %D1, r11\n\
     122          mov  %A2, r12\n\
     123          mov  %B2, r13\n\
     124          mov  %C2, r14\n\
     125          mov  %D2, r15\n\
     126          calla #__mspabi_divllu\n\
     127          mov  r12, %A0\n\
     128          mov  r13, %B0\n\
     129          mov  r14, %C0\n\
     130          mov  r15, %D0\n"
     131  	     : "=r" (ret) : "r" (a), "m" (b));
     132  #else
     133    __asm ("mov  %A1, r8\n\
     134          mov  %B1, r9\n\
     135          mov  %C1, r10\n\
     136          mov  %D1, r11\n\
     137          mov  %A2, r12\n\
     138          mov  %B2, r13\n\
     139          mov  %C2, r14\n\
     140          mov  %D2, r15\n\
     141          call #__mspabi_divllu\n\
     142          mov  r12, %A0\n\
     143          mov  r13, %B0\n\
     144          mov  r14, %C0\n\
     145          mov  r15, %D0\n"
     146  	     : "=r" (ret) : "r" (a), "m" (b));
     147  #endif
     148  
     149    return ret;
     150  }