Hi, I'm working on a GCC (4.3.0) backend for a custom 16 bit microcontroller we're designing at work, and I'm facing a reload problem. After having lost many hours trying to make it work, I decided to ask for some help :)
I'll try to summarize the situation below, but by all means please ask for more if something is missing. The error I'm encountering happens when compiling _divdi3 in libgcc (note that before compiling this one, several functions from libgcc compiled fine): ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c: In function ‘__divhi3’: ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1106: error: insn does not satisfy its constraints: (insn 1117 16 1118 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10) (const_int 24 [0x18])) 1 {*movqi_imm} (nil)) ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1106: internal compiler error: in reload_cse_simplify_operands, at postreload.c:395 The microcontroller in question is a 16 bit one, and addresses the memory only in 16 bit words: #define BITS_PER_UNIT 16 #define UNITS_PER_WORD 1 This microcontroller has 32 hard registers. Immediate constants can only be loaded into the first 8 registers. There are no index registers. All the even registers can serve as a base register. However, the base register addressing is reduced to its simplest form, where the offset is always 0. Based on the above, I have defined: enum reg_class { NO_REGS, STACK_REGS, EIGHT_REGS, EVEN_REGS, ALL_REGS, LIM_REG_CLASSES }; #define GENERAL_REGS ALL_REGS ... #define REG_CLASS_CONTENTS \ { \ { 0x00000000 }, \ { 0x80000000 }, \ { 0x000000FF }, \ { 0x55555555 }, \ { (1LL << FIRST_PSEUDO_REGISTER) - 1 } \ } #define REGNO_REG_CLASS(REGNO) \ ((REGNO) > 30 ? STACK_REGS \ : (REGNO) < 8 ? EIGHT_REGS \ : (REGNO % 2) == 0 ? EVEN_REGS \ : GENERAL_REGS) #define BASE_REG_CLASS EVEN_REGS #define INDEX_REG_CLASS NO_REGS #define REGNO_OK_FOR_BASE_P(NUM) (NUM % 2 == 0) #define REGNO_OK_FOR_INDEX_P(NUM) 0 #define PREFERRED_RELOAD_CLASS(X, CLASS) \ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) ... #define STACK_POINTER_REGNUM 31 #define FRAME_POINTER_REGNUM 30 .... #ifdef REG_OK_STRICT #define REG_OK_FOR_BASE_P(X) \ (REGNO_OK_FOR_BASE_P (REGNO (X)) && (REGNO (X) <FIRST_PSEUDO_REGISTER)) #else #define REG_OK_FOR_BASE_P(X) \ (REGNO_OK_FOR_BASE_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER) #endif #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ do { \ if (GET_CODE (X) == REG && (REG_OK_FOR_BASE_P(X))) \ goto LABEL; \ else if (GET_CODE(X) == PLUS && \ REG_OK_FOR_BASE_P (XEXP (X, 0)) && \ GET_CODE(XEXP(X,1)) == CONST_INT && \ INTVAL(XEXP(X,1)) == 0) \ goto LABEL; \ } while (0) I also defined some constraints for the register classes: (define_register_constraint "x" "STACK_REGS" "Stack registers (r30--r31)") (define_register_constraint "y" "EIGHT_REGS" "Low eight registers (r0--r7)") (define_register_constraint "z" "EVEN_REGS" "Even registers (r0,r2,r4, @dots{} r30)") The movqi_imm pattern which constraints doesn't match has been defined with (note the 'y' constrant): (define_insn "*movqi_imm" [(set (match_operand:QI 0 "register_operand" "=y") (match_operand:QI 1 "const_int_operand" ""))] "" { output_asm_insn ("ldih %0, hi(%1)", operands); output_asm_insn ("ldil %0, lo(%1)", operands); return ""; } [(set_attr "cc" "none")] ) Now, I'm trying to figure out why the error happens, with GCC choosing to put an immediate into r10 instead of an EIGHT_REGS. It all seems to come (I do not know why) from insn 16 in libgcc2.c.175r.lreg: Register 453 costs: EIGHT_REGS:0 EVEN_REGS:0 ALL_REGS:0 MEM:4175 Register 466 costs: EIGHT_REGS:600 EVEN_REGS:600 ALL_REGS:600 MEM:5200 ... Register 453 pref EVEN_REGS Register 466 pref EVEN_REGS ... (insn 16 15 21 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 453 [ uu+1 ]) (reg:QI 466 [ v ])) 0 {*movqi_reg} (nil)) In libgcc2.c.176.greg I see: Reloads for insn # 16 Reload 0: reload_in (QI) = (plus:QI (reg/f:QI 30 r30) (const_int 24 [0x18])) EVEN_REGS, RELOAD_FOR_OUTPUT_ADDRESS (opnum = 0), can't combine reload_in_reg: (plus:QI (reg/f:QI 30 r30) (const_int 24 [0x18])) reload_reg_rtx: (reg:QI 10 r10) Reload 1: reload_out (QI) = (mem/c:QI (plus:QI (reg/f:QI 30 r30) (const_int 24 [0x18])) [31 S1 A16]) EVEN_REGS, RELOAD_FOR_OUTPUT (opnum = 0) reload_out_reg: (reg:QI 453 [ uu+1 ]) reload_reg_rtx: (reg:QI 14 r14) ... (insn 16 1115 1117 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 14 r14) (reg:QI 2 r2 [orig:466 v ] [466])) 0 {*movqi_reg} (nil)) (insn 1117 16 1118 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10) (const_int 24 [0x18])) 1 {*movqi_imm} (nil)) (insn 1118 1117 1119 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10) (plus:QI (reg:QI 10 r10) (reg/f:QI 30 r30))) 13 {addqi3} (expr_list:REG_EQUIV (plus:QI (reg/f:QI 30 r30) (const_int 24 [0x18])) (nil))) (insn 1119 1118 21 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (mem/c:QI (reg:QI 10 r10) [31 S1 A16]) (reg:QI 14 r14)) 8 {*movqi_tomem} (nil)) I tried playing with different definitions for PREFERRED_RELOAD_CLASS, PREFERRED_OUTPUT_RELOAD_CLASS, TARGET_SECONDARY_RELOAD, with no luck. Thanks to anybody who can explain to me what's wrong here, and give a clue on what I must do to fix it. Stelian. -- Stelian Pop <[EMAIL PROTECTED]>