I wrote a small function to convert u8 to hex: // converts 4-bit nibble to ascii hex uint8_t nibbletohex(uint8_t value) { if ( value > 9 ) value += 'A' - '0'; return value + '0'; }
// returns value as 2 ascii characters in a 16-bit int uint16_t u8tohex(uint8_t value) { uint16_t hexdigits; uint8_t hidigit = (value >> 4); hexdigits = (nibbletohex(hidigit) << 8); uint8_t lodigit = (value & 0x0F); hexdigits |= nibbletohex(lodigit); return hexdigits; } I compiled it with avr-gcc -Os using 4.8 and 5.1 and got the same code: 0000007a <u8tohex.1416>: 7a: 28 2f mov r18, r24 7c: 22 95 swap r18 7e: 2f 70 andi r18, 0x0F ; 15 80: 2a 30 cpi r18, 0x0A ; 10 82: 08 f0 brcs .+2 ; 0x86 <u8tohex.1416+0xc> 84: 2f 5e subi r18, 0xEF ; 239 86: 20 5d subi r18, 0xD0 ; 208 88: 30 e0 ldi r19, 0x00 ; 0 8a: 32 2f mov r19, r18 8c: 22 27 eor r18, r18 8e: 8f 70 andi r24, 0x0F ; 15 90: 8a 30 cpi r24, 0x0A ; 10 92: 08 f0 brcs .+2 ; 0x96 <u8tohex.1416+0x1c> 94: 8f 5e subi r24, 0xEF ; 239 96: 80 5d subi r24, 0xD0 ; 208 98: a9 01 movw r20, r18 9a: 48 2b or r20, r24 9c: ca 01 movw r24, r20 9e: 08 95 ret There's some completely pointless code there, like loading 0 to r19 and immediately overwriting it with the contents of r18 (88, 8a). Other register use is convoluted. The compiler should at least be able to generate the following code (5 fewer instructions): 28 2f mov r18, r24 22 95 swap r18 2f 70 andi r18, 0x0F ; 15 2a 30 cpi r18, 0x0A ; 10 08 f0 brcs .+2 ; 0x86 <u8tohex.1416+0xc> 2f 5e subi r18, 0xEF ; 239 20 5d subi r18, 0xD0 ; 208 32 2f mov r25, r18 8f 70 andi r24, 0x0F ; 15 8a 30 cpi r24, 0x0A ; 10 08 f0 brcs .+2 ; 0x96 <u8tohex.1416+0x1c> 8f 5e subi r24, 0xEF ; 239 80 5d subi r24, 0xD0 ; 208 08 95 ret Hand-optimized for size I was able to write it with 3 fewer instructions: .macro addi Rd, K subi \Rd, -(\K) .endm .global u8tohex u8tohex: mov r0, r24 swap r24 rcall nibbletohex ; convert hi digit mov r25, r24 mov r24, r0 ; fall into nibbletohex to convert lo digit ; convert lower nibble of byte to ascii hex char nibbletohex: andi r24, 0x0F cpi r24, 10 brlo under10 addi r24, 'A'-'0'; under10: addi r24, '0' ret I have no intention of learning Gimple and the internals of the gcc back-end, but maybe someone from Atmel can fix this?