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.