[gnu.gcc.bug] GCC bug for 68000

richards@EDDIE.MIT.EDU (Richard Sewards) (06/20/89)

I've found a code generation bug in gcc 1.34 with the 68000 code generator.
The following is the assembler output (and corresponding source lines) where
the problem occurs and after that I'm including the entire (preprocessed)
source file which generates the bug with comments at the lines where the
problem is.

Essentially, the "addqw #4,sp" instruction following lable L59 clobbers the
condition codes of the immediately preceding "movew d0,d2" instruction.
This causes the test of "rval" at line 323 ("jne L33" instruction) to be
incorrect.



#|-| 
#|-| 		/* BUG ! starts here
#|-| 		 */
#|-| 		if ((data & 0x0400   ) == 0) {
#| line 312
	btst #10,d1
	jne L38
#|-| 			rval = proc_cmd(data) ;
#| line 313
	clrl d0
	movew d1,d0
	movel d0,sp@-
	jbsr _proc_cmd
	jra L59
L38:
#|-| 		} else {
#|-| 			rval = proc_cmd_data(data) ;
#| line 315
	clrl d0
	movew d1,d0
	movel d0,sp@-
	jbsr _proc_cmd_data
L59:
	movew d0,d2
	addqw #4,sp
#|-| 		}
#|-| 		/* The condition codes reflecting the
#|-| 		 * value of rval are clobbered be the
#|-| 		 * removal of the parameters to
#|-| 		 * proc_cmd and proc_cmd_data, causing
#|-| 		 * this test to fail.
#|-| 		 */
#|-| 		if (rval != 0) {
#| line 323
	jne L33
#|-| 			break;
#| line 324
#|-| 		}
#|-| 		i_nptr = chp->in_chdb.i_nptr ;


The compile command I've been using is:
     gcc68 -m68000 -fomit-frame-pointer -O -W -Wcomment \
	   -Wreturn-type -Wunused -Wcast-qual -nostdinc -g \
	   -DDVN7189B -DDEG_ICM -Dunix -I. -ffixed-a5 -S -o bug.S -c bug.c




Complete source file starts after this line:----------------------------------


typedef int (*(PFI)) ();
typedef 	void  (*(PFV)) ();
extern  	unsigned char  proc_id;
typedef union {

	unsigned char 	*p ;
	unsigned long int 	i ;
} mach_addr ;


static inline		unsigned short int 
get_sr()
{
	unsigned short int 	sr ;
asm volatile ("	movew	sr,%0" : 
	"=dm" (sr))  ;
	return sr ;
}
static inline		void 
set_sr(v)
short int 	v ;
{
asm volatile ("	movew	%1,sr" : 
	"=m" (*((char *) 0)) : 
	"dim" (v))  ;
}
static inline		unsigned long int 	*
get_sp()
{
	unsigned long int 	*sp ;
asm volatile ("	movel	sp,%0" : 
	"=g" (sp))  ;
	return sp ;
}
static inline		void 
set_sp(p)
unsigned long int 	*p ;
{
asm volatile ("	movel	%1,sp" : 
	"=m" (*((char *) 0)) : 
	"g" (p))  ;
}
static inline		unsigned long int 	*
get_fp()
{
	unsigned long int 	*fp ;
asm volatile ("	movel	a6,%0" : 
	"=g" (fp))  ;
	return fp ;
}
static inline		void 
set_fp(p)
unsigned long int 	*p ;
{
asm volatile ("	movel	%1,a6" : 
	"=m" (*((char *) 0)) : 
	"g" (p))  ;
}
static inline 	void 
exception_return()
{
asm volatile ("	unlk	a6" : 
: 
	)  ;
asm volatile ("	rte" : 
: 
	)  ;
}




struct cm_ebiu {
	struct icf {
		unsigned char  icf_chn ;
		unsigned char  icf_msg ;
	};
	struct icf eb_to_C;
	struct icf eb_to_D;
	struct icf eb_f_C;
	struct icf eb_f_D;
	struct chn_q {
		mach_addr	chn_ptr;
		unsigned short int 		chn_len ;
	} eb_q[128	][3] ;
	unsigned char  eb_cardadr[4];
	unsigned char  eb_cardid[4];
	unsigned char  eb_lstadr[4];
};
extern struct cm_ebiu cm_ebiu;



