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"
)
-------------------------------




Reply via email to