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 <[email protected]>:
>>> 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
>>>
>
>