https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70162
Bug ID: 70162 Summary: [RX] const_int printing causes wrong code on 32 bit host Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: olegendo at gcc dot gnu.org CC: dj at redhat dot com Target Milestone: --- Host: i686 Target: rx-elf It seems the rx-elf toolchain (incl. binutils) has some issues on 32 bit hosts. The following C++ program exposes 3 issues. typedef unsigned char uint8_t; void send_1 (unsigned int, const void*, unsigned int); signed char fail (void) { static const uint8_t cmd42[] = { 0x98, 0x00, 0x00, 0x00, 0x00, 0xFF }; send_1 (0x42, cmd42, 6); static const uint8_t cmd40[] = { 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; send_1 (0x40, cmd40, 6); uint8_t wr_data[] = { 0x88, 0x00, 0x00, 0x00 }; send_1 (0x42, wr_data, 4); return -80; } Compiled with -O2 will result in: ... mov.L r0, r2 mov.B #0xffffffffffffff88, [r0] <<<<< (*1) mov.B #0, 1[r0] mov.B #0, 2[r0] mov.B #0, 3[r0] jsr r7 mov.L #0xffffffffffffffb0, r1 <<<<< (*2) rtsd #8, r7-r7 In (*1) GAS will misinterpret the 64 bit value and the resulting code becomes: 2b: f8 04 88 mov.b #136, [r0] 2e: ff ff *unknown* Which results in an illegal instruction exception. In (*2) GAS will select a longer instruction than necessary: 3c: fb 12 b0 ff ff ff mov.l #-80, r1 Another issue (*3) is GAS issuing the warning: main.s: Assembler messages: main.s:33: Warning: bignum truncated to 1 bytes main.s:42: Warning: bignum truncated to 1 bytes which comes from things like __ZZ4failvE5cmd40: .byte 0xffffffffffffff98 .byte -1 .... The following patch fixes issues (*1) and (*2): Index: gcc/config/rx/rx.md =================================================================== --- gcc/config/rx/rx.md (revision 234073) +++ gcc/config/rx/rx.md (working copy) @@ -588,7 +588,21 @@ (match_operand:register_modes 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))] "" - { return rx_gen_move_template (operands, false); } + { + if (CONST_INT_P (operands[1])) + { + /* Truncate constants to the size of the move insn to avoid printing + 64 bit constants which might be misinterpreted by the assembler. */ + if (<MODE>mode == QImode) + operands[1] = GEN_INT (INTVAL (operands[1]) & 0xFF); + else if (<MODE>mode == HImode) + operands[1] = GEN_INT (INTVAL (operands[1]) & 0xFFFF); + else + operands[1] = GEN_INT (INTVAL (operands[1]) & 0xFFFFFFFF); + } + + return rx_gen_move_template (operands, false); + } [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8") (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")] ) Issue (*3) can be avoided by this: Index: gcc/config/rx/rx.c =================================================================== --- gcc/config/rx/rx.c (revision 234073) +++ gcc/config/rx/rx.c (working copy) @@ -513,6 +513,9 @@ static bool rx_assemble_integer (rtx x, unsigned int size, int is_aligned) { + if (!TARGET_AS100_SYNTAX) + return default_assemble_integer (x, size, is_aligned); + const char * op = integer_asm_op (size, is_aligned); if (! CONST_INT_P (x))