Subject: port-sun3/2811: [dM] code-generation bug
To: None <gnats-bugs@gnats.netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 10/06/1996 19:49:16
>Number:         2811
>Category:       port-sun3
>Synopsis:       [dM] code-generation bug
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Oct  6 17:05:00 1996
>Last-Modified:
>Originator:     der Mouse
>Organization:
	Dis-
>Release:        1.2_BETA, sup of Jul 3
>Environment:
	Seen on Sun-3/260, likely exists on any sun3, possibly other
	68k ports suffer from it.
System: NetBSD Twig.Rodents.Montreal.QC.CA 1.2_BETA NetBSD 1.2_BETA (TWIG) #0: Tue Sep 3 00:45:26 EDT 1996 mouse@Twig.Rodents.Montreal.QC.CA:/mouse/sources/working-usr-src/sys/arch/sun3/compile/TWIG sun3
>Description:
	There's a bug somewhere in the compiler's code generation.

	I do not (yet) know whether this appears in the underlying gcc
	distribution or was introduced by the NetBSD adaptation.  (The
	former seems likelier to me.)

	A loop reading
		for (; i >= 0; i--)
		  {
		    n0 = num_ptr[i];
		    __asm__ ("divu%.l %4,%1:%0"
			: "=d" ((unsigned long int)( quot_ptr[i] )),
			  "=d" ((unsigned long int)(  n1 ))
			: "0" ((unsigned long int)(  n0 )),
			  "1" ((unsigned long int)(  n1 )),
			  "dmi" ((unsigned long int)(  d ))	);
		  }
	gets miscompiled; in particular, in the resulting assembly (no
	optimization), in the fragment
			movel a6@(-12),d3
		#APP
			divul a6@(-20),d3:d2
		#NO_APP
			movel d3,d0		<<< line A
			movel d2,a0@(d0:l)	<<< line B
			movel d0,d1
			movel d1,a6@(-12)
	the lines marked "line A" and "line B" should be interchanged.
	Before the __asm__-generated instruction, d0 is correctly
	loaded with the addressing offset for the subscript store, but
	the compiler spazz causes it to try to use the remainder from
	the division as the subscript offset.  This usually segfaults;
	if the remainder is small, it may simply store into a randomly
	wrong memory location.

	Full input (and output, in case this is in some
	incomprehensible way the fault of something on this particular
	system) files are given below.  This is a stripped-down version
	of something seen while trying to install ssh 1.2.14 on
	NetBSD/sun3; it was crashing in mpn_div.  The .i file given
	here is a test case obtained by gutting cc -E output from
	mpn_div.c.
>How-To-Repeat:
	Inspect the generated assembly code in the following.
% cat bug.i
typedef	int 	ptrdiff_t;
typedef	unsigned int 	size_t;
typedef	int 	wchar_t;
typedef struct
{
  long int alloc;
  long int size;
  unsigned long int *d;
} __MP_INT;
typedef unsigned long int	mp_limb;
typedef long int		mp_limb_signed;
typedef mp_limb *		mp_ptr;
typedef const mp_limb *		mp_srcptr;
typedef long int		mp_size;
typedef struct
{
  __MP_INT  num;
  __MP_INT  den;
} MP_RAT;
void mp_set_memory_functions (void *(*) (size_t),
			      void *(*) (void *, size_t, size_t),
			      void (*) (void *, size_t));
