Michael Hope wrote:
> Hi Sergio.  Any luck so far?

Micheal, thanks for your inquiry. I made some progress, in fact.

I got the GO_IF_LEGITIMATE_ADDRESS() macro to detect correctly REG+IMM
addresses, and then the LEGITIMIZE_ADDRESS() macro to force them to be
pre-computed in a register.

However, now the compiler freaks out with an ICE.. :-/ I put some
details below. Thanks for any clue that you or others can give me.

Cheers,

        Sergio

==========================================================================


This is a fragment of my LEGITIMIZE_ADDRESS():
-----------------------------------------------------------------

rtx
legitimize_address(rtx X,rtx OLDX, enum machine_mode MODE)
{
        rtx op1,op2,op,sum;
        op=NULL;
...
        if(GET_CODE(X)==PLUS && !no_new_pseudos)
        {
                op1=XEXP(X,0);
                op2=XEXP(X,1);
                if(GET_CODE(op1) == CONST_INT && (GET_CODE(op2) == REG ||
GET_CODE(op2) == SUBREG)) // base displacement
                {
                        sum = gen_rtx_PLUS (MODE, op1, op2);
                        op = force_reg(MODE, sum);
                }
...
-----------------------------------------------------------------


Now when compiling a simple program such as:

void foobar(int par1, int par2, int parN)
{
        int a,b;
        a = 0x1234;
        b = a;
}

the instructions (n. 8,12,13) which compute the addresses in registers
seem to be generated correctly:

-----------------------------------------------------------------
;; Function foobar

;; Register dispositions:
37 in 4  38 in 2  39 in 4  40 in 2  41 in 2

;; Hard regs used:  2 4 30

(note 2 0 3 NOTE_INSN_DELETED)

(note 3 2 6 0 NOTE_INSN_FUNCTION_BEG)

;; Start of basic block 1, registers live: 1 [A1] 29 [B13] 30 [B14]
(note 6 3 8 1 [bb 1] NOTE_INSN_BASIC_BLOCK)

(insn 8 6 9 1 (set (reg/f:HI 4 A4 [37])
        (plus:HI (reg/f:HI 30 B14)
            (const_int -16 [0xfffffffffffffff0]))) 9 {addhi3} (nil)
    (nil))

(insn 9 8 10 1 (set (reg:HI 2 A2 [38])
        (const_int 4660 [0x1234])) 5 {*constant_load} (nil)
    (nil))

(insn 10 9 12 1 (set (mem/i:HI (reg/f:HI 4 A4 [37]) [0 a+0 S2 A32])
        (reg:HI 2 A2 [38])) 7 {*store_word} (nil)
    (nil))

(insn 12 10 13 1 (set (reg/f:HI 4 A4 [39])
        (plus:HI (reg/f:HI 30 B14)
            (const_int -14 [0xfffffffffffffff2]))) 9 {addhi3} (nil)
    (nil))

(insn 13 12 14 1 (set (reg/f:HI 2 A2 [40])
        (plus:HI (reg/f:HI 30 B14)
            (const_int -16 [0xfffffffffffffff0]))) 9 {addhi3} (nil)
    (nil))

(insn 14 13 15 1 (set (reg:HI 2 A2 [orig:41 a ] [41])
        (mem/i:HI (reg/f:HI 2 A2 [40]) [0 a+0 S2 A32])) 4 {*load_word} (nil)
    (nil))

(insn 15 14 16 1 (set (mem/i:HI (reg/f:HI 4 A4 [39]) [0 b+0 S2 A16])
        (reg:HI 2 A2 [orig:41 a ] [41])) 7 {*store_word} (nil)
    (nil))
;; End of basic block 1, registers live:
 1 [A1] 29 [B13] 30 [B14]

(note 16 15 25 NOTE_INSN_FUNCTION_END)

(note 25 16 0 NOTE_INSN_DELETED)
-----------------------------------------------------------------

However, when I compile it

$ hcc -da foobar8.c

I get an ICE at the end of the compilation, and the assembly source is
not produced:

[ lots of my debugging output removed ]

legitimate_address2(non-strict, soft-reg allowed), X=
(reg/f:HI 29 B13)
legitimate_address2() yes: (X)==REG && non_strict_base_reg(REGNO(X))

-----------------MOVHI--------------- [generating a MOV X, Y insn]
MOVHI: operands[0]
(mem:HI (reg/f:HI 29 B13) [0 S2 A8])
MOVHI: operands[1]
(reg:HI 31 B15)
MOVHI --- END


[then checking if -2(B13) is legitimate, it is not...]

legitimate_address2(non-strict, soft-reg allowed), X=
(plus:HI (reg/f:HI 29 B13)
    (const_int -2 [0xfffffffffffffffe]))
legitimate_address2(): FOUND register+offset --> FAIL!

legitimate_address2(non-strict, soft-reg allowed), X=
(plus:HI (reg/f:HI 29 B13)
    (const_int -2 [0xfffffffffffffffe]))
legitimate_address2(): FOUND register+offset --> FAIL!

legitimate_address2(non-strict, soft-reg allowed), X=
(plus:HI (reg/f:HI 29 B13)
    (const_int -2 [0xfffffffffffffffe]))
legitimate_address2(): FOUND register+offset --> FAIL!

legitimate_address2(non-strict, soft-reg allowed), X=
(plus:HI (reg/f:HI 29 B13)
    (const_int -2 [0xfffffffffffffffe]))
legitimate_address2(): FOUND register+offset --> FAIL!


[and after four check of the add above, gcc 4.0.2 freaks out with ]

foobar8.c: In function ‘foobar’:
foobar8.c:7: internal compiler error: in change_address_1, at
emit-rtl.c:1800
Please submit a full bug report,

with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.


The failed assertion is in line 1800: some "addr" is not an address.

   1784 change_address_1 (rtx memref, enum machine_mode mode, rtx addr,
int validate)
   1785 {
   1786   rtx new;
   1787
   1788   gcc_assert (MEM_P (memref));
   1789   if (mode == VOIDmode)
   1790     mode = GET_MODE (memref);
   1791   if (addr == 0)
   1792     addr = XEXP (memref, 0);
   1793   if (mode == GET_MODE (memref) && addr == XEXP (memref, 0)
   1794       && (!validate || memory_address_p (mode, addr)))
   1795     return memref;
   1796
   1797   if (validate)
   1798     {
   1799       if (reload_in_progress || reload_completed)
   1800         gcc_assert (memory_address_p (mode, addr));
   1801       else
   1802         addr = memory_address (mode, addr);
   1803     }
   1804
   1805   if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE
(memref))
   1806     return memref;
   1807
   1808   new = gen_rtx_MEM (mode, addr);
   1809   MEM_COPY_ATTRIBUTES (new, memref);
   1810   return new;
   1811 }


Could it be the REG+OFF which the LEGITIMATE_ADDRESS() rejects above?

But then why all the others before it get re-written by a call to
LEGITIMIZE_ ADDRESS() ?!

What is calling change_address_1() at the end of the compilation phase?

Thanks

        Sergio

==========================================================================






Sergio Ruocco wrote:
> 
> 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
>>>
> 
> 

Reply via email to