Re: porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
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 : >> 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 ?!
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 : > 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 ?!
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 ?!
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 ?!
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
porting GCC to a micro with a very limited addressing mode --- what to write in LEGITIMATE_ADDRESS, LEGITIMIZE_ADDRESS and micro.md ?!
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]); }