This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/10733] Modulus bug
- From: "ericw at evcohs dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 30 Aug 2004 18:47:25 -0000
- Subject: [Bug target/10733] Modulus bug
- References: <20030510153600.10733.jbright@winfordeng.com>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Additional Comments From ericw at evcohs dot com 2004-08-30 18:47 -------
In comment #5 the inline assembly at the end of the preprocessed source comes
from an old version of avr-libc (the Standard C library for AVR GCC)
<http://savannah.nongnu.org/projects/avr-libc/>, which comes from the outp()
macros. In the later versions of avr-libc, the implementation of outp() was
changed and is now deprecated. This is also the reason why Kazu Hirata wrote the
reduction found in comment #8.
The test case in comment #4 can be changed to:
--------- bug10733a.c -------------
#include <avr/io.h>
int main(void)
{
unsigned char t1;
t1=40;
t1=(t1 + 2)%30;
DDRB = 0xff;
PORTB = t1;
return(0);
}
------------------------------
Using avr-gcc 3.3.2 gives the following preprocessed source:
------------------------------
# 1 "bug10733a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "bug10733a.c"
# 1 "c:/WinAVR/avr/include/avr/io.h" 1 3
# 81 "c:/WinAVR/avr/include/avr/io.h" 3
# 1 "c:/WinAVR/avr/include/avr/sfr_defs.h" 1 3
# 121 "c:/WinAVR/avr/include/avr/sfr_defs.h" 3
# 1 "c:/WinAVR/avr/include/inttypes.h" 1 3
# 67 "c:/WinAVR/avr/include/inttypes.h" 3
typedef signed char int8_t;
typedef unsigned char uint8_t;
# 90 "c:/WinAVR/avr/include/inttypes.h" 3
typedef int int16_t;
typedef unsigned int uint16_t;
# 106 "c:/WinAVR/avr/include/inttypes.h" 3
typedef long int32_t;
typedef unsigned long uint32_t;
# 124 "c:/WinAVR/avr/include/inttypes.h" 3
typedef long long int64_t;
typedef unsigned long long uint64_t;
# 141 "c:/WinAVR/avr/include/inttypes.h" 3
typedef int16_t intptr_t;
typedef uint16_t uintptr_t;
# 122 "c:/WinAVR/avr/include/avr/sfr_defs.h" 2 3
# 82 "c:/WinAVR/avr/include/avr/io.h" 2 3
# 189 "c:/WinAVR/avr/include/avr/io.h" 3
# 1 "c:/WinAVR/avr/include/avr/io8535.h" 1 3
# 190 "c:/WinAVR/avr/include/avr/io.h" 2 3
# 229 "c:/WinAVR/avr/include/avr/io.h" 3
# 1 "c:/WinAVR/avr/include/avr/portpins.h" 1 3
# 230 "c:/WinAVR/avr/include/avr/io.h" 2 3
# 2 "bug10733a.c" 2
int main(void)
{
unsigned char t1;
t1=40;
t1=(t1 + 2)%30;
(*(volatile uint8_t *)((0x17) + 0x20)) = 0xff;
(*(volatile uint8_t *)((0x18) + 0x20)) = t1;
return(0);
}
------------------------------
and also compiles to (mixed C and assembly listing):
------------------------------
3:bug10733a.c **** int main(void)
4:bug10733a.c **** {
61 .LM1:
62 /* prologue: frame size=0 */
63 0000 C0E0 ldi r28,lo8(__stack - 0)
64 0002 D0E0 ldi r29,hi8(__stack - 0)
65 0004 DEBF out __SP_H__,r29
66 0006 CDBF out __SP_L__,r28
67 /* prologue end (size=4) */
5:bug10733a.c **** unsigned char t1;
6:bug10733a.c ****
7:bug10733a.c **** t1=40;
8:bug10733a.c **** t1=(t1 + 2)%30;
69 .LM2:
70 .LBB2:
71 0008 8AE2 ldi r24,lo8(42)
72 000a 90E0 ldi r25,hi8(42)
73 000c 6EE1 ldi r22,lo8(30)
74 000e 70E0 ldi r23,hi8(30)
75 0010 00D0 rcall __divmodhi4
76 0012 282F mov r18,r24
77 0014 392F mov r19,r25
9:bug10733a.c ****
10:bug10733a.c **** DDRB = 0xff;
79 .LM3:
80 0016 8FEF ldi r24,lo8(-1)
81 0018 87BB out 55-0x20,r24
11:bug10733a.c **** PORTB = t1;
83 .LM4:
84 001a 28BB out 56-0x20,r18
12:bug10733a.c ****
13:bug10733a.c **** return(0);
14:bug10733a.c **** }
86 .LM5:
87 .LBE2:
88 001c 80E0 ldi r24,lo8(0)
89 001e 90E0 ldi r25,hi8(0)
90 /* epilogue: frame size=0 */
91 0020 00C0 rjmp exit
92 /* epilogue end (size=1) */
------------------------------
Note the call to __divmodhi4 above. This is the same as the original bug report.
In comment #3, the OP gave a workaround as such:
--------- bug10733b.c ------------
#include <avr/io.h>
int main(void)
{
unsigned char t1;
t1=2;
t1=t1+40;
t1%=30;
DDRB = 0xff;
PORTB = t1;
return(0);
}
------------------------------
Preprocessed source:
------------------------------
# 1 "bug10733b.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "bug10733b.c"
# 1 "c:/WinAVR/avr/include/avr/io.h" 1 3
# 81 "c:/WinAVR/avr/include/avr/io.h" 3
# 1 "c:/WinAVR/avr/include/avr/sfr_defs.h" 1 3
# 121 "c:/WinAVR/avr/include/avr/sfr_defs.h" 3
# 1 "c:/WinAVR/avr/include/inttypes.h" 1 3
# 67 "c:/WinAVR/avr/include/inttypes.h" 3
typedef signed char int8_t;
typedef unsigned char uint8_t;
# 90 "c:/WinAVR/avr/include/inttypes.h" 3
typedef int int16_t;
typedef unsigned int uint16_t;
# 106 "c:/WinAVR/avr/include/inttypes.h" 3
typedef long int32_t;
typedef unsigned long uint32_t;
# 124 "c:/WinAVR/avr/include/inttypes.h" 3
typedef long long int64_t;
typedef unsigned long long uint64_t;
# 141 "c:/WinAVR/avr/include/inttypes.h" 3
typedef int16_t intptr_t;
typedef uint16_t uintptr_t;
# 122 "c:/WinAVR/avr/include/avr/sfr_defs.h" 2 3
# 82 "c:/WinAVR/avr/include/avr/io.h" 2 3
# 189 "c:/WinAVR/avr/include/avr/io.h" 3
# 1 "c:/WinAVR/avr/include/avr/io8535.h" 1 3
# 190 "c:/WinAVR/avr/include/avr/io.h" 2 3
# 229 "c:/WinAVR/avr/include/avr/io.h" 3
# 1 "c:/WinAVR/avr/include/avr/portpins.h" 1 3
# 230 "c:/WinAVR/avr/include/avr/io.h" 2 3
# 2 "bug10733b.c" 2
int main(void)
{
unsigned char t1;
t1=2;
t1=t1+40;
t1%=30;
(*(volatile uint8_t *)((0x17) + 0x20)) = 0xff;
(*(volatile uint8_t *)((0x18) + 0x20)) = t1;
return(0);
}
------------------------------
And compiled output (mixed C and assembly):
------------------------------
3:bug10733b.c **** int main(void)
4:bug10733b.c **** {
61 .LM1:
62 /* prologue: frame size=0 */
63 0000 C0E0 ldi r28,lo8(__stack - 0)
64 0002 D0E0 ldi r29,hi8(__stack - 0)
65 0004 DEBF out __SP_H__,r29
66 0006 CDBF out __SP_L__,r28
67 /* prologue end (size=4) */
5:bug10733b.c **** unsigned char t1;
6:bug10733b.c ****
7:bug10733b.c **** t1=2;
8:bug10733b.c **** t1=t1+40;
9:bug10733b.c **** t1%=30;
69 .LM2:
70 .LBB2:
71 0008 8AE2 ldi r24,lo8(42)
72 000a 6EE1 ldi r22,lo8(30)
73 000c 00D0 rcall __udivmodqi4
10:bug10733b.c ****
11:bug10733b.c **** DDRB = 0xff;
75 .LM3:
76 000e 8FEF ldi r24,lo8(-1)
77 0010 87BB out 55-0x20,r24
12:bug10733b.c **** PORTB = t1;
79 .LM4:
80 0012 98BB out 56-0x20,r25
13:bug10733b.c ****
14:bug10733b.c **** return(0);
15:bug10733b.c **** }
82 .LM5:
83 .LBE2:
84 0014 80E0 ldi r24,lo8(0)
85 0016 90E0 ldi r25,hi8(0)
86 /* epilogue: frame size=0 */
87 0018 00C0 rjmp exit
88 /* epilogue end (size=1) */
------------------------------
Note that this time the modulus is done with a call to __udivmodqi4.
Could this be the problem?
Eric Weddington
WinAVR Admin
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10733