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]>