Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!

2010-01-28 Thread Sergio Ruocco


Now my GO_IF_LEGITIMATE_ADDRESS refuses anything that is not a REG
or a CONSTANT_ADDRESS:

int legitimate_address1(enum machine_mode MODE,rtx X)
{
if(CONSTANT_ADDRESS_P(X))
return 1;
if(GET_CODE(X)==REG  is_base_reg(REGNO(X)))
return 1;

return 0; /* fails everything else */

} /* this is the strict version, the non strict version is similar */

but GCC (4.0.2, just in case the version is relevant) still aborts the
compilation.


Then I found this wiki note about forcing complex addresses into
registers: http://gcc.gnu.org/wiki/WritingANewBackEnd

...
rtx copy_addr_to_reg (rtx x)
Equivalent to copy_to_mode_reg (Pmode, x). For example, this
function can be used to compute a complex address X in a register for an
instruction which supports only register indirect addressing. See also
replace_equiv_address() below.
...


Thus I changed in the .md file the movXX RTL expand macro to force any
MEM expression into a register:

(define_expand movhi /*  my micro is 16 bit... */
[(set (match_operand:HI 0 nonimmediate_operand )
  (match_operand:HI 1 general_operand )
)]

{
if(!no_new_pseudos  GET_CODE(operands[0])==MEM) {
if( /* addr in operands[0] == base reg + offset */ )
operands[0] = copy_addr_to_reg ( operands[0] );
}
)

The GCC still fails to generate the assembly code to do the arithmetic
computation of the baseReg+offset--tempReg, and then use (tempReg) as
address.

Note that with the current MD GCC is able to generate simple sums like
R1 = R2 + R3 and R1 = R2 + IMM, thus the basic math to compute an
address is there.

Any suggestion on what I am doing wrong ?

Sergio


Michael Hope wrote:
 Hi Sergio.  My port has similar addressing modes - all memory must be
 accessed by one of two registers and can only be accessed indirectly,
 indirect with pre increment, and indirect with post increment.  The
 key is GO_IF_LEGITIMATE_ADDRESS and the legitimate address helper
 function.  Mine looks like this:
 
 /* Return 1 if the address is OK, otherwise 0.
Used by GO_IF_LEGITIMATE_ADDRESS.  */
 
 bool
 tomi_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED,
rtx x,
bool strict_checking)
 {
   /* (mem reg) */
   if (REG_P (x)
tomi_reg_ok (x, strict_checking)
   )
 {
   return 1;
 }
 
   if (GET_CODE(x) == PRE_DEC)
 {
 ...
 }
 
   if (GET_CODE(x) == POST_INC)
 {
 ...
 }
 
   return 0;
 }
 
 tomi_reg_ok returns true if x is any register when strict checking is
 clear and true if x is one of my addressing registers when strict
 checking is set.
 
 GCC will feed any memory accesses through this function to see if they
 are directly supported, and if not it will break them up into
 something smaller and try again.
 
 Hope that helps,
 
 -- Michael
 
 
 2010/1/26 Sergio Ruocco sergio.ruo...@gmail.com:
 Gabriel Paubert wrote:
 On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote:
 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/*.
 The Itanium (ia64) has the same limited choice of addressing modes.

   Gabriel
 Thanks Gabriel.

 I dived into the ia64 md, but it is still unclear to me how the various
 parts (macros, define_expand and define_insn in MD etc.) work together
 to force the computation of a source/dest address plus offset into a
 register... can anyone help me with this ?

 Thanks,

Sergio




porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!

2010-01-25 Thread Sergio Ruocco

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 

Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!

2010-01-25 Thread Gabriel Paubert
On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote:
 
 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/*.

The Itanium (ia64) has the same limited choice of addressing modes. 

Gabriel


Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!

2010-01-25 Thread Sergio Ruocco
Gabriel Paubert wrote:
 On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote:
 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/*.
 
 The Itanium (ia64) has the same limited choice of addressing modes. 
 
   Gabriel

Thanks Gabriel.

I dived into the ia64 md, but it is still unclear to me how the various
parts (macros, define_expand and define_insn in MD etc.) work together
to force the computation of a source/dest address plus offset into a
register... can anyone help me with this ?

Thanks,

Sergio


Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!

2010-01-25 Thread Jeff Law

On 01/25/10 11:21, Sergio Ruocco wrote:

Gabriel Paubert wrote:
   

On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote:
 

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/*.
   

The Itanium (ia64) has the same limited choice of addressing modes.

Gabriel
 

Thanks Gabriel.

I dived into the ia64 md, but it is still unclear to me how the various
parts (macros, define_expand and define_insn in MD etc.) work together
to force the computation of a source/dest address plus offset into a
register... can anyone help me with this ?
   

GO_IF_LEGITIMATE_ADDRESS is what you need to be looking at.

jeff



Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!

2010-01-25 Thread Michael Hope
Hi Sergio.  My port has similar addressing modes - all memory must be
accessed by one of two registers and can only be accessed indirectly,
indirect with pre increment, and indirect with post increment.  The
key is GO_IF_LEGITIMATE_ADDRESS and the legitimate address helper
function.  Mine looks like this:

/* Return 1 if the address is OK, otherwise 0.
   Used by GO_IF_LEGITIMATE_ADDRESS.  */

bool
tomi_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED,
 rtx x,
 bool strict_checking)
{
  /* (mem reg) */
  if (REG_P (x)
   tomi_reg_ok (x, strict_checking)
  )
{
  return 1;
}

  if (GET_CODE(x) == PRE_DEC)
{
...
}

  if (GET_CODE(x) == POST_INC)
{
...
}

  return 0;
}

tomi_reg_ok returns true if x is any register when strict checking is
clear and true if x is one of my addressing registers when strict
checking is set.

GCC will feed any memory accesses through this function to see if they
are directly supported, and if not it will break them up into
something smaller and try again.

Hope that helps,

-- Michael


2010/1/26 Sergio Ruocco sergio.ruo...@gmail.com:
 Gabriel Paubert wrote:
 On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote:
 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/*.

 The Itanium (ia64) has the same limited choice of addressing modes.

       Gabriel

 Thanks Gabriel.

 I dived into the ia64 md, but it is still unclear to me how the various
 parts (macros, define_expand and define_insn in MD etc.) work together
 to force the computation of a source/dest address plus offset into a
 register... can anyone help me with this ?

 Thanks,

        Sergio