typedef struct	{
	volatile 	unsigned short int 	biu_data ;
	volatile 	unsigned short int 	biu_cnt ;
	volatile 	unsigned short int 	biu_clr_ft ;
	volatile 	unsigned short int 	biu_clr_r ;
} biu_f ;
typedef	struct	{
	union {
		volatile 	unsigned long int 	biu_im ;
		volatile 	unsigned char 	biu_byte[4] ;
	} b_u ;
	volatile 	unsigned char 	biu_rl_lock ;
	volatile 	unsigned char 	biu_nul0 ;
	volatile 	unsigned char 	biu_nul1;
	volatile 	unsigned char 	biu_w4_lock ;
} biu_l ;

extern 	biu_f	*biu_fifo ;
extern 	biu_l	*biu_latch ;
static	inline
short int 	biu_ififo_depth(cc, nc, sl)
int	cc, nc, sl ;
{
	unsigned long int 	bus_odata ;
	unsigned char 	tbuf[4] ;
	extern		unsigned long int 	pack_addr() ;
	tbuf[0] = cc ;
	tbuf[1] = nc ;
	tbuf[2] = sl ;
	tbuf[3] = 0 ;
	bus_odata = pack_addr(tbuf) ;
asm volatile ("	movepl	%1,%0@(0)" : 
: 
	"a" ( &biu_latch[proc_id - 	2	].b_u.biu_im ) , "d" ( bus_odata)) ;  
	;
	while ((( (biu_fifo  + 0) )->biu_cnt & 0x00ff	   )  == 0) ;
	return (( (biu_fifo  + 0) )->biu_data  & 0x0800	   ) ? 255 : 63 ;
}


