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]); }
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 ?!
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 --- success with LEGITIMATE / LEGITIMIZE_ADDRESS, stuck with ICE !
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 : >>> Gabriel Paubert wrote: >>>> On Mon, Jan 25, 2010 at 01:34:09PM +0100, Sergio Ruocco wrote: >>>>> Hi everyone, >>>>> >>>>>
Re: porting GCC to a micro with a very limited addressing mode --- enforcing a 'register indirect memory operand' through a constraint in md
Thanks Micheal for your code, I will try it... however, I think the problem that crashes my compiler may not lie in my LEGITIMATE/LEGITIMIZE ADDRESS macros, which are equivalent to many others (yours included), but in the GCC which - in some corner cases - does not like being told that an register+offset is an invalid address. While investigating this hypothesis, I found this tutorial http://spindazzle.org/ggx/ which discusses a GCC port with the same constraints I am battling with, but solved in a different way. In this port, the register indirect addressing is enforced through a custom constraint in the MD (details below). What do you think of this approach? Sergio (from the patch to the MD) - ;; Constraints ;; - (define_constraint "W" "A register indirect memory operand." (and (match_code "mem") (match_test "REG_P (XEXP (op, 0)) && REGNO_OK_FOR_BASE_P (REGNO (XEXP (op, 0)))"))) which is then specified by the define_insn (define_insn "*movsi" [(set (match_operand:SI 0 "general_operand" "=r,r,W,m,r,r") (match_operand:SI 1 "ggx_general_movsrc_operand" "r,i,r,r,W,m"))] "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" "@ mov%0, %1 ldi.l %0, %1 st.l %0, %1 sta.l %0, %1 ld.l %0, %1 lda.l %0, %1") http://spindazzle.org/ggx/gcc/add-load-store.patch.txt The GO_IF_LEGITIMATE_ADDRESS() macro is plain and simple: /* A C compound statement with a conditional `goto LABEL;' executed if X (an RTX) is a legitimate memory address on the target machine for a memory operand of mode MODE. */ #define GO_IF_LEGITIMATE_ADDRESS(MODE,X,LABEL) \ do { \ if (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) \ goto LABEL; \ if (GET_CODE (X) == SYMBOL_REF \ || GET_CODE (X) == LABEL_REF\ || GET_CODE (X) == CONST) \ goto LABEL; \ } while (0) http://spindazzle.org/ggx/gcc/add-ggx-config.patch.txt Michael Hope wrote: > Hi Sergio. Here's the interesting parts from my port. The code's a > bit funny looking as I've edited it for this post. > > In .h: > > #define BASE_REG_CLASS ADDR_REGS > #define INDEX_REG_CLASS NO_REGS > > #ifdef REG_OK_STRICT > # define _REG_OK_STRICT 1 > #else > # define _REG_OK_STRICT 0 > #endif > > #define REGNO_OK_FOR_BASE_P(r) _regno_ok_for_base_p(r, > _REG_OK_STRICT) > #define REGNO_OK_FOR_INDEX_P(r) 0 > > In .c: > > static bool > _reg_ok(rtx reg, bool strict) > { > int regno = REGNO(reg); > > bool is_addr = _is_addr_regno(regno); > bool ok_strict = is_addr; > bool special = regno == ARG_POINTER_REGNUM > || regno == TREG_S > ; > > if (strict) > { > return ok_strict || special; > } > else > { > return ok_strict || special > || regno >= FIRST_PSEUDO_REGISTER > ; > } > } > > bool > _legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, >rtx x, >bool strict_checking) > { > /* (mem reg) */ > if (REG_P (x) > && _reg_ok (x, strict_checking) > ) > { > return 1; > } > > return 0; > } > > Note that this ISA only has indirect addressing and has no indirect + > offset or indirect + register modes. GCC > handles this just fine by splitting up any other type that fails > legitimate_address into smaller components. > > -- Michael > > On 10 February 2010 09:02, Sergio Ruocco wrote: >> 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(): >> -
Re: porting GCC to a micro with a very limited addressing mode --- enforcing a 'register indirect memory operand' through a constraint in md
I found the source of my problems! The prologue()/epilogue() functions (*) I took from the tutorial written for SPIM/MIPS emit a number of move insn to/from "invalid" memory addresses (reg+off) that do not go through LEGITIMIZE_ADDRESS(), and this freaks out GCC, so I have to rewrite these in some ways... It seems that prologue()/epilogue() are called quite late in the compiling process, thus new registers cannot be created (no_new_pseudos assert fires) and/or emit_move_insn() does not go through LEGITIMIZE_ADDRESS()... will work on this tomorrow... Thanks for the support so far! Sergio (*) void spim_prologue(void) { int i,j; emit_move_insn(gen_rtx_MEM(HImode,plus_constant(stack_pointer_rtx,0)),return_addr_rtx); emit_move_insn(gen_rtx_MEM(HImode,plus_constant(stack_pointer_rtx,-2)),stack_pointer_rtx); emit_move_insn(gen_rtx_MEM(HImode,plus_constant(stack_pointer_rtx,-4)),hard_frame_pointer_rtx); ... } Sergio Ruocco wrote: > > Thanks Micheal for your code, I will try it... however, I think the > problem that crashes my compiler may not lie in my LEGITIMATE/LEGITIMIZE > ADDRESS macros, which are equivalent to many others (yours included), > but in the GCC which - in some corner cases - does not like being told > that an register+offset is an invalid address. > > While investigating this hypothesis, I found this tutorial > > http://spindazzle.org/ggx/ > > which discusses a GCC port with the same constraints I am battling with, > but solved in a different way. > > In this port, the register indirect addressing is enforced through a > custom constraint in the MD (details below). > > What do you think of this approach? > > Sergio > > (from the patch to the MD) > > - > ;; Constraints > ;; - > (define_constraint "W" > "A register indirect memory operand." > (and (match_code "mem") >(match_test "REG_P (XEXP (op, 0)) > && REGNO_OK_FOR_BASE_P (REGNO (XEXP (op, 0)))"))) > > > which is then specified by the define_insn > > (define_insn "*movsi" >[(set (match_operand:SI 0 "general_operand" "=r,r,W,m,r,r") > (match_operand:SI 1 "ggx_general_movsrc_operand" "r,i,r,r,W,m"))] >"register_operand (operands[0], SImode) > || register_operand (operands[1], SImode)" >"@ > mov%0, %1 > ldi.l %0, %1 > st.l %0, %1 > sta.l %0, %1 > ld.l %0, %1 > lda.l %0, %1") > > http://spindazzle.org/ggx/gcc/add-load-store.patch.txt > > > The GO_IF_LEGITIMATE_ADDRESS() macro is plain and simple: > > /* A C compound statement with a conditional `goto LABEL;' executed >if X (an RTX) is a legitimate memory address on the target machine >for a memory operand of mode MODE. */ > #define GO_IF_LEGITIMATE_ADDRESS(MODE,X,LABEL)\ > do { \ > if (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) \ > goto LABEL; \ > if (GET_CODE (X) == SYMBOL_REF\ > || GET_CODE (X) == LABEL_REF\ > || GET_CODE (X) == CONST) \ > goto LABEL; \ > } while (0) > > http://spindazzle.org/ggx/gcc/add-ggx-config.patch.txt > > > > > Michael Hope wrote: >> Hi Sergio. Here's the interesting parts from my port. The code's a >> bit funny looking as I've edited it for this post. >> >> In .h: >> >> #define BASE_REG_CLASS ADDR_REGS >> #define INDEX_REG_CLASS NO_REGS >> >> #ifdef REG_OK_STRICT >> # define _REG_OK_STRICT 1 >> #else >> # define _REG_OK_STRICT 0 >> #endif >> >> #define REGNO_OK_FOR_BASE_P(r) _regno_ok_for_base_p(r, >> _REG_OK_STRICT) >> #define REGNO_OK_FOR_INDEX_P(r) 0 >> >> In .c: >> >> static bool >> _reg_ok(rtx reg, bool strict) >> { >> int regno = REGNO(reg); >> >> bool is_addr = _is_addr_regno(regno); >> bool ok_strict = is_addr; >> bool special = regno == ARG_POINTER_REGNUM >> || regno == TREG_S >> ; >> >> if (strict) >> { >> return ok_strict || special; >> } >> else >> { >> return ok_strict || special >> || regno >= FIRST_PSEUDO_REGISTER >> ; >> } >> } >> >&g
Re: GCC porting tutorials
Hi Radu, Check both the GCC Wiki and the work done at IIT Bombay: http://www.cse.iitb.ac.in/grc/reach.html Activities->Workshops They developed some tutorials on porting GCC and writing new backends, such as: http://www.cse.iitb.ac.in/grc/gcc-workshop-09/ http://www.cse.iitb.ac.in/~uday/gcc-mini-workshop/ On 24 April 2010 10:53, Radu Hobincu wrote: > Hello, > > My name is Radu Hobincu, I am part of a team at "Politehnica" University > of Bucharest that is developing a massive parallel computing architecture > and currently my job is to port the GCC compiler to this new machine. > > I've been looking over the GCC official site at http://gcc.gnu.org/ but I > couldn't find an official porting tutorial. Is there such a thing? And > maybe a small example for a lightweight architecture? > > Regards, > Radu >
Trouble with MDs: "const" RTL object stops recognition of RTL expressions by insn patterns
Dear All, I am porting GCC to a 16 bit micro (with 16 bit bytes, thus BITS_PER_UNIT=16, 16 bit ints become "QI"s etc). The port compiles is nearly done and simple C programs, but now chokes on a trivial line such as: yyy(&array[4], &e, &p); with this error: xxx.c: In function ‘yyy’: xxx.c:193: error: unrecognizable insn: (insn 183 181 184 4 (set (reg/f:QI 37 [ D.1127 ]) (const:QI (plus:QI (symbol_ref:QI ("digest") [flags 0x2] ) (const_int 8 [0x8] -1 (nil) (nil)) sha1_16_struct2.c:193: internal compiler error: in extract_insn, at recog.c:2020 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html> for instructions. I determined that the problem is triggered by the computation of array address+const (4/8 in this case). My MD contains: (define_insn "addqi3" [(set (match_operand:QI 0 "register_operand" "=r,r") (plus:QI (match_operand:QI 1 "register_operand" "0,0") (match_operand:QI 2 "nonmemory_operand" "r,K")) )] "" "@ ADD \\t%2 %0 ADDI \\t%h2 %0" ) which correctly compiles ordinary arithmetic expressions: x = 5+y etc. However, when a symbol is involved, the addqi3 isns pattern cannot recognise the RTL: Symbol+Int. Is maybe the surrounding (const:QI...) the reason why addqi3 does not match?! Grepping the GCC source I found in rtl.h that CONST is defined as: /* This is used to encapsulate an expression whose value is constant (such as the sum of a SYMBOL_REF and a CONST_INT) so that it will be recognized as a constant operand rather than by arithmetic instructions. */ DEF_RTL_EXPR(CONST, "const", "e", RTX_CONST_OBJ) So, what is my port missing to make it compile such RTL expressions? I feel that it must be something really trivial which I am overlooking.. Thanks for your help, Sergio