template <typename T> __attribute__((always_inline)) static inline void out (unsigned port, T val) { asm volatile ("out %0, %w1" : : "a" (val), "Nd" (port)); }
void func (unsigned bits, unsigned val) { switch (bits) { case 8: out (0x80, static_cast<unsigned char>(val)); return; case 16: out (0x80, static_cast<unsigned short>(val)); return; case 32: out (0x80, static_cast<unsigned long>(val)); return; } } Above test program compiled with: gcc -Os -fomit-frame-pointer -c x.cc produces the following object code: 00000000 <func(unsigned int, unsigned int)>: 0: 8b 54 24 04 mov 0x4(%esp),%edx 4: 8b 44 24 08 mov 0x8(%esp),%eax 8: 83 fa 10 cmp $0x10,%edx b: 74 10 je 1d <func(unsigned int, unsigned int)+0x1d> d: 83 fa 20 cmp $0x20,%edx 10: 74 12 je 24 <func(unsigned int, unsigned int)+0x24> 12: 83 fa 08 cmp $0x8,%edx 15: 75 0f jne 26 <func(unsigned int, unsigned int)+0x26> 17: 0f b6 c0 movzbl %al,%eax 1a: e6 80 out %al,$0x80 1c: c3 ret 1d: 0f b7 c0 movzwl %ax,%eax 20: 66 e7 80 out %ax,$0x80 23: c3 ret 24: e7 80 out %eax,$0x80 26: c3 ret gcc unnecessarily zero-extends %eax before the out operations. gcc -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: ../gcc-svn/configure --prefix=/usr --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-languages=c,c++ --disable-checking --with-gnu-ld --verbose Thread model: posix gcc version 4.3.0 20070903 (experimental) (GCC) -- Summary: Redundant zero-extension of registers Product: gcc Version: 4.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: us15 at os dot inf dot tu-dresden dot de GCC host triplet: 686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33349