extern		void 	tr_init() ;
extern  struct icf *l3_ebiu_icf;
extern  struct icf *ebiu_l3_icf;
extern  struct chn_q *cmch_map[128	][3];
typedef struct {
	unsigned char  channel;
	unsigned char  msg;
} serv_q ;
typedef	struct	{
	int	srv_front ;
	int	srv_rear ;
	serv_q	srv_queue[256 ] ;
} srv_q ;
extern  srv_q	*service_q ;
static	inline	int
service_Q_empty()
{
	return (service_q->srv_front == service_q->srv_rear)  ;
}
typedef struct {
	unsigned char  channel;
	unsigned char  int_cmd;
} int_q ;
extern  int_q intq[	100		];
extern  int_q *intq_front;
extern  int_q *intq_rear;
extern  	unsigned char  intq_flag;
typedef struct local_chdb_table {
	struct general_chdb {
		unsigned char   ch_flags;
		unsigned char   channel;
		unsigned char   config;
		unsigned char   wdsize;
		unsigned short int  sfr_size;
		unsigned char   tickle;
		unsigned char   leof_seq;
		unsigned char   rack_seq;
		unsigned char   uack_seq;
		unsigned long int  destination;
		unsigned char   pend_vercmd;
		biu_f  *biu_ptr ;
		PFV    ch_fn_ptr;
	} gen_chdb;
	union gen_db_overlay {
		struct x25_ITI_overlay {
			unsigned short int  brk_timer;
			unsigned short int  brk_dura;
			unsigned short int  idle_timer;
			unsigned short int  idle_dura;
		} gen_iti;
	} gen_db;
	struct output_chdb {
		unsigned char    o_flags;
		unsigned char    *o_nptr;
		unsigned short int   o_count;
		unsigned char    o_chksum;
		unsigned long int   o_hop_partner;
		unsigned short int   o_fs;
		unsigned char    *o_eiptr;
		unsigned char    *o_eoptr;
		unsigned char    o_ebuffer[24 ];
	} out_chdb;
	union output_overlay {
		struct o_x25_iti_overlay {
			unsigned char 	forwarding[16];
		} out_iti;
	} out_db;
	struct input_chdb {
		unsigned char  i_flags;
		unsigned char   *i_nptr;
		unsigned short int  i_buflen;
		unsigned short int  i_count;
		unsigned char   *i_ctrl_ptr;
		unsigned short int  i_ctrl_count;
		unsigned short int  i_ctrl_blen;
		unsigned char  i_dbcmd_id;
		unsigned char  i_chksum;
	} in_chdb;
	union i_chdb_overlay {
		struct i_x25_iti_overlay {
			unsigned char  echo[16     ];
		} in_iti;
	} in_db;

} local_chdb ;
extern  local_chdb	*chann_map[128	];
register local_chdb	*chp asm ("a5");
extern  	unsigned char   current_sub;
static	inline	local_chdb	*
get_chdb(chan)
{
	return chann_map[chan] ;
}
extern  	unsigned char   sys_mode;
extern  	unsigned short int  time;
extern  	unsigned char   timer_flags;
extern  	unsigned char   eof_timer;
extern  	unsigned char   vcmd_timer;
extern  	char   proc_ch;
extern  volatile 	unsigned long int  *pofifo;
extern  	char   my_cc;
extern  	char   my_nc;
extern  	char   my_slot;
extern  	unsigned char  my_chan;
extern  	unsigned char  vcmd_loc;
extern  	unsigned char  rx_max;
extern  	unsigned char  tx_max;
extern  	unsigned char  rx_limit;
extern  	unsigned char  ebiu_window;
extern  	unsigned short int  biu_depth ;
extern  	unsigned char  max_frame;
extern  	unsigned char  clk_tick_msk;
extern  	unsigned short int  max_no_ipb;
extern  	unsigned short int  max_no_ctlipb;
extern  	unsigned short int  chan_count ;
extern  struct debug_s {
	unsigned char    qL3;
	unsigned char    l3msg;
	char     l3ch;
	unsigned char    dcstp;
	unsigned char    cstperr;
	unsigned char    eof;
	unsigned char    cl_reason;
	unsigned char    dtickle;
	unsigned char    dtickle_ch;
	unsigned char    dl3_qfreq;
	unsigned char    dl3_qcount;
	unsigned char    dl3_qmax;
	unsigned char    cstp_sub;
	unsigned char    cstp_fl;
	unsigned char    crl3msg;
	unsigned char    crl3msgsub;
} debug_db ;
extern		unsigned char 	proc_id ;




extern  	unsigned char  cstp_setup_msg[9			];
extern  	unsigned char  cstp_clear_msg[5			];
extern  	unsigned char  cstp_rej_msg[6			];



