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