https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62180
Bug ID: 62180 Summary: (RX600) - compiler doesn't honor -fstrict-volatile-bitfields and generates incorrect machine code for I/O register access Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: jan.capek at braiins dot cz Created attachment 33359 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33359&action=edit broken output from gcc 4.9.0 I have come across this issue while testing 4.9.x series of the compiler with Renesas RX600 target The compiler now generates byte accesses when writing bitfields completely ignoring their 'type'. The strict-volatile-bitfields options seems to have no effect. Our original compiler version 4.7.2 seems to work correctly and generates accesses to the bitfields based on their type. This is essentially what the documentation for the 'strict-volatile-bitfields' says. I have tested this with 4.8.2 and 4.8.3, too with the same result. The test case demonstrates access to a 16-bit memory mapped peripheral register. It is absolutely necessary that the register is always being written in 16-bit quantities. A simple testcase: struct st_cmt0 { union { unsigned short WORD; struct { volatile unsigned short CKS:2; volatile unsigned short :4; volatile unsigned short CMIE:1; volatile unsigned short :9; } BIT; } CMCR; unsigned short CMCNT; unsigned short CMCOR; }; void test(volatile struct st_cmt0 *reg) { reg->CMCR.BIT.CMIE = 1; } The output for gcc 4.7.2 is: .file "test.c" .section P,"ax" .global _test .type _test, @function _test: pushm r6-r11 add #-4, r0, r6 mov.L r6, r0 mov.L r1, [r6] mov.L [r6], r11 mov.W [r11], r10 ; HONORS the 16-bit register size bset #6, r10 mov.W r10, [r11] ; HONORS the 16-bit register size rtsd #28, r6-r11 .size _test, .-_test .ident "GCC: (GNU) 4.7.2" The output for gcc 4.9.0 is: .file "test.c" .section P,"ax" .global _test .type _test, @function _test: pushm r6-r11 add #-4, r0, r6 mov.L r6, r0 mov.L r1, [r6] mov.L [r6], r11 mov.B [r11], r10 ; broken - reads only part of the register bset #6, r10 mov.B r10, [r11] ; broken - writes only part of the register rtsd #28, r6-r11 .size _test, .-_test .ident "GCC: (GNU) 4.9.0"