extern		short int 	proc_cmd(), proc_cmd_data() ;
void 
PACKET_f()
{
	unsigned long int   odata ;
	volatile 	unsigned long int   *olatch ;
	char 	chksum ;
	unsigned short int   count ;
	if ((chp->gen_chdb.ch_flags &   (	0x10	 | 	0x80	) ) ==   (	0x10	 | 	0x80	) ) {
		biu_f	  *biu_ptr = chp->gen_chdb.biu_ptr ;
		if (((biu_ptr)->biu_cnt & 0x00ff	   ) ) {
			short int 	rval = 0 ;
			unsigned char 	*i_nptr = chp->in_chdb.i_nptr ;
			unsigned short int 	i_count = chp->in_chdb.i_count ;
			chksum = chp->in_chdb.i_chksum ;
			do {
				unsigned short int 	data = (biu_ptr)->biu_data ;
				;
				if ((data & 0x0200   ) == 0) {
					chksum += data & 0x00ff ;
					*i_nptr++ = data & 0x00ff ;
					if (--i_count == 0) {
						rval =  	50	 ;
						break;
					}
				} else {
					chp->in_chdb.i_nptr = i_nptr ;
					chp->in_chdb.i_chksum = chksum ;
					chp->in_chdb.i_count = i_count ;

					/* BUG ! starts here
					 */
					if ((data & 0x0400   ) == 0) {
						rval = proc_cmd(data) ;
					} else {
						rval = proc_cmd_data(data) ;
					}
					/* The condition codes reflecting the
					 * value of rval are clobbered be the
					 * removal of the parameters to
					 * proc_cmd and proc_cmd_data, causing
					 * this test to fail.
					 */
					if (rval != 0) {
						break;
					}
					i_nptr = chp->in_chdb.i_nptr ;
					chksum = chp->in_chdb.i_chksum ;
					i_count = chp->in_chdb.i_count ;
				}
			} while (((biu_ptr)->biu_cnt & 0x00ff	   )  > 0) ;
			if (rval != 0) {
				if (rval > 0) {
					n_o_input(rval) ;
				}
			} else {
				chp->in_chdb.i_nptr = i_nptr ;
				chp->in_chdb.i_chksum = chksum ;
				chp->in_chdb.i_count = i_count ;
			}
		}
	}
	if (chp->gen_chdb.ch_flags & 	0x40	) {
		if (timer_flags & 	0x01	) {
			if (chp->gen_chdb.tickle == 0) {
				chp->gen_chdb.tickle = 4 ;
				intL3(chp->gen_chdb.channel, 47	);
				chp->gen_chdb.ch_flags &= ~	0x40	;
				return;
			}
			send_one( 	0x10		 | chp->gen_chdb.leof_seq, 0x0200   		);
			chp->gen_chdb.tickle--;
		}
	}
	if ( !(chp->out_chdb.o_flags & 	0x01	)
	    || !(chp->gen_chdb.ch_flags &  	0x20	)) {
		return;
	}
	olatch = pofifo ;
	count = ((chp->out_chdb.o_count) > ( chp->out_chdb.o_fs) ? ( chp->out_chdb.o_fs) : (chp->out_chdb.o_count)) ;
	chksum = chp->out_chdb.o_chksum ;
	odata = chp->out_chdb.o_hop_partner | 	0		 ;
	if (count > 0) {
		unsigned char 	*o_nptr = chp->out_chdb.o_nptr ;
		chp->out_chdb.o_count -= count;
		chp->out_chdb.o_fs -= count;
		do {
			unsigned char   tdata = *o_nptr++ ;
			chksum += tdata ;
asm volatile ("	movepl	%1,%0@(0)" : 
: 
			"a" (olatch) , "d" ( odata | tdata)) ;  
			;
			;
		} while (--count > 0) ;
		chp->out_chdb.o_nptr = o_nptr ;
		chp->out_chdb.o_chksum = chksum ;
	}
	if (chp->out_chdb.o_count == 0) {
		if (chp->out_chdb.o_fs >= 2) {
asm volatile ("	movepl	%1,%0@(0)" : 
: 
			"a" (olatch) , "d" ( odata | (0x48		 | 0x0200   		))) ;  
			;
asm volatile ("	movepl	%1,%0@(0)" : 
: 
			"a" (olatch) , "d" ( ((-chksum & 0x00ff) | (0x0200    | 0x0400   ) ))) ;  
			;
			chp->out_chdb.o_chksum = chksum = 0 ;
			n_o_output (59	) ;
			chp->out_chdb.o_fs -= 2 ;
		} else {
			send_eof() ;
			return ;
		}
	}
	if (chp->out_chdb.o_fs == 0) {
		send_eof() ;
	}
}

-- 
Richard Sewards                      Develcon Electronics Ltd.
UUCP: ...watmath!dvlmarv!richards    515 Consumers Road, Suite 500,
                                     Willowdale, Ont, Canada M2J 4Z2
                                     (416) 495-8666 (B)
                                     (416) 665-6248 (H)

m5@lynx.uucp (Mike McNally) (06/29/89)

gatech!dvlmarv!richards@EDDIE.MIT.EDU (Richard Sewards) writes:

>I've found a code generation bug in gcc 1.34 with the 68000 code generator.

>Essentially, the "addqw #4,sp" instruction following lable L59 clobbers the
>condition codes . . .

When the destination is an address register, "addq" does not affect 
condition codes.




-- 
Mike McNally                                    Lynx Real-Time Systems
uucp: {voder,athsys}!lynx!m5                    phone: 408 370 2233

            Where equal mind and contest equal, go.