void mpz_init (__MP_INT  *);
void mpz_set (__MP_INT  *, const __MP_INT  *);
void mpz_set_ui (__MP_INT  *, unsigned long int);
void mpz_set_si (__MP_INT  *, signed long int);
int mpz_set_str (__MP_INT  *, const char *, int);
void mpz_init_set (__MP_INT  *, const __MP_INT  *);
void mpz_init_set_ui (__MP_INT  *, unsigned long int);
void mpz_init_set_si (__MP_INT  *, signed long int);
int mpz_init_set_str (__MP_INT  *, const char *, int);
unsigned long int mpz_get_ui (const __MP_INT  *);
signed long int mpz_get_si (const __MP_INT  *);
char * mpz_get_str (char *, int, const __MP_INT  *);
void mpz_clear (__MP_INT  *);
void * _mpz_realloc (__MP_INT  *, mp_size);
void mpz_add (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_add_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_sub (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_sub_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_mul (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_mul_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_div (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_div_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_mod (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_mod_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_divmod (__MP_INT  *, __MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_divmod_ui (__MP_INT  *, __MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_mdiv (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_mdiv_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_mmod (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
unsigned long int mpz_mmod_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_mdivmod (__MP_INT  *, __MP_INT  *, const __MP_INT  *, const __MP_INT  *);
unsigned long int mpz_mdivmod_ui (__MP_INT  *, __MP_INT  *, const __MP_INT  *,
				  unsigned long int);
void mpz_sqrt (__MP_INT  *, const __MP_INT  *);
void mpz_sqrtrem (__MP_INT  *, __MP_INT  *, const __MP_INT  *);
int mpz_perfect_square_p (const __MP_INT  *);
int mpz_probab_prime_p (const __MP_INT  *, int);
void mpz_powm (__MP_INT  *, const __MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_powm_ui (__MP_INT  *, const __MP_INT  *, unsigned long int, const __MP_INT  *);
void mpz_pow_ui (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_fac_ui (__MP_INT  *, unsigned long int);
void mpz_gcd (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_gcdext (__MP_INT  *, __MP_INT  *, __MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_neg (__MP_INT  *, const __MP_INT  *);
void mpz_com (__MP_INT  *, const __MP_INT  *);
void mpz_abs (__MP_INT  *, const __MP_INT  *);
int mpz_cmp (const __MP_INT  *, const __MP_INT  *);
int mpz_cmp_ui (const __MP_INT  *, unsigned long int);
int mpz_cmp_si (const __MP_INT  *, signed long int);
void mpz_mul_2exp (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_div_2exp (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_mod_2exp (__MP_INT  *, const __MP_INT  *, unsigned long int);
void mpz_and (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_ior (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_xor (__MP_INT  *, const __MP_INT  *, const __MP_INT  *);
void mpz_array_init (__MP_INT  [], size_t, mp_size);
void mpz_random (__MP_INT  *, mp_size);
void mpz_random2 (__MP_INT  *, mp_size);
size_t mpz_size (const __MP_INT  *);
size_t mpz_sizeinbase (const __MP_INT  *, int);
void mpq_init (MP_RAT *);
void mpq_clear (MP_RAT *);
void mpq_set (MP_RAT *, const MP_RAT *);
void mpq_set_ui (MP_RAT *, unsigned long int, unsigned long int);
void mpq_set_si (MP_RAT *, signed long int, unsigned long int);
void mpq_add (MP_RAT *, const MP_RAT *, const MP_RAT *);
void mpq_sub (MP_RAT *, const MP_RAT *, const MP_RAT *);
void mpq_mul (MP_RAT *, const MP_RAT *, const MP_RAT *);
void mpq_div (MP_RAT *, const MP_RAT *, const MP_RAT *);
void mpq_neg (MP_RAT *, const MP_RAT *);
int mpq_cmp (const MP_RAT *, const MP_RAT *);
void mpq_inv (MP_RAT *, const MP_RAT *);
void mpq_set_num (MP_RAT *, const __MP_INT  *);
void mpq_set_den (MP_RAT *, const __MP_INT  *);
void mpq_get_num (__MP_INT  *, const MP_RAT *);
void mpq_get_den (__MP_INT  *, const MP_RAT *);
mp_limb mpn_add (mp_ptr, mp_srcptr, mp_size, mp_srcptr, mp_size);
mp_size mpn_sub (mp_ptr, mp_srcptr, mp_size, mp_srcptr, mp_size);
mp_size mpn_mul (mp_ptr, mp_srcptr, mp_size, mp_srcptr, mp_size);
mp_size mpn_div (mp_ptr, mp_ptr, mp_size, mp_srcptr, mp_size);
mp_limb mpn_divmod_1 (mp_ptr, mp_srcptr, mp_size, mp_limb);
mp_limb mpn_mod_1 (mp_srcptr, mp_size, mp_limb);
mp_limb mpn_lshift (mp_ptr, mp_srcptr, mp_size, unsigned int);
mp_size mpn_rshift (mp_ptr, mp_srcptr, mp_size, unsigned int);
mp_size mpn_rshiftci (mp_ptr, mp_srcptr, mp_size, unsigned int, mp_limb);
mp_size mpn_sqrt (mp_ptr, mp_ptr, mp_srcptr, mp_size);
int mpn_cmp (mp_srcptr, mp_srcptr, mp_size);
volatile void abort (void);
void *malloc (size_t);
void *realloc (void *, size_t);
void free (void *);
extern void *	(*_mp_allocate_func) (size_t);
extern void *	(*_mp_reallocate_func) (void *, size_t, size_t);
extern void	(*_mp_free_func) (void *, size_t);
void *_mp_default_allocate (size_t);
void *_mp_default_reallocate (void *, size_t, size_t);
void _mp_default_free (void *, size_t);
char *_mpz_get_str (char *, int, const __MP_INT  *);
int _mpz_set_str (__MP_INT  *, const char *, int);
void _mpz_impl_sqrt (__MP_INT  *, __MP_INT  *, const __MP_INT  *);
struct bases
{
  int chars_per_limb;
  mp_limb big_base;
  mp_limb big_base_inverted;
  float chars_per_bit_exactly;
};
extern const struct bases __mp_bases[37];
mp_size
mpn_div (mp_ptr quot_ptr,
	 mp_ptr num_ptr, mp_size num_size,
	 mp_srcptr den_ptr, mp_size den_size)
{
  mp_size q_is_long = 0;
  switch (den_size)
    {
    case 0:
      num_size = 1 / den_size;
    case 1:
      {
	mp_size i;
	mp_limb n1, n0;
	mp_limb d;
	d = den_ptr[0];
	i = num_size - 1;
	n1 = num_ptr[i];
	i--;
	if (n1 >= d)
	  {
	    q_is_long = 1;
	    n1 = 0;
	    i++;
	  }
	for (; i >= 0; i--)
	  {
	    n0 = num_ptr[i];
	    __asm__ ("divu%.l %4,%1:%0"
		: "=d" ((unsigned long int)( quot_ptr[i] )),
		  "=d" ((unsigned long int)(  n1 ))
		: "0" ((unsigned long int)(  n0 )),
		  "1" ((unsigned long int)(  n1 )),
		  "dmi" ((unsigned long int)(  d ))	);
	  }
	num_ptr[0] = n1;
      }
      break;
    }
  return q_is_long;
}
% gcc -S bug.i
% cat bug.s
#NO_APP
gcc2_compiled.:
___gnu_compiled_c:
.text
	.even
.globl _mpn_div
	.type	 _mpn_div,@function
_mpn_div:
	link a6,#-20
	movel d3,sp@-
	movel d2,sp@-
	clrl a6@(-4)
	movel a6@(24),d0
	tstl d0
	jeq L3
	moveq #1,d2
	cmpl d0,d2
	jeq L4
	jra L11
L3:
	moveq #1,d1
	divsll a6@(24),d0:d1
	movel d1,a6@(16)
L4:
	movel a6@(20),a0
	movel a0@,a6@(-20)
	movel a6@(16),d3
	subql #1,d3
	movel d3,a6@(-8)
	movel a6@(-8),d0
	movel d0,d1
	movel d1,d0
	asll #2,d0
	movel a6@(12),a0
	movel a0@(d0:l),a6@(-12)
	subql #1,a6@(-8)
	movel a6@(-12),d2
	cmpl a6@(-20),d2
	jcs L5
	moveq #1,d3
	movel d3,a6@(-4)
	clrl a6@(-12)
	addql #1,a6@(-8)
L5:
	nop
L6:
	tstl a6@(-8)
	jge L9
	jra L7
L9:
	movel a6@(-8),d0
	movel d0,d1
	movel d1,d0
	asll #2,d0
	movel a6@(12),a0
	movel a0@(d0:l),a6@(-16)
	movel a6@(-8),d0
	movel d0,d1
	movel d1,d0
	asll #2,d0
	movel a6@(8),a0
	movel a6@(-16),d2
	movel a6@(-12),d3
#APP
	divul a6@(-20),d3:d2
#NO_APP
	movel d3,d0
	movel d2,a0@(d0:l)
	movel d0,d1
	movel d1,a6@(-12)
L8:
	subql #1,a6@(-8)
	jra L6
L7:
	movel a6@(12),a0
	movel a6@(-12),a0@
	jra L2
L11:
L2:
	movel a6@(-4),d0
	jra L1
L1:
	movel a6@(-28),d2
	movel a6@(-24),d3
	unlk a6
	rts
Lfe1:
	.size	 _mpn_div,Lfe1-_mpn_div
% 
>Fix:
	Maybe someone can test whether this is the FSF's fault or ours,
	and, accordingly, either push it off to them or fix it....but
	not me.  gcc is too deep magic for me. :-)

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     01 EE 31 F6 BB 0C 34 36  00 F3 7C 5A C1 A0 67 1D
>Audit-Trail:
>Unformatted: