some disasm listings to show what is going wrong.. i cant find the guilty source files:-( 000fa8b2 <___pack_d>: <snip> fadb7: 75 42 push.w:g r2 //pushing 64 bit exponent [63:48] fadb9: 75 42 push.w:g r2 //pushing 64 bit exponent [47:32] fadbb: 75 42 push.w:g r2 //pushing 64 bit exponent [31:16] fadbd: 75 40 push.w:g r0 //pushing 64 bit exponent [15:0] fadbf: 75 c2 34 00 mov.w:g #52,r2 //shift count to get exponent in [62:52] fadc3: fd 83 6f 0f jsr.a f6f83 <___ashldi3> ___ashldi3 detects that it needs to shift more then 32 bits and prepares to shift by -(32-52) = 20 bits (and after that 'shift' by 32 by moving registers around)
000f6f83 <___ashldi3>: <snip> f7055: 73 b2 07 mov.w:g 7[fb],r2 //src bit[15:0] f7058: 73 b0 05 mov.w:g 5[fb],r0 //src bit[31:16] f705b: 72 b2 e2 mov.b:g -30[fb],r1l //shift count (20) f705e: 72 23 mov.b:g r1l,r1h //shift count (20) f7060: eb 21 sha.l r1h,r2r0 //the shift The M16C/60, M16C/20, M16C/Tine Series Software Manual says: "If src is a register and you selected (.W) or (.L) for the size specifier (.size), the number of shifts is 16 to +16. Although you can set 0, no bits are shifted and no flags are changed. If you set a value less than 16 or greater than +16, the result of shift is indeterminate." the actual result on my hardware is a shift by 4 (20 & 0xf). i think ___ashldi3 (and friends!) should (also) check if the shift is >16 and only do the shift % 16 with the shift instruction and do the rest of the shift by moving registers. -- Summary: M16C invalid shift count used by pack_d -> ashldi3 Product: gcc Version: 4.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: eightdot at hotmail dot com GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: m32c-unknown-elf http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40129