Mohamed Shafi wrote: > Hello Omar, > > I saw your mail to gcc mailing list regarding splitting of HImode > patterns into QImode patterns. I am also involved in porting. My > problem is similar to yours. But i have to split SImode patterns into > HImode patterns. > > I am sure that you have modified your define_split patterns after > receiving the suggestions from the mailing list. Could you just mail > me the finalized define_split pattern of HImode. > > One thing that i noticed in your split pattern is that you are not > handling cases where operand[0] is memory, i.e store patterns. How > are you handling this? Do you have a define_insn for this case? > > I hope you don't mind me asking these questions. > > Thank you for your time. > > Regards, > Shafi > >
Hi Mohamed, I added the gcc mailing list to the threat. My current implementation looks like this: ;; movhi (define_expand "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" ""))] "" { if (c816_expand_move (HImode, operands)) { DONE; } }) ;; =&r creates an early clobber. ;; It prevent insn where the target register ;; is the same as the base register used for memory addressing... ;; This is needed so that the split produce correct code. (define_insn "*movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=&r,m") (match_operand:HI 1 "general_operand" "g,r"))] "" "#") (define_split [(set (match_operand:HI 0 "nonimmediate_operand" "") (match_operand:HI 1 "general_operand" ""))] "reload_completed" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] "{ gcc_assert (REG_P (operands[0]) || MEM_P (operands[0])); #ifdef DEBUG_OVERLAP if (reg_overlap_mentioned_p(operands[0], operands[1])){ fprintf (stderr, \"\nOperands Overlap:\n\"); debug_rtx (curr_insn); } #endif if (REG_P (operands[0])) { operands[2] = gen_highpart(QImode, operands[0]); operands[3] = gen_lowpart (QImode, operands[0]); } else if (MEM_P (operands[0])) { operands[2] = adjust_address (operands[0], QImode, 0); operands[3] = adjust_address (operands[0], QImode, 1); } if (MEM_P (operands[1])) {// || CONST == GET_CODE (operands[1])) { operands[4] = adjust_address (operands[1], QImode, 0); operands[5] = adjust_address (operands[1], QImode, 1); } else if (LABEL_REF == GET_CODE (operands[1]) || SYMBOL_REF == GET_CODE (operands[1])) {// operands[4] = simplify_gen_subreg(QImode, operands[1], HImode, 0); operands[5] = simplify_gen_subreg(QImode, operands[1], HImode, 1); } else if (CONST_INT == GET_CODE (operands[1]) || REG_P (operands[1])) { operands[4] = simplify_gen_subreg(QImode, operands[1], HImode, 0); operands[5] = simplify_gen_subreg(QImode, operands[1], HImode, 1); } else { error(\"Unrecognized code in operands[1]\"); fputs(\"\nrtx code is: \", stderr); debug_rtx(curr_insn); abort(); } }") The purpose of the expand is to load Label or Symbol references into base registers for index addressing. I decided to use the expand since the force_reg() was failing when I called from the split. The c816_expand_move() is implemented as follows: bool c816_expand_move (enum machine_mode mode, rtx *operands) { if (!no_new_pseudos) { int i; for (i = 0; i < 2; i++) { if (MEM_P (operands[i]) || CONST == GET_CODE (operands[i])) { rtx base = XEXP (operands[i],0); if (CONST == GET_CODE(base)) { base = XEXP (base,0); } if (PLUS == GET_CODE (base)) { rtx off = XEXP (base,1); base = XEXP (base,0); if (SYMBOL_REF == GET_CODE (base) || LABEL_REF == GET_CODE (base)) { rtx newreg = force_reg (Pmode, base); operands[i] = gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, newreg, off)); } } else if (SYMBOL_REF == GET_CODE (base) || LABEL_REF == GET_CODE(base)) { rtx newreg = force_reg (Pmode, base); operands[i] = gen_rtx_MEM (mode, newreg); } }// if MEM_P }// for }// if !no_new_pseudos return false; } In your case, you might want to look at other gcc ports for 16-bit machines. One I have look from time to time is the MSP430 port (http://mspgcc.sourceforge.net/). Hope this helps. Good Luck, -Omar