Hi,
I think I have found a bug in the way mspgcc generates in-line multiply code
when using typecasts. In a particular bit of code, I want to multiply a
byte-sized variable with a constant. The result should be 16-bit, since it
could well be over 255. I was under the impression that normal C integer
promotion would automatically give me 16-bit wide multiplication, but since
that failed, I tried typecasting - and that failed too.
In the sample below, m1 is generated as 8-bit. I thought that should be
16-bit, but I am quite happy to believe that 8-bit is the correct code and
that my interpretation is wrong. m3 is generated correctly for 16-bit. But
m2 should be 16-bit, and yet is generated as 8-bit.
Incidently, is the inline multiply code faster than using the hardware
multiply? I can see it would be for small constants, but do you switch over
automatically for constants that generate larger code? Also, is it not
possible to optomise the 7 "rla" instructions as a "swapb" then an "rra" ?
The command-line I used was this (although I also tried with optomisation
off - it made no difference):
msp430-gcc -c -mmcu=msp430x149 -g -O2 -fverbose-asm -Wa,-ahld=test.lst
test.c
mvh.
David
/**** test.c ****/
#define scale 122
unsigned int m1(unsigned char b) {
// The mult is 8-bit
return b*scale;
}
unsigned int m2(unsigned char b) {
// The mult should be 16-bit, but is actually 8-bit
return ((unsigned int)b) * scale;
}
unsigned int m3(unsigned int w) {
// The mult is 16-bit
return w * scale;
}
unsigned int m4(unsigned char b) {
// The mult is 16-bit
unsigned int w = b;
return w * scale;
}
/**** test.lst ****/
12:test.c **** #define scale 122
13:test.c ****
14:test.c **** unsigned int m1(unsigned char b) {
109 .LM1:
110 /* prologue: frame size = 0 */
111 .L__FrameSize_m1=0x0
GAS LISTING /cygdrive/d/temp/ccGc8q6D.s page 2
112 .L__FrameOffset_m1=0x0
113 /* prologue end (size=0) */
15:test.c **** // The mult is 8-bit
16:test.c **** return b*scale;
115 .LM2:
116 0000 4E4F mov.b r15, r14 ; b, b
117 0002 0E5E rla r14 ; b
118 0004 0E5E rla r14 ; b
119 0006 0E5E rla r14 ; b
120 0008 0E5E rla r14 ; b
121 000a 0E5E rla r14 ; b
122 000c 0E5E rla r14 ; b
123 000e 0E5E rla r14 ; b
124 0010 4F5F rla.b r15 ; b
125 0012 4E8F sub.b r15, r14 ; b, b
126 0014 4E8F sub.b r15, r14 ; b, b
127 0016 4E8F sub.b r15, r14 ; b, b
17:test.c **** }
129 .LM3:
130 0018 0F4E mov r14, r15 ; b
131 001a 3041 ret
132 /* epilogue: not required */
133 /* function m1 size 14 (13) */
134 .Lfe1:
136 /********* End of function ******/
137
138 .Lscope0:
140 .p2align 1,0
143 .global m2
145 /***********************
146 * Function `m2'
147 ***********************/
148 m2:
18:test.c ****
19:test.c **** unsigned int m2(unsigned char b) {
150 .LM4:
151 /* prologue: frame size = 0 */
152 .L__FrameSize_m2=0x0
153 .L__FrameOffset_m2=0x0
154 /* prologue end (size=0) */
20:test.c **** // The mult should be 16-bit, but is actually 8-bit
21:test.c **** return ((unsigned int)b) * scale;
156 .LM5:
157 001c 4E4F mov.b r15, r14 ; b, b
158 001e 0E5E rla r14 ; b
159 0020 0E5E rla r14 ; b
160 0022 0E5E rla r14 ; b
161 0024 0E5E rla r14 ; b
162 0026 0E5E rla r14 ; b
163 0028 0E5E rla r14 ; b
164 002a 0E5E rla r14 ; b
165 002c 4F5F rla.b r15 ; b
166 002e 4E8F sub.b r15, r14 ; b, b
167 0030 4E8F sub.b r15, r14 ; b, b
168 0032 4E8F sub.b r15, r14 ; b, b
22:test.c **** }
170 .LM6:
GAS LISTING /cygdrive/d/temp/ccGc8q6D.s page 3
171 0034 0F4E mov r14, r15 ; b
172 0036 3041 ret
173 /* epilogue: not required */
174 /* function m2 size 14 (13) */
175 .Lfe2:
177 /********* End of function ******/
178
179 .Lscope1:
181 .p2align 1,0
184 .global m3
186 /***********************
187 * Function `m3'
188 ***********************/
189 m3:
23:test.c ****
24:test.c **** unsigned int m3(unsigned int w) {
191 .LM7:
192 /* prologue: frame size = 0 */
193 .L__FrameSize_m3=0x0
194 .L__FrameOffset_m3=0x0
195 /* prologue end (size=0) */
25:test.c **** // The mult is 16-bit
26:test.c **** return w * scale;
197 .LM8:
198 0038 0E4F mov r15, r14 ; w, w
199 003a 0E5E rla r14 ; w
200 003c 0E5E rla r14 ; w
201 003e 0E5E rla r14 ; w
202 0040 0E5E rla r14 ; w
203 0042 0E5E rla r14 ; w
204 0044 0E5E rla r14 ; w
205 0046 0E5E rla r14 ; w
206 0048 0F5F rla r15 ; w
207 004a 0E8F sub r15, r14 ; w, w
208 004c 0E8F sub r15, r14 ; w, w
209 004e 0E8F sub r15, r14 ; w, w
27:test.c **** }
211 .LM9:
212 0050 0F4E mov r14, r15 ; w
213 0052 3041 ret
214 /* epilogue: not required */
215 /* function m3 size 14 (13) */
216 .Lfe3:
218 /********* End of function ******/
219
220 .Lscope2:
222 .p2align 1,0
225 .global m4
227 /***********************
228 * Function `m4'
229 ***********************/
230 m4:
28:test.c ****
29:test.c **** unsigned int m4(unsigned char b) {
232 .LM10:
233 /* prologue: frame size = 0 */
234 .L__FrameSize_m4=0x0
GAS LISTING /cygdrive/d/temp/ccGc8q6D.s page 4
235 .L__FrameOffset_m4=0x0
236 /* prologue end (size=0) */
237 .LBB2:
30:test.c **** // The mult is 16-bit
31:test.c **** unsigned int w = b;
239 .LM11:
240 0054 4E4F mov.b r15, r14 ; b, w
32:test.c **** return w * scale;
242 .LM12:
243 0056 0F4E mov r14, r15 ; w, w
244 0058 0F5F rla r15 ; w
245 005a 0F5F rla r15 ; w
246 005c 0F5F rla r15 ; w
247 005e 0F5F rla r15 ; w
248 0060 0F5F rla r15 ; w
249 0062 0F5F rla r15 ; w
250 0064 0F5F rla r15 ; w
251 0066 0E5E rla r14 ; w
252 0068 0F8E sub r14, r15 ; w, w
253 006a 0F8E sub r14, r15 ; w, w
254 006c 0F8E sub r14, r15 ; w, w
255 .LBE2:
33:test.c **** }
257 .LM13:
258 006e 3041 ret
259 /* epilogue: not required */
260 /* function m4 size 14 (13) */
261 .Lfe4:
263 /********* End of function ******/
264