This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
- From: Sergio Ruocco <sergio dot ruocco at gmail dot com>
- To: GCC <gcc at gcc dot gnu dot org>
- Date: Mon, 25 Jan 2010 13:34:09 +0100
- Subject: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
- Reply-to: sergio dot ruocco at gmail dot com
Hi everyone,
I am porting GCC to a custom 16-bit microcontroller with very limited
addressing modes. Basically, it can only load/store using a (general
purpose) register as the address, without any offset:
LOAD (R2) R1 ; load R1 from memory at address (R2)
STORE R1 (R2) ; store R1 to memory at address (R2)
As far as I can understand, this is more limited than the current
architectures supported by GCC that I found in the current gcc/config/*.
Since for my port I started modifying a MIPS target (from the tutorials
by IIT Bombay http://www.cse.iitb.ac.in/grc/ - great work guys!), the
GCC still generates code like:
sw R15, 0(R13)
sw R13, -2(R13)
sw R14, -4(R13)
...
lw R14, -4(R13)
lw R15, 0(R13)
Now, in order to restrict the addressing mode, I want to force GCC to
compute the address and store it in a register, then generate the
instructions above to LOAD/STORE in memory. Thus I tried to fiddle with
LEGITIMATE_ADDRESS() and LEGITIMIZE_ADDRESS(), but the compilation of a
simple C program like:
void foobar(int par1, int par2, int parN)
{
int a, b, c;
a = -1;
b = -65535;
c = 0xabcd;
}
fails with
foobar7.c:11: internal compiler error: in change_address_1, at
emit-rtl.c:1800
Please submit a full bug report,
The same program gets compiled with the lw/sw above if I replace 0 with
1 in legitimate_address() below, at the comment /* reject/accept*/.
What should I do? How the addressing mode(s) are managed in the md files
and the LEGITxxx_ADDRESS() macros ? The GCC manual is not very clear on
this... Is there any other architecture/documentation I should look at ?
Thanks,
Sergio
===================================================
Here follows a fragment of my micro.c with the C implementations of the
LEGITIMATE_ADDRESS() and LEGITIMIZE_ADDRESS() macros:
---------------------------------------------------------
int
legitimate_address2(enum machine_mode MODE,rtx X)
{
rtx op1,op2;
if(CONSTANT_ADDRESS_P(X))
{
return 1;
}
if(GET_CODE(X)==REG && non_strict_base_reg(REGNO(X)))
{
return 1;
}
if(GET_CODE(X)==PLUS) /* is it offset+(Rx) ?! */
{
puts ("GET_CODE(X)==PLUS ");
op1=XEXP(X,0);
op2=XEXP(X,1);
if(GET_CODE(op1)==REG && CONSTANT_ADDRESS_P(op2) &&
non_strict_base_reg(REGNO(op1)))
{
return 0; /* reject / accept */
}
if(GET_CODE(op2)==REG && CONSTANT_ADDRESS_P(op1) &&
non_strict_base_reg(REGNO(op2)))
{
return 0; /* reject / accept */
}
}
/* reject all other cases, too */
puts ("legitimate_address2() - end - ret 0/NO");
return 0;
}
rtx
legitimize_address(rtx X,rtx OLDX, enum machine_mode MODE)
{
rtx op1,op2,op;
op=NULL;
if(memory_address_p(MODE,X))
return X;
if(GET_CODE(X)==MEM && !no_new_pseudos)
op = force_reg(MODE,X);
else if ( GET_CODE(X)==PLUS && !no_new_pseudos)
{
puts("GET_CODE(X)==PLUS && !no_new_pseudos !");
op1=XEXP(X,0);
op2=XEXP(X,1);
if(GET_CODE(op1)==REG && !CONSTANT_ADDRESS_P(op2))
{
op=force_reg(MODE,X);
}
else if(GET_CODE(op2)==REG && !CONSTANT_ADDRESS_P(op1))
{
op=force_reg(MODE,X);
}
else /* HACK */
{
op=force_reg(MODE,X);
}
-----
/* Here is another HACK attempt, now disabled (commented), inspired by
http://gcc.gnu.org/ml/gcc/2001-07/msg01513.html, but this is not
working, either */
else if ( (GET_CODE (op1)== REG) && (GET_CODE (op2) ==
CONST_INT) )
{
op1 = force_reg (MODE, op1);
op = force_reg (MODE, gen_rtx_PLUS (MODE, op1, op2));
}
-----
}
if(op!=NULL && memory_address_p(MODE,op))
{
return op; /* if we rewrote the expression */
}
return X; /* otherwise original */
}
-------------------------------------------------------------
Here is a fragment of "micro.md" with the definitions of the "movXX",
load and store patterns:
----------------------------------------------------
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" "")
)]
""
{
if(GET_CODE(operands[0])==MEM && GET_CODE(operands[1])!=REG)
{
if(!no_new_pseudos) {
operands[1]=force_reg(HImode,operands[1]);
}
}
}
)
;;Load patterns
(define_insn "*load_word"
[(set (match_operand:HI 0 "register_operand" "=r")
(mem:HI (match_operand:HI 1 "address_operand" "p")))]
""
"lw \\t%0, %a1"
)
;;Store patterns
(define_insn "*store_word"
[(set (mem:HI (match_operand:HI 0 "address_operand" "p"))
(match_operand:HI 1 "register_operand" "r"))]
""
"sw \\t%1, %a0"
)
-------------------------------