I sent mail to James about a month ago, but never heard back.... So...
This patch works around a problem in the ft32 port that shows up when building newlib. The assembler was complaining about a line like this: ldi.b $r1,_ctype_-0x800000+1($r0) That's certainly an odd looking address computation. It corresponds to this in the .final dump: (insn 8 7 9 (set (reg:QI 3 $r1 [orig:53 *_3 ] [53]) (mem:QI (plus:SI (reg/v:SI 2 $r0 [orig:49 c ] [49]) (const:SI (plus:SI (symbol_ref:SI ("_ctype_") [flags 0x1040] <var_decl 0x7ff18f27d090 _ctype_>) (const_int 1 [0x1])))) [0 *_3+0 S1 A8])) "j.c":7 31 {*movqi} (expr_list:REG_EQUIV (mem:QI (plus:SI (reg/v:SI 2 $r0 [orig:49 c ] [49]) (const:SI (plus:SI (symbol_ref:SI ("_ctype_") [flags 0x1040] <var_decl 0x7ff18f27d090 _ctype_>) (const_int 1 [0x1])))) [0 *_3+0 S1 A8]) (nil))) Presumably the -0x8000000+1 is to deal with some oddity in the ft32 port, but there's no comments where this happens: #define ASM_OUTPUT_SYMBOL_REF(stream, sym) \ do { \ assemble_name (stream, XSTR (sym, 0)); \ int section_debug = in_section && \ (SECTION_STYLE (in_section) == SECTION_NAMED) && \ (in_section->named.common.flags & SECTION_DEBUG); \ if (!section_debug && SYMBOL_REF_FLAGS (sym) & 0x1000) \ asm_fprintf (stream, "-0x800000"); \ } while (0) Essentially it's some section encoding and ultimately I don't think it's terribly important. The assembler simply won't accept the insn in question. Arguably it could/should, since it's really just a reg+disp address where the disp isn't know until link time. If I simplify the line to: ldi.b $r1,_ctype($r0) The assembler still complains. After a bit more poking around I think we're just formatting the address totally wrong. AFAICT the ft32 wants: ldi.b $r1,$r0,<constant part> So it would seem that just fixing ft32_print_operand_address to emit it in that format would be sufficient. However, I'm not familiar enough with this port to know if there are other contexts where it wants the <constant>(register) style formatting. Can you take a look and take appropriate action. Testcase, compile with -O2. extern const char _ctype_[]; int tolower (int c) { return (((((_ctype_) + sizeof (""[c]))[(int) (c)]) & (01 | 02)) == 01) ? (c) - 'A' + 'a' : c; } My patch is a hack, plain and simple. It disables addressing modes such as reg + sym +- const_int. I doubt it matters in any significant way. With the maintainer unresponsive, this patch seems like a reasonable minimal effort workaround. Jeff
commit 73262eafbf11463163d9cd805648ee2d704a677a Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon Oct 15 23:22:05 2018 +0000 * config/ft32/ft32.md (ft32_general_movsrc_operand): Disable reg + sym +- const_int addressing modes. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@265179 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 789e43b2388..0f4e293d06f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2018-10-12 Jeff Law <l...@redhat.com> + + * config/ft32/ft32.md (ft32_general_movsrc_operand): Disable + reg + sym +- const_int addressing modes. + 2018-10-15 David Malcolm <dmalc...@redhat.com> * common.opt (fdiagnostics-minimum-margin-width=): New option. diff --git a/gcc/config/ft32/predicates.md b/gcc/config/ft32/predicates.md index bac2e8ef5aa..0c147ec1aab 100644 --- a/gcc/config/ft32/predicates.md +++ b/gcc/config/ft32/predicates.md @@ -23,6 +23,11 @@ ;; ------------------------------------------------------------------------- ;; Nonzero if OP can be source of a simple move operation. +;; +;; The CONST_INT could really be CONST if we were to fix +;; ft32_print_operand_address to format the address correctly. +;; It might require assembler/linker work as well to ensure +;; the right relocation is emitted. (define_predicate "ft32_general_movsrc_operand" (match_code "mem,const_int,reg,subreg,symbol_ref,label_ref,const") @@ -34,7 +39,7 @@ if (MEM_P (op) && GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG - && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST) + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) return 1; return general_operand (op